- Home /
Quaternion.Slerp seemingly not working with LateUpdate
Howdy, and sorry for taking your time. I have a script, attached to the 'head' bone of my main character, whose purpose is to face her head towards enemies and other noteworthy objects that are close to her (think Silent Hill protagonists looking at items). The code itself works just fine, and does it by generating OverlapSpheres and iterating through the results, in order of importance.
However, to actually get the head to move, I've had to use LateUpdate (so that the code affects the armature after the Animator is done with it), and Slerp seems to not work at all with LateUpdate. I've been forced to instantly snap her head towards whatever she's looking at - while it does work, it's very jerky and looks completely unnatural. I can't use a bone mask and stuff the code in Update either, because her head movement is important to a few other animations.
Here's the offending bit of code:
if (target) { // if there's a suitable target, look at it
var distCheck = Vector3.Distance(target.GetComponent.<Collider>().ClosestPointOnBounds(transform.position), transform.position);
// headRot is the facing direction towards the target (not some horrible disease)
var headRot = Quaternion.LookRotation(target.position - transform.position);
// the z angle has to be manually set, or her head will be sideways
headRot = Quaternion.Euler(headRot.eulerAngles.x, headRot.eulerAngles.y, -90);
// continuously sets her face angle to face the target
transform.rotation = headRot;
/* transform.rotation = Quaternion.Slerp(transform.rotation, headRot, Time.deltaTime * 3.0);*/
// raycasts ALMOST up to the target, to check if there's anything in between
var rayCheck = false;
rayCheck = Physics.Raycast(transform.position,checkRot * Vector3.forward,distance*0.9);
// checks the angle between her face and neck's forward vectors
angleBetween = Vector3.Angle(transform.forward,neckForward);
// if the angle is too large (as in, she's facing unnaturally far to the sides), remove the target
if(angleBetween > 65 || distCheck >= (10*self.GetComponent(PlayerStats).flashlightOn)|| rayCheck){
target = null;
}
The bit of code inside / / doesn't work at all, I've just included it as an example of what I've tried. Any alternatives to smoothly moving her head would be just fine, if possible.
Thanks a lot!
Answer by tanoshimi · May 05, 2016 at 11:57 AM
This is not specific to LateUpdate or Slerp, but a very common people have with using (s)lerp incorrectly, described here amongst other places: http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
You're never increasing the delta parameter you pass to Slerp - you're just setting it to Time.deltaTime * 3.0f on every frame, which, if your game is running at 60FPS, is equal to 0.05:
transform.rotation = Quaternion.Slerp(transform.rotation, headRot, Time.deltaTime * 3.0);
So what this line of code says, in every frame, is "Start with the transform rotation set by the animator, and then adjust it 5% of the way towards the rotation specified by headRot".
It should make a bit of difference, but 5% is pretty small, and you might not notice it. As you never increase the third parameter value, the rotation never changes.