- Home /
How to make an object look at another object over time?
I have an object that I want to face another object. I used transform.LookAt() and it does that in just 1 frame, but I want to spread it out over time. I was looking into Slerp() but the angle is always off. This is the code I'm using that makes it work in just 1 frame.
transform.rotation = Quaternion.LookRotation(target - transform.position);
transform.eulerAngles = new Vector3(270.0f, transform.eulerAngles.y + 180, 0f);
As I said the above code works for just 1 frame, but I'd like it work over a few seconds. Also it only looks at it on one axis, hence the eularangles set.
Answer by aldonaletto · Feb 12, 2013 at 02:59 AM
Usually you should place the code in Update or in a coroutine, so that the object rotates a little each frame - like this:
public float speed = 2.5f;
void Update(){
Vector3 dir = target - transform.position;
dir.y = 0; // keep the direction strictly horizontal
Quaternion rot = Quaternion.LookRotation(dir);
// slerp to the desired rotation over time
transform.rotation = Quaternion.Slerp(transform.rotation, rot, speed * Time.deltaTime);
}
This is the so called "Lerp filter": the rotation speed is proportional to the angle to be rotated, thus it's fast at first and slows down when approaching the desired rotation. As a rule of thumb, speed = 5 takes about 1 second to reach 99% of the final angle, 2.5 takes 2 seconds, and so on.
Alright I used this code for my rotations and it seems like its rotating on the wrong axis. I dont have a way to edit the source model. The starting rotation is 270, 90, 0, then after a test run it's 0, 180, 0, whereas it should be 270, 180, 0. I tried setting the x to 270 after the Slerp call, but it didn't seem to do anything.
The easiest solution is to create an empty object, child the model to it and adjust the model orientation, then move the scripts from the model to the empty object: this way the empty game object can align its forward direction to the target, and the model will follow it.
Hmm I found another way that sort of works. I have it rotating the correct axis, but it rotates 45 degrees too far on the y axis. This is the code I'm using now:
Vector3 dir = ts.turret.position - target;
dir.x = 0;
dir.z = 0;
Quaternion rot = Quaternion.LookRotation(dir);
// slerp to the desired rotation over time
ts.turret.rotation = Quaternion.Lerp(ts.turret.rotation, rot, 1.0f * Time.deltaTime);
That's weird: zeroing x and z makes the direction vector totally vertical, thus the object should always look at the same direction. Using a "sandwich" game object should be a better solution - take a look at How to fix the rotation of an imported model in the $$anonymous$$anual.
Answer by S_Darkwell · Jul 20, 2019 at 08:45 PM
Given examples apply an easing effect as they approach the direction of the target.
The code below MonoBehavior will turn the transform to which it is attached toward at a given target with a consistent speed from start to finish.
using UnityEngine;
public class LookAtBehavior : MonoBehaviour {
public Transform Target;
public float TurnSpeed = 50.00F;
private Transform myTransform;
public void Start() {
myTransform = GetComponent<Transform>(); // Cache own Transform component
}
public void Update() {
var targetDirection = Target.position - myTransform.position;
targetDirection.y = 0.00F; // Lock global y-axis
var targetRotation = Quaternion.LookRotation(targetDirection);
var deltaAngle = Quaternion.Angle(myTransform.rotation, targetRotation);
if (deltaAngle == 0.00F) { // Exit early if no update required
return;
}
myTransform.rotation = Quaternion.Slerp(
myTransform.rotation,
targetRotation,
TurnSpeed * Time.deltaTime / deltaAngle
);
}
}
Your answer
Follow this Question
Related Questions
Look at rotation at a moving object while moving (C#)(2D) 3 Answers
Get slerp to work just as LookAt(,Vector3.right) does 1 Answer
Incorrect script for slerp rotation 1 Answer
How to make a gameobject look at(rotate) another gameobject smoothly? 0 Answers
Slerp doesnt go to the rotation its supposed to go to 1 Answer