Move_and_slide does not work until something collides with it

Godot Version

Godot 4.2.1

Question

I am trying to make a character3D move forward using move_and_slide after the player finishes some dialog, but for some reason the character is not moving unless I collide with them. Why is this and how do I get rid of it? I would like to know what is causing this and how I can fix it. Here is the code for the Character3D, let me know if you want to see anything else.

extends CharacterBody3D
@onready var raycast = $Body/Torso/Shoulder/Leftarm/Blasterbmesh/RayCast3D
@onready var blaster = $Body/Torso/Shoulder/Leftarm/Blasterbmesh
@export var coordmod = Vector3(0,0.0,0)
@onready var cooldown = $Timer
@export var target: Node3D
var going = false
const SPEED = 5.0
const JUMP_VELOCITY = 4.5

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")


func _physics_process(delta):
	
	move_and_slide()
	
	if going:
		velocity = Vector3(0,-0.1,200)
	if self.position.z > 4:
		velocity = Vector3(0,-0.1,0)
		going = false
				


	# Handle jump.
	

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	#var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	#var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	#if direction:
	#	velocity.x = direction.x * SPEED
	#	velocity.z = direction.z * SPEED
	#else:
	#	velocity.x = move_toward(velocity.x, 0, SPEED)
	#	velocity.z = move_toward(velocity.z, 0, SPEED)

	#move_and_slide()
func _ready():
	$AnimationPlayer.play("sit")
	
func damage(_amount,notself):
	pass


func _on_enemyflying_specialtrigger():
	$AnimationPlayer.play("RESET")
	$"../HUD/DialogueBox".visible = true
	$"../HUD/DialogueBox".start("0")
	
func _process(delta):
	if $AnimationPlayer.get_current_animation_position() > 0.9 and $AnimationPlayer.get_current_animation_position() < 1.5:
		if target != null and blaster != null and cooldown.is_stopped():
			blaster.look_at(target.position, Vector3(-2.1,0.3,0),true)
			
			if raycast.is_colliding(): 
			
				var collider = raycast.get_collider()
				blaster.position += Vector3(0,0,-0.05)
				await get_tree().create_timer(0.1).timeout
				blaster.position -= Vector3(0,0,-0.05)
			# Hitting an enemy
				if collider != null:
					if collider.has_method("damage"):
						cooldown.start()
						collider.damage(0.1,self)
					
			
			# Creating an impact animation
			
				var impact = preload("res://objects/impact.tscn")
				var impact_instance = impact.instantiate()
			
				impact_instance.play("shot")
			
				get_tree().root.add_child(impact_instance)
			
				impact_instance.position = raycast.get_collision_point() + (raycast.get_collision_normal() / 10)

func _on_dialogue_box_dialogue_ended():
	self.rotate_y(-1.5708)
	going = true
	velocity = Vector3(0,-0.1,10)

Have you tried setting can_sleep to false?
Thats it for wme most of the time.
Good Luck!

I’ll try that

Character3D does not have a can_sleep property, thats only for rigid bodies, and my character is not one of them.

Try putting a print statement in the _on_dialogue_box_dialogue_ended function to verify that it’s being called correctly. It’s the only place where going is set to true, so my guess is that there’s a signal somewhere that isn’t connected to that function quite right.

Otherwise, make sure your character’s z position is < 4, since it will stop moving as soon as it passes that threshold. You’re using local position here, not global position, so depending on what’s a parent of what, the position might be something unexpected. Try printing position.z in _physics_process to make sure.

I have checked to make sure on_dialogue_box is running and I’ve checked out the z-position thing. My problem is that when I set the velocity, nothing happens, but if I then collide with the object it will start moving.

I noticed you’re playing an animation in the _ready() function, would that animation happen to set the position of your character? Maybe that’s overwriting it?

Is _on_enemyflying_specialtrigger being called when something collides with your character? if so, the animationplayer playing the “RESET” animation could be the reason why it starts working then.

So use a Rigidbody with the mode set to character maybe?

special trigger is what causes a dialog box to open, and then when it closes I want the character to walk away. I do not have any collision detection code set up for this NPC aside from the basic collision that comes with character3d.

Try commenting out your ready function just to see if it works without it.

I have no clue what you are trying to say here. Rigidbody3d doesn’t even have a mode selection.

I’ll try that. Hold on for a second while I open the project.

Nope, I am still getting the same strange behavior were it does not move until it detects a collision.

When does _on_enemyflying_specialtrigger get called?

When an enemy that the NPC is meant to thank you for killing is defeated.

Ok so that’s when it’s supposed to start moving?

No, they are supposed to start moving after the player finishes reading the dialog and closes it.

Right, ok. It seems like even when going is true, velocity is immediately being overwritten every frame. What kind of movement do you get when you bump it? is it the correct movement?

Yes. When I bump it everything starts working perfectly.

The npc isn’t stuck in the ground right? If you don’t have any other collision detection code, maybe the bump is just enough to knock it free if it’s stuck?

Edit: Just the collisionshape I mean

1 Like