I have some platformer code to make my character jump based on height. I'd like to be able to tune it in the editor using both world units or number of tiles. I can do this with setters:
extends CharacterBody2D
const TILE_SIZE := 16.0
@export_group("Jump Movement")
## Height in world units.
@export_range(1, 160) var jump_height: float = TILE_SIZE * 4
## Height in tile count.
@export_range(1, 10, 0.25) var jump_tiles: float = 4:
get:
return jump_height / TILE_SIZE
set(value):
jump_height = value * TILE_SIZE
@export var jump_speed: float:
get:
return calc_jump_speed()
@export_range(0, 9999) var gravity: float = 3840
func calc_jump_speed():
return -sqrt(2 * gravity * jump_height)
func _physics_process(dt: float) -> void:
velocity.y += gravity * dt
if Input.is_action_just_pressed("jump0"):
velocity.y = calc_jump_speed()
move_and_slide()
However, the editor doesn't display updated values when I change them: setting jump_tiles
to 1 should change jump_height
to 16 but it stays at 64 and jump_speed
is always 0. If I change jump_height
to 128, my character jumps higher but no values change. The underlying values do change -- my character only jumps 1 tile. And when viewing the player in Remote scene tab, the values all update. But when I save the file, it stores the values seen in the Local inspector and only if they're modified:
[node name="Node2D" type="CharacterBody2D" parent="."]
position = Vector2(-71, 376.054)
collision_mask = 15
script = ExtResource("10_ob28b")
jump_height = 128.0
jump_tiles = 1.0
If I restart the editor, it uses my jump_tiles
value and not jump_height
. It seems that the values are applied in the order they appear in script and loading jump_tiles
from the tscn executes the setter which overrides the jump_height
value from the tscn.
I can add @tool
to the top of the script and then the values change, but then my character is difficult to work with: they fall due to gravity and walk away from their spawn point in the editor scene while I'm testing.
The Running code in the editor docs say you can use not Engine.is_editor_hint()
to skip any code that shouldn't run in editor (like applying gravity), but also has a big red warning about how you might crash the editor.
So how can I add derived inspector values without making my whole script affected by @tool
?