0 votes

So, I'm trying to make my enemy look at my player.
I was using the look_at() function. This worked. The only problem with it is, that the enemy turned instantly, and not gradually.
I then found this reddit post. There i found the following code snippet:

func turn_face(target, delta):
    var rotation_speed = 3
    var target_pos = target.global_transform.origin
    var pos = global_transform.origin
    target_pos.y = pos.y
    var origin_rot = rotation
    look_at(target_pos, Vector3(0,1,0))
    var target_rot = rotation
    var rot_length = target_rot - origin_rot
    var rot_step = rot_length * rotation_speed * delta
    rotation = origin_rot + rot_step

I was able to make this work. But there is one problem.
It does not handle any wrapping. Sometimes the enemy just makes a quick 360. and well I don't want that he does that.
I then looked a little bit further and found this question. Yes I got this working as well. But I have 2 problems with it.
First, this method wants an object and then gets it's position. But I can't always give the function an Object/Target. I need to give it a position.
Second, sometimes the enemy looks very weird when turning. Like squeezed or something.
But when using this, the enemy does turn around perfectly and isn't doing any 360's.

What I'd like to know is, how I could use the first example (not the tweening thing) with a way to wrap around. I heard I need to use something like basis or quat? If so, I have no clue on how to use those.
Or on how to use the tweening method, but without that squeezing and without giving an object but rather giving straight a position.

I hope it's clear what I'm asking for.

And sorry if my english isn't so good, I'm still learning!

Thank you all for the help, and I hope you all are doing good with that quarantine thing going on.

asked May 25 in Engine by Tim Irmler (22 points)

2 Answers

+1 vote
Best answer
extends KinematicBody

var player

func _ready():
    set_process(false)

func _process(delta):
    turn(player)

func turn(player):
    var global_pos = global_transform.origin
    var player_pos = player.global_transform.origin
    var rotation_speed = 0.01
    var wtransform = global_transform.looking_at(Vector3(player_pos.x,global_pos.y,player_pos.z),Vector3(0,1,0))
    var wrotation = Quat(global_transform.basis).slerp(Quat(wtransform.basis), rotation_speed)

    global_transform = Transform(Basis(wrotation), global_transform.origin)

func _on_Area_body_entered(body):
    player = body
    set_process(true)

func _on_Area_body_exited(body):
    set_process(false)

Hey, I thought the document I included previously(this one:https://docs.godotengine.org/en/stable/tutorials/math/interpolation.html) explained slerp which is key for smooth rotation which it does not my bad. the code snippet above worked for me, hope it solves your problem too.
Have a good day.

answered May 26 by M15F17 (53 points)
selected May 26 by Tim Irmler

OMG YES THANK YOU VERY MUCH!
THIS WORKS PERFECTLY!

you're my saviour! THANK YOU!!

0 votes

You can just use Interpolation to smooth out the motion

reference: https://docs.godotengine.org/en/stable/tutorials/math/interpolation.html

Hope you are doing well in this hard time too
Good luck.

answered May 25 by M15F17 (53 points)

Hello and Thank you for your answer.

I'm not so sure how interpolation can help me with my problem.
Can I use Interpolation for wrapping around the rotation?
Or did i miss something?
Can you give me an example?

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.