A Way to smooth the lookat command?

i was looking for an alternative so the camera wont look at the character right away, instead, i want the camera to rotate arround until its fully lined with the object, but with the code “Camera.transform.Lookat” (i may have screwed up the caps in here but is just an example) the camera just transform its rotation towards the object i a milisecound, and its a bit desorienting for the player

any way for me to fix this up?

You can use Quaternion.LookAt to calculate a look at based on the relative value between two vectors. Then use the Quaternion.Lerp function to set the cameras look at over time.

Yea, if you use Quaternion.LookRotation you can get a quaternion. Then you can do something like this:

int totalRotationsQueued = 0;

Coroutine activeRotateCoroutine;

IEnumerator RotateProcess( Quaternion target, float degreesPerSecond, Coroutine lastRotateCoroutine ) {
    if( lastRotateCoroutine != null ) yield return lastRotateCoroutine;// wait for last rotation to finish.

    Quaternion start = transform.rotation;// start rotation.

    float degrees = Quaternion.Angle(start, target);
    float degreesLeft = degrees;
    
    while( degreesLeft > 0f ) {
        degreesLeft -= Time.deltaTime * degreesPerSecond;
        transform.rotation = Quaternion.Slerp( target, start, degreesLeft / degrees );
        if( degreesLeft > 0f )
            yield return null; // wait one frame.
        else
            break;
    }
    if( --totalRotationsQueued == 0 ){
        // theres no more rotations, so we must be the active one.
        activeRotateCoroutine = null;
    }
}
public void RotateTo(Quaternion rotateTarget, float degreesPerSecond) {
    Coroutine lastRotateCoroutine = activeRotateCoroutine;
    totalRotationsQueued ++;
    activeRotateCoroutine = StartCoroutine(RotateProcess(rotateTarget, degreesPerSecond)); 
}

it looks a little more complex than it is. It lets you send a rotation and degrees per second, and it queues each call. so if you call it twice it will go through each. You could change this to use Update pretty easily. The main thing is you should have a start rotation and a end target rotation, unless you want to throttle it manually by the angle difference.

hmm… thanks a lot for the script… it sure does look complex

but im getting the hang of it… tell me this, can you show me an example of how i could do this with a update function, and if you can, how can i do an “if statement” to check if the camera is already looking at the target so i can swith false this function?

something like

Transform target;
Quaternion rotationStart;
float rotationPercent;
public Transform lookTarget { 
    get { return target; }
    set { if( target != value ) { target = value; RestartLookProcess(); } }
}
void RestartLookProcess() 
{
    if( target ) { // if were suppose to be looking at something
        // store off our start data.
        rotationStart = transform.rotation;
        rotationPercent= 0f;
    }else {
         // no target.
         rotationPercent= 1f; 
    }
}

void Update() {
    if( target ){
        Quaternion targetAngle = Quaternion.LookRotation( target.position - transform.position, transform.up );
        if( rotationPercent < 1f ) {
            rotationPercent += Time.deltaTime;
            if( rotationPercent < 1f )
                targetAngle = Quaternion.Slerp(rotationStart, targetAngle, rotationPercent);
        }
        transform.rotation = targetAngle;
    }
}

to use you’d just do this.lookTarget = other.transform;

to disable
this.lookTarget = null;

That just does the rotation over a second. You could modify the line:
rotationPercent += Time.deltaTime;
to change the speed.

1 Like

Alternatively, something simple like this**:

float damping = 2.0f;

void LateUpdate()
{
    this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookAt(targetPosition-myPosition)), damping * Time.deltaTime);
}

Note: Untested code, you will need to fix the targetPosition and myPosition vectors.

Yea that works too, though it wont be linear.

hmm i tryed then both… and they both work!!

well… some bugs are still apearing but i’ll deal with then

just to clarify… in the first script it says

Transform target;

but thats actualy a var right?

the same for the secound script performed by justinLloyd, it starts with

float damping = 2.0f;

but is actualy

var damping : float = 2.0f ; right?

Agreed.

Yeah, sorry, hackish C# :slight_smile:

yea target would be

var target : Transform

I don’t know much about properties with JS but if you want you could just change the content inside get and set into public methods ( like GetLookTarget and SetLookTarget )

Totaly!.. thanks man both of your scripts helped me, actualy im using BDev script for cutsceenes you know, since the camera moves a little smoothier, and JustinLloid’s for gameplay when the aim is locked at something, i’ll put the name of you dudes on the credtis !

This code is giving me compile errors is there something else I need to add? Thanks

Assets/Scripts/NPCActive.cs(84,52): error CS1501: No overload for method RotateProcess' takes 2’ arguments

Assets/Scripts/NPCActive.cs(84,37): error CS1503: Argument #1' cannot convert object’ expression to type
`System.Collections.IEnumerator’

Assets/Scripts/NPCActive.cs(84,37): error CS1502: The best overloaded method match for `UnityEngine.MonoBehaviour.StartCoroutine(System.Collections.IEnumerator)’ has some invalid arguments