I am writing a script to rotate my object in a random direction. My object is a cube that starts facing a single direction and I want it to generally face that same direction forever but I want to apply a random rotation at sporadic intervals to create the illusion that the cube is alive and looking around. Since I want the cube to generally face the same direction over the lifetime of the game object my plan is to start out by storing the cube forward rotation and then pick a random number for Z and Y. I would then add those numbers to the original forward rotation and slowly rotate the cube to the new rotation.
I’m not really sure how to do this, but here’s what I’ve got so far (slowMove will be called at a random interval to give the appearance of not being predetermined.
private void slowMove()
{
if (_fromOrigin)
{
_fromOrigin = false;
// if we're in our origin rotation, then pick a new random rotation
// x +/- 90 degrees, y +/- 90 degrees and z +/- 90 degrees from our
// current rotation
_toRotation = Quaternion.LookRotation(new Vector3(UnityEngine.Random.Range(-90, 90), UnityEngine.Random.Range(-90, 90), UnityEngine.Random.Range(-90, 90)) + _originalRotation.eulerAngles, transform.up);
}
else
{
// if we're rotated away from our origin rotation, rotate back
_toRotation = _originalRotation;
}
}
void Update()
{
if (_toRotation != null)
{
// slowly move to our new rotation over time
transform.rotation = Quaternion.Slerp(transform.rotation, _toRotation.Value, Time.deltaTime * 20f);
// until the difference in angle between our current rotation and
// our destination rotation is < 1
if (Quaternion.Angle(transform.rotation, _toRotation.Value) < 1)
{
_toRotation = null;
}
}
}
Obviously the _toRotation value isn’t being calculated correctly because it’s not taking into account my current rotation so it can’t be an offset like I would like, but I don’t really know how to do that.
slerping between start and end position made it really jumpy. It would move a bit on each frame, then reset and move the same distance on the next frame. It looks like slerping from current and target is what I want because that’s nice and smooth. localRotation, rotation, tried them both and they both have the same look. My big problem is the rotation calculation. I need to calculate a rotation that is no more than +/- 90 degrees from my starting rotation in all three directions (x,y,z). If I use UnityEngine.Random.rotation everything works perfectly, I just need a rotation that is clamped to that 180 degree range in all directions.
This code works perfectly for what I’m doing other than that clamping.
private void slowMove()
{
if (_fromOrigin)
{
_fromOrigin = false;
// if we're in our origin rotation, then pick a new random rotation
// x +/- 90 degrees, y +/- 90 degrees and z +/- 90 degrees from our
// current rotation
_toRotation = UnityEngine.Random.rotation;
}
else
{
_fromOrigin = true;
// if we're rotated away from our origin rotation, rotate back
_toRotation = _originalRotation;
}
}
void Update()
{
if (_toRotation != null)
{
// slowly move to our new rotation over time
transform.rotation = Quaternion.Slerp(transform.rotation, _toRotation.Value, Mathf.Clamp01(Time.deltaTime * 10));
// until the difference in angle between our current rotation and
// our destination rotation is < 1
if (Quaternion.Angle(transform.rotation, _toRotation.Value) < 1)
{
_toRotation = null;
}
}
}
Hmmmm, I found a method called Quaternion.FromToRotation that is supposed to create a rotation between two vectors which looked promising but didn’t really work. I still get a rotation that is beyond the 90 degrees I want to go.
Actually, nevermind, that looks like it’s sort-of working. although, oddly, whether I have the rotationVariance to 90 or 1 it seems to work exactly the same way…