Search code examples
godotgodot4

How can I rotate a 2D Arrow to face a 3D Objects position?


Explanation: I am trying to create a damage indicator like in call of duty where if you get hit a arrow in the middle of the screen rotates towards the target.

Issue: So the current issue I am experiencing is offsetting the damage indicator, facing forward (-Z axis) the indicator seems to work correctly, I go left and right and the indicator rotates correctly, now if I the player rotates the offset gets ruined and it "seems" to be off by 90 degrees.

code:

func _physics_process(delta):
    if target_position == Vector3.ZERO: return
    
    rotate_to_target(target_position)

func set_target(target : Vector3) -> void:
    target_position = target

func rotate_to_target(target : Vector3) -> void:
    var player_position = PlayerProperties.player.global_position
    # Get the direction for the rotation
    var direction = (player_position - target).normalized()
    
    # Get the players rotation to influience the indicator
    direction = PlayerProperties.player.global_transform.basis * direction
    
    # Convert the direction into a angle that can be used
    # And offset the angle to follow the correct oritation
    var angle = atan2(direction.z,direction.x) - PI * 0.5
    
    # Apply rotation to the damage indicator
    damage_indicator.rotation = angle

Solution

  • Okay I have found a solution after searching on the internet I found a unity tutorial that does what I want, the code is obviously different but it was easy enough to find godots equivalent functions.

    This is the code, in the unity tutorial they used a vector3.signed_angle, I did not know what that is so I looked at the unity docs and understood what it did, so I went to godots docs to find an equivalent function and I did and it works perfectly!

    code:

    func rotate_to_target(target : Vector3) -> void:
        var player = PlayerProperties.player
        # Get the direction for the rotation
        var direction = (player.global_position - target).normalized()
        # Maths...
        var angle = direction.signed_angle_to(-player.transform.basis.z,Vector3.UP)
    
        # Apply the angle + PI to get full 360 rotation
        damage_indicator.rotation = angle + PI