Topic was automatically imported from the old Question2Answer platform.
Asked By
Pluto1
Hi, I’m trying to make mobs follow my player. I used a tutorial, but it is not working correctly for my code. The mobs all go to where the player start position is and pile up on eachother - do I have to instance the player instead or something? - I thought the tutorial I looked at didn’t do that. Here is the code for my mob (named jelly):
extends KinematicBody2D
signal jelly_dead
var backcount = 1
var player = preload("res://player.tscn").instance()
# Node references
# Random number generator
var rng = RandomNumberGenerator.new()
# Movement variables
export var speed = 50
var direction : Vector2
var last_direction = Vector2(0, 1)
var bounce_countdown = 0
func _ready():
rng.randomize()
$AnimatedSprite.play()
func _process(delta):
pass
func _physics_process(delta):
var movement = direction * speed * delta
var collision = move_and_collide(movement)
if collision != null and collision.collider.name != "player":
direction = direction.rotated(rng.randf_range(PI/4, PI/2))
bounce_countdown = rng.randi_range(2, 5)
func _on_Timer_timeout():
# Calculate the position of the player relative to the mob
var player_relative_position = player.position - position
if player_relative_position.length() <= 16:
# If player is near, don't move but turn toward it
direction = Vector2.ZERO
last_direction = player_relative_position.normalized()
elif player_relative_position.length() <= 200 and bounce_countdown == 0:
# If player is within range, move toward it
direction = player_relative_position.normalized()
elif bounce_countdown == 0:
# If player is too far, randomly decide whether to stand still or where to move
var random_number = rng.randf()
if random_number < 0.03:
direction = Vector2.ZERO
elif random_number < 0.1:
direction = Vector2.DOWN.rotated(rng.randf() * 2 * PI)
# Update bounce countdown
if bounce_countdown > 0:
bounce_countdown = bounce_countdown - 1
As you suggested, I think your problem is that your player variable points to the definition of the player scene not the actual instance of that scene in your world.
You need your player variable to be a reference to the player object when that has been instantiated in the world (in the scene tree).
One way to do it is to
at the top of your script, change your definition of the player variable to simply declare the player variable (null), not define it (because it won’t be instantiated until the node tree is created in game)
var player : Object = null
in your _ready function you can set _player (it will have been instantiated at this point)
player = $“/root/World/player” [I do not know how you have setup the player in your node tree, so change this to the path to your player kinematic_body
Hard-coding a nodepath like this is fragile since you will need to update that it if you change where you player is in the tree. So you will probably want a more reliable method to figure out where the player object is in the tree. Documentation for other approaches is here
Fixed! Thank you for highlighting the issue for me. Looks like I didn’t follow the tutorial correctly (I’m only using it as a reference). I’m new to this and I think my biggest issue was understanding the what and why of the “root” node. I think I understand now though, it’s just root by default always for your selected scene? Ah I guess, I’ll read up on it.
Pluto1 | 2020-11-12 04:34
Hi, Yes - the top node will always be root. So, when you look at the node tree in the GUI, you are seeing what comes after root (root is hidden)
AndyCampbell | 2020-11-12 13:52
Follow up question, in case you know whats going on:
I fixed the above problem but the instanced mobs still also don’t detect collisions with the player, however the mob that is not instanced (placed in the scene editor) does. Why would that be?
EDIT: Looks like it only works if I configure that layer/mask of the player both to 1, along with the mob, for some reason it doesn’t work if they have a layer/mask of something different from 1 even if everything is correct.
Pluto1 | 2020-11-13 17:37
Hi, Yes - for collision detection to work they Mobs and Player need to share a common collision layer.
Are you changing the collision layer when you add the Player or Mob in the editor? If you are, you would need to ensure that mobs instanced in your script share a collision layer.