Godot 3 to 4 rename

VisibilityNotifier3D in Godot 4: it is VisibleOnScreenNotifier3D now

VisibilityNotifier3D is VisibleOnScreenNotifier3D in Godot 4.7.2, and the editor's parse error names it. Its screen_entered and screen_exited signals keep their names; connect them through the signal itself, notifier.screen_entered.connect(...).

What Godot prints

A Node3D that adds a VisibilityNotifier3D and connects its screen_entered signal the Godot 3 way.

repro.gd
extends Node3D

func _ready():
	var notifier = VisibilityNotifier3D.new()
	notifier.connect("screen_entered", self, "_on_screen_entered")
	add_child(notifier)

func _on_screen_entered():
	print("on screen")
Output, Godot 4.7.2
Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

SCRIPT ERROR: Parse Error: Identifier "VisibilityNotifier3D" not declared in the current scope. Did you mean to use "VisibleOnScreenNotifier3D"?
   at: GDScript::reload (res://answers/visibilitynotifier3d-in-godot-4/repro.gd:4)
ERROR: Failed to load script "res://answers/visibilitynotifier3d-in-godot-4/repro.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript_resource_format.cpp:46)

The fix

The same notifier as VisibleOnScreenNotifier3D, its signals connected through the Signal objects. The fix prints the class and its default box.

fix.gd
extends Node3D

func _ready() -> void:
	var notifier := VisibleOnScreenNotifier3D.new()
	notifier.screen_entered.connect(_on_screen_entered)
	notifier.screen_exited.connect(_on_screen_exited)
	add_child(notifier)
	print(notifier.get_class(), " aabb: ", notifier.aabb)

func _on_screen_entered() -> void:
	print("on screen")

func _on_screen_exited() -> void:
	print("off screen")
Output, Godot 4.7.2
Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

VisibleOnScreenNotifier3D aabb: [P: (-1.0, -1.0, -1.0), S: (2.0, 2.0, 2.0)]

Why it happens

GDScript's analyzer resolves every identifier when the script loads. VisibilityNotifier3D is not a class in Godot 4.7.2, so the script fails to parse and Godot does not load it. The editor build adds the new name from Godot's 3 to 4 rename table: Did you mean to use "VisibleOnScreenNotifier3D"?

The table maps both VisibilityNotifier, the 3D node's Godot 3 name, and VisibilityNotifier3D to VisibleOnScreenNotifier3D, and VisibilityNotifier2D to VisibleOnScreenNotifier2D.

Godot 3.6's VisibilityNotifier also had camera_entered and camera_exited signals and a max_distance property. VisibleOnScreenNotifier3D has screen_entered, screen_exited and its bounding box, aabb, which the fix printed at its default: a 2 by 2 by 2 box centred on the node.

Object.connect() in Godot 4 takes the signal's name and a Callable, not a target object and a method name, so the Godot 3 call connect("screen_entered", self, "_on_screen_entered") does not carry over as written. The fix connects through the Signal object instead.

Sources

Run on Godot 4.7.2, .

Related