Smooth steering for an ai, tank controls kinda

4.3.stable.official

Sorry for spamming the forum, i’ll make this post as detailed as possible.
I’m trying to give an npc movement thats smarter than what you get out of navigationagent3D, eventually my goal is to implement context based steering. But before that, i have to make it steer in general, and for some reason i just cant seem to find the answer despite staring at the documentation and searching online.
What i need is for my script to 1. compare the direction it’s facing with another target position, and 2. if it’s not facing towards the target position, gradually turn towards it with a variable speed, steering. This is important for the context based steering later on. i dont want to just set the rotation so it snaps, and i dont want to move in the direction of the target position, i want to turn in the direction of the target position.

Extra context: What i can do is make my guy move forward, i can get the global vector3 of the target position and i can use look_at to make him snap towards the target position. What i cant do is the gradual turn, or limit the movement to x and z axis only.

Could you check if tank is facing target, if not then move tank forward in direction he is facing while rotating until he is facing target.

Sorry on phone can’t easily write sudo code at the moment. Also, not the most familiar with 3D.

You would have to figure out speed you want for his rotation. But if his facing direction is constantly being updated by rotating and you move him in facing direction it should theoretically work.

Rather than moving him to the target position you move him forward and rotate him towards target position, then once he is facing that position it is just a matter of driving.

extends CharacterBody3D

@export var turn_speed: float = 2.0  # Radians per second
@export var forward_speed: float = 5.0

# Called every physics frame
func _physics_process(delta: float) -> void:
    # Get the target position (replace this with your actual target)
    var target_pos = Vector3(10, 0, 10)  # Example target
    
    # Get current forward direction (assuming character faces -Z)
    var current_direction = -global_transform.basis.z
    
    # Get direction to target (ignoring Y axis)
    var to_target = target_pos - global_position
    to_target.y = 0  # Ignore height difference
    
    if to_target.length() > 0.1:  # Only rotate if we're not too close
        # Calculate the angle difference
        var target_direction = to_target.normalized()
        
        # Get the angle between current direction and target direction
        var angle_to_target = current_direction.signed_angle_to(target_direction, Vector3.UP)
        
        # Calculate rotation step for this frame
        var turn_step = turn_speed * delta
        
        # Clamp the rotation to be no more than what we need
        turn_step = min(abs(angle_to_target), turn_step) * sign(angle_to_target)
        
        # Apply the rotation
        rotate_y(turn_step)
        
        # Move forward
        var velocity = -global_transform.basis.z * forward_speed
        velocity.y = 0  # Keep Y velocity unchanged
        set_velocity(velocity)
        move_and_slide()

# Optional debug visualization
func _draw() -> void:
    # If you want to visualize the turning, you can add debug lines here
    pass

this works like a charm, thank you so much!

1 Like

this was what i ended up doing, i just didnt have the gdscript knowledge to achieve it. thanks for the help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.