I can't get my Quaternion rotation to work
The first line of my code below makes my object follow the rotation of the object it collides with. The part after that is supposed to make the object rotate 180 degrees (go in opposite direction of collision object), but doesn't do anything at all. I've tried a few different approaches, but none of them seem to do anything.
Any help is much appreciated!
// follow the rotation of the object it collides with:
gameObject.transform.rotation = other.transform.rotation;
// rotate 180 degrees (go in opposite direction of collision object):
var lookPos = other.transform.position - transform.position;
lookPos.y = 0;
var rotation = Quaternion.LookRotation(lookPos);
rotation *= Quaternion.Euler(0, 90, 0); // this adds a 90 degrees Y rotation
// apply interpolation over time:
transform.rotation = Quaternion.Slerp( transform.rotation , rotation , Time.deltaTime*smooth );
Slerp
makes sense when called in any of the Update
methods. But guessing from "(...) object it collides with (...)" you nested this code inside OnColliderEnter
or OnColliderStay
method , which won't be called often enough for interpolation to work properly or at all.
Thanks so much for your reply. That makes perfect sense. So I move this code into the update function and then call that part of the code from the OnColliderEnter (?)
option 1: animate in Coroutines
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InterpolateRotationExample : MonoBehaviour
{
[SerializeField][Min(0.0001f)] float _interpolationDuration = 2f;
Coroutine _animationCoroutine = null;
void OnCollisionEnter ( Collision collision )
{
if( _animationCoroutine!=null ) StopCoroutine( _animationCoroutine );// prevents 2 rotation coroutines (animations by code) being executed at the same time
Transform otherTransform = collision.transform;
var startRot = transform.rotation;
var targetRot = Quaternion.LookRotation( -otherTransform.forward , otherTransform.up );
_animationCoroutine = StartCoroutine( InterpolateRotationOverTime(startRot,targetRot,_interpolationDuration) );
}
IEnumerator InterpolateRotationOverTime ( Quaternion src , Quaternion dst , float duration )
{
Debug.Log("started");
float timeStart = Time.time;
float completion = 0;
var waitForFixedUpdate = new WaitForFixedUpdate();
while( completion<1 )
{
yield return waitForFixedUpdate;// code execution stops and waits until FixedUpdate (physics update) basically, then continues
completion = ( Time.time - timeStart ) / _interpolationDuration;
transform.rotation = Quaternion.Slerp( src , dst , completion );
}
Debug.Log("\tdone :T");
}
}
option 2: animate in update methods
using UnityEngine;
public class InterpolateRotationExample : MonoBehaviour
{
[SerializeField][Min(0.0001f)] float _interpolationDuration = 2f;
float _interpolationStart;
Quaternion _quatSrc, _quatDst;
void Start ()
{
enabled = false;
}
void OnCollisionEnter ( Collision collision )
{
Transform otherTransform = collision.transform;
_quatSrc = transform.rotation;
_quatDst = Quaternion.LookRotation( -otherTransform.forward , otherTransform.up );
_interpolationStart = Time.time;
enabled = true;
}
void FixedUpdate ()
{
float t = ( Time.time - _interpolationStart ) / _interpolationDuration;
transform.rotation = Quaternion.Slerp( _quatSrc , _quatDst , t );
if( t>=1 )
{
enabled = false;
}
}
}
I really appreciate your help. I will have to try and implement this tomorrow. I'm pretty new to Unity so I will need some time to see if I can get this to work with my code. Thanks a lot!