Trying to dynamically animate a Gimbal?
I have been trying to solve this problem for weeks now, and I am banging my head off the wall at this stage.
I am trying to dynamically animate a Gimbal:
I would like the centre of this Gimble to point at an object using something like transform.lookAt. I would like to achieve this by dynamically rotating the three rings (x,y,z) of the Gimble so that the center points in the correct direction 'naturally'.
So I have parented the rings together like so: outsideRing>middleRing>centreRing+referenceObject.
Along with the centreRing, there is also a referenceObject parented to the middle ring. This object has Transform.LookAt active on it. My idea was to use this reference object to find out what rotations I needed to apply to each ring in order to get the centreRing of my Gimbal facing the same way.
I thought I could measure each angle (x,y,z) between the referenceObject's direction (refRing) and the centreRing's current direction (gameObject) and apply each angle separately and concurrently to each ring of my Gimbal (outerRing = y, middleRing = z, centreRing = x) to make the centreRing arrive at it's target. (using lerp)
My script on the centreRing looks like this:
public float zAngle; //the Z angle between centre ring and target
public float yAngle; //the Y angle between centre and target
public float xAngle; //the X angle between centre and the target
public float lerpPos; //the position along the lerp that the gameobject occupies
public float lerpSpeed; //the speed that the lerpPos is multiplied by
public GameObject refRing; //the reference object used to gain target direction
public bool lerp = false; //if true the lerp is active
public bool anglePos; //angle positive, this tells the script in which direction the gameObject should rotate (+ the angle or - it)
public bool correctRot; //This tells the object whether or not it should keep trying to rotate
public bool testboolPlzIgnore; //for testing
void Update()
{
xAngle = Vector3.Angle(gameObject.transform.forward, -refRing.transform.forward); //this is the difference in degrees between the target x rotation and the current x rotation
zAngle = Vector3.Angle(gameObject.transform.right, refRing.transform.right);
//yAngle = Vector3.Angle(Vector3.Cross(gameObject.transform.up, -refRing.transform.up), gameObject.transform.right);
yAngle = Vector3.Angle(gameObject.transform.up, refRing.transform.up)
if (!correctRot)
{
if (lerp)
{
lerpPos += Time.deltaTime * lerpSpeed; //increase the lerpPos float over time
if (anglePos)
{
gameObject.transform.Rotate(Mathf.Lerp(0, xAngle, lerpPos), 0, 0); //the game object should ADD the difference in degrees to it's x axis
}
else if (!anglePos)
{
gameObject.transform.Rotate(Mathf.Lerp(0, -xAngle, lerpPos), 0, 0); //the game object should SUBTRACT the difference in degrees to it's x axis
}
}
}
if(Vector3.Dot(gameObject.transform.up, -refRing.transform.forward) > 0) //if the gameObject's up direction faces the same way as the target object's backwards direction:
{
anglePos = true;
correctRot = false;
}
else if (Vector3.Dot(gameObject.transform.up, -refRing.transform.forward) < 0) //the opposite^^
{
anglePos = false;
correctRot = false;
}
if (xAngle == 0) //if the diffence in angle is the same then set all the bools to off
{
correctRot = true; //this means the lerp bool is not being looked at
lerp = false; //if it was being identified it would be off because it does not need to be moved
lerpPos = 0f; //resets the lerpPos float back to 0%
}
else if(xAngle != 0) //a change in angle is needed
{
correctRot = false; //let the lerp be evaluated
}
}
}
The idea is that this script will pass Z & Y values to the outer most rings as soon as it calculates them, and then those objects have similar scripts that lerp in the same way this one does, only using their respective Z & Y values.
So far the centreRing and the middleRing work somewhat correctly, I can turn on the lerp bool on each of those objects and they will adjust themselves into the correct position but I cannot crack the last, outer most ring. This ring is supposed to pivot on it's Y axis and I can manually rotate the it along the Y during play time into the correct position and with both lerp bools on the middleRing and centreRing turned on the centreRing will turn to the correct position but I cannot figure out how to calculate the Y angle before hand and then apply it through code. The above method in the script to calculate yAngle just does not produce the correct angle to get those other two rings into the correct position.
I have tried many variations of the algorithm to produce the correct yAngle but I just can't seem to get it, the closest I came was:
yAngle = Vector3.Angle(Vector3.Cross(gameObject.transform.up, -refRing.transform.up), gameObject.transform.right);
But is not it either, it's still off, (albiet slightly)
If anyone has any ideas about how to calculate that last yAngle I will be eternally grateful, OR any other method that might produce the same effect, this might be far from the simplist/best way to do this. (I wish there was some kind of bounty I could offer through this site for this question) At this stage I just want to figure out if it's possible, I feel like it is, but my own mathematical ability is letting me down.