Godot Version
4.1
Question
the function run_away()
in ghost_body.run_away()
gives me an error:
“Invalid call. Nonexistent function ‘run_away’ in base ‘Nil’.”
i dont know if i forgot something or not, is there a way to fix this?
4.1
the function run_away()
in ghost_body.run_away()
gives me an error:
“Invalid call. Nonexistent function ‘run_away’ in base ‘Nil’.”
i dont know if i forgot something or not, is there a way to fix this?
ghost_body
does not have a valid reference.
but it does:
@onready var ghost_body = $theghost as BodySprite
is this actually valid though?
I’m not familiar with the as BodySprite
syntax for @onready, but I have seen Godot silently fail on some incompatible assignments. Have you checked to see if ghost_body has a value after this assignment?
i checked and i dont think it has a value after it
btw BodySprite
is a class
so is there a solution to this?
Its likely your path to the node (or spelling) is wrong.
Drag the node from the scene tree into your code page and press ctrl and drop the node.
This will give you the correct path to it. You can then add the type as BodySprite
.
Here’s a better way:
Public variables, example:
@export var ghost_body:Node
Set up nodes in Inspector and save the scene
Try removing as BodySprite
, and see if ghost_body
has a value.
according to the tutorial im using, it isnt the wrong one but ill use the actual name anyway, still didnt work
also tried removing as BodySprite
, ghost_body seems to have a value
i also putted @export var ghost_body:Node
, but they all still got the same error
Post more of the code please
ok
func run_away_from_pacman():
if run_away_timer.is_stopped():
theghost.run_away()
run_away_timer.start()
current_state = GhostState.RUN_AWAY
# stop timers
update_chasing_target_position_timer.stop()
scatter_timer.stop()
var empty_cell_position = tile_map.get_random_empty_cell_position()
navigation_area_2d.target_position = empty_cell_position
I think the issue is in your BodySprite class. I think either you don’t have a class_name BodySprite
in your code, or you didn’t change the class type to BodySprite
in the scene tab:
class_name BodySprite
is in another gd file, and i didnt change the name though
but i tried to replace theghost
in theghost.run_away()
with bodysprite
and it gives me an error saying “Identifier “bodysprite” not declared in the current scope.” (before that i tried adding the bodysprite class name in the bottom of another class name but it says that class name should only be used once so i erased it)
EDIT: fixed the bottom problem
Post the complete script file that has the error in it and the file where you define the BodySprite
class.
A screenshot of your Scene Tree for both would be good as well.
Otherwise it’s just guessing what’s wrong with your code and no one can properly help you. Complete context for resolving errors is important.
the script that has the error in it:
extends Area2D
class_name Ghost
enum GhostState {
SCATTER,
CHASE,
RUN_AWAY
}
signal direction_change(current_direction: String)
var current_scatter_index = 0
var direction = null
var current_state: GhostState
@export var speed = 65
@export var movement_targets: Resource
@export var tile_map: MazeTileMap
@export var image: CompressedTexture2D
@export var chasing_target: Node2D
@onready var update_chasing_target_position_timer = $updateChasingTargetPositionTimer
@export var bodysprite:Area2D
@onready var navigation_area_2d = $NavigationAgent2D
@onready var scatter_timer = $scatterTimer
@onready var run_away_timer = $runAwayTimer
func _ready():
navigation_area_2d.path_desired_distance = 4.0
navigation_area_2d.target_desired_distance = 4.0
navigation_area_2d.target_reached.connect(on_position_reached)
call_deferred("setup")
func _process(delta):
move_ghost(navigation_area_2d.get_next_path_position(), delta)
func move_ghost(next_position: Vector2, delta: float):
var current_ghost_position = global_position
var new_velocity = (next_position - current_ghost_position).normalized() * speed * delta
caculate_direction(new_velocity)
position += new_velocity
func caculate_direction(new_velocity: Vector2):
var current_direction
if new_velocity.x > 1:
current_direction = "right"
elif new_velocity.x < -1:
current_direction = "left"
elif new_velocity.y > 1:
current_direction = "up"
elif new_velocity.y < -1:
current_direction = "down"
if current_direction != direction:
direction = current_direction
direction_change.emit(direction)
func setup():
print(tile_map.get_navigation_map(0))
navigation_area_2d.set_navigation_map(tile_map.get_navigation_map(0))
NavigationServer2D.agent_set_map(navigation_area_2d.get_rid(), tile_map.get_navigation_map(0))
scatter()
func scatter():
scatter_timer.start()
current_state = GhostState.SCATTER
navigation_area_2d.target_position = movement_targets.scatter_targets[current_scatter_index].position
func on_position_reached():
if current_state == GhostState.SCATTER:
scatter_position_reached()
speed = 65
elif current_state == GhostState.CHASE:
chase_position_reached()
elif current_state == GhostState.RUN_AWAY:
run_away_from_pacman()
func chase_position_reached():
print("kill pacman")
func scatter_position_reached():
if current_scatter_index < 3:
current_scatter_index += 1
else:
current_scatter_index = 0
navigation_area_2d.target_position = movement_targets.scatter_targets[current_scatter_index].position
func _on_scatter_timer_timeout():
starting_chasing_pacman()
func starting_chasing_pacman():
if chasing_target == null:
print("no chasing target, chasing wont work obviously lol")
current_state = GhostState.CHASE
update_chasing_target_position_timer.start()
navigation_area_2d.target_position = chasing_target.position
func _on_update_chasing_target_position_timer_timeout():
navigation_area_2d.target_position = chasing_target.position
func run_away_from_pacman():
if run_away_timer.is_stopped():
bodysprite
run_away_timer.start()
current_state = GhostState.RUN_AWAY
# stop timers
update_chasing_target_position_timer.stop()
scatter_timer.stop()
var empty_cell_position = tile_map.get_random_empty_cell_position()
navigation_area_2d.target_position = empty_cell_position
func _on_run_away_timer_timeout():
starting_chasing_pacman()
the script that defines the BodySprite
class:
extends Sprite2D
class_name BodySprite
@onready var animation_player = $"../AnimationPlayer"
func _ready():
self.texture = (get_parent() as Ghost).image
animation_player.play("ghost_moving")
func run_away():
animation_player.play("thetwostates")
animation_player.play("frightened_moving")
the scene tree (note that its the character scene, not the main one):
waiting for a reply
In your first post you said this line defined ghost_body.
@onready var ghost_body = $theghost as BodySprite
This is not in any of the code you posted.
Did you change it to this:?
@export var bodysprite:Area2D
If so, you will need to provide a value for that export in the editor.
i tried to replace theghost in theghost.run_away() with bodysprite
I think you are really getting things mixed up here.
When you add “as BodySprite” you force the variable ghost_body
to become a BodySprite object. So you don’t replace ghost_body with bodysprite that will only confuse the issue.
At this point it might be helpful to link the tutorial you are following.
yeah i changed it to @export var bodysprite:Area2D
since someone suggested it
btw heres the tutorial im following:
Is the script of theghost node different from the BodySprite class?