Strange bug with instanced kinematic bodies

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By da_dev

So, I’ve been working on a stategy game and I ran into a problem: my kinematic body Soldier is instanced, when I init the instance in _ready() function like this:

const Soldier = preload("res://Scenes/Soldier.tscn")
...
_ready():
   var soldier = Soldier.instance()
   add_child(soldier)

it works perfectly fine and moves as it should.
Here’s a movement script btw:

if Input.is_action_just_pressed("click"):
	firstMove = true #make sure that correct animation is playing
	target = get_global_mouse_position() #script here is combination of my work and Godot docs page
	trans = Vector2(target.x - position.x, target.y - position.y).normalized() * speed
	rotation = trans.angle() + deg2rad(90)
	
if (target - position).length() > 5 && firstMove == true:
	move_and_slide(trans)
	legs.animation = "walk"
else:
	legs.animation = "idle"

I also have a script that duplicates soldier. It’s attached to the root node:

if Input.is_action_pressed("duplicate"): #that means pressing D
	var soldier = Soldier.instance()
	add_child(soldier)

The thing is the initial soldier walks as it should, but duplicated teleport around like crazy. Here’s the video on Imgur

Coding Tips: Instead of writing

trans = Vector2(target.x - position.x, target.y - position.y).normalized() * speed

write

var to_target = target - position
trans = to_target.normalized() * speed

then in your if statement you can use it again:

if to_target.length() > 5 && firstMove:

Don’t write firstMove == true just firstMove or not firstMove for firstMove == false.

Dlean Jeans | 2019-06-10 07:51

:bust_in_silhouette: Reply From: Dlean Jeans

Likely it’s because you’re creating a new soldier every frame you’re pressing duplicate with Input.is_action_pressed. This causes those newly created soldiers to collide and “teleport” like that.

Solution: Use Input.is_action_just_pressed:

if Input.is_action_just_pressed("duplicate"):
    var soldier = Soldier.instance()
    add_child(soldier)

This will only create a new soldier only once every you press duplicate instead of every frame.

Thank you very much!!!

da_dev | 2019-06-10 11:08