UnityServicesMade with UnityLearnCommunityAsset StoreGet Unity
ForumsAnswersFeedbackIssue TrackerBlogEvangelistsUser Groups
Find posts and topics…
Ask a question
Spaces
Ask a Question
The form below has errors. Correct the fields in red and try again.
avatar image
Your Question:
rotating an object around a pivot inside and stopping at a set degree
I’ve been struggling with this one all morning. I have a game I’m designing where the entire level can rotate on a set pivot. I am rotating the level because, not the camera, because gravity needs to remain unchanged. My script, when Q or E is hit, rotates the entire level. (Currently in the X/Y plane, rotating around the z)
I was able to get it working without a pivot (it would rotate around 0,0,0) In the interest of being able to have multiple rotation points as levels get bigger, i was adjusting my script. I am having trouble getting it to stop - I have tried a bunch of different ways: my current version is setting a vector at an angle equal to the desired rotation and then using vector3.dot to see if they line up as the script rotates it.
The rotation is also in a coroutine.
If you could please help me figure out how to get this while loop to recognize that the vectors have aligned, I woudl be very grateful
[SerializeField] public GameObject level; // levels will change.
[SerializeField] private float rotationDegree = 90f; // how far you want the level to rotate. May need to be made public in order to change it for different levels.
[SerializeField] private float rotateSpeed = 15f; // speed of the rotation
private bool levelRotating = false,
Quaternion toAngle, startAngle;
private float startDegree;
private Transform levelTrans;
private Transform pivot;
private void Awake()
{
levelTrans = level.transform; // shorthand for the transform of the level vrs the GO
startAngle = Quaternion.identity; // Make sure the level startAngle is set to No Rotation to start.
foreach(Transform child in levelTrans)
{
// searches for each child in the Level for the pivot point on layer 9 (pivot layer) and then sets it for use later. Should only be one pivot per camera move.
// Note: Camera Move script (to change levels/scenes) will need to re find pivot!!
if(child.gameObject.layer == 9)
{
pivot = child;
break;
}
}
}
private void LateUpdate()
{
if (!levelRotating)
{
startDegree = levelTrans.eulerAngles.z;
if (Input.GetAxisRaw("Rotate") < 0)
{
toAngle = Quaternion.AngleAxis(startDegree + rotationDegree, levelTrans.forward); // set the destination angle as an offset from the start angle
this.transform.SetParent(levelTrans); // adds the player object to the level, so it will rotate with the level and not get tossed out
rotatingClockwise = true; // set the direction flag
levelRotating = true;
StartCoroutine(SpinLevel(rotateSpeed, Vector3.forward, pivot));
}
else if (Input.GetAxisRaw("Rotate") > 0)
{
toAngle = Quaternion.AngleAxis(startDegree + rotationDegree, -levelTrans.forward);
this.transform.SetParent(levelTrans);
rotatingCounterClock = true;
levelRotating = true;
StartCoroutine(SpinLevel(rotateSpeed, -Vector3.forward, pivot));
}
} // else do nothing if the level is moving. No change in current location, no change in flags, no change in toAngle
}
private IEnumerator SpinLevel(float overTime, Vector3 rotDirection, Transform pivot)
{
Vector3 pivotPoint = pivot.position;
Vector3 destination = FindEndRotation(rotationDegree);
Vector3 start = startAngle.eulerAngles;
float dotRotateCheck = 0.0f;
// if they are different, rotate the level a small amount, and set the level rotating to True
while (!Mathf.Approximately(dotRotateCheck,0.0f))
{
levelRotating = true;
levelTrans.RotateAround(pivotPoint, rotDirection, overTime * Time.deltaTime);
dotRotateCheck = Vector3.Dot(levelTrans.transform.right, destination);
yield return null;
}
levelRotating = false;
this.transform.parent = null;
}
private Vector3 FindEndRotation(float degree)
{
Vector3 end = new Vector3(0,0,0);
float radians = degree * Mathf.Deg2Rad;
end.x = Mathf.Cos(radians);
end.y = Mathf.Sin(radians);
return end;
}
I’ve been struggling with this one all morning. I have a game I’m designing where the entire level can rotate on a set pivot. I am rotating the level because, not the camera, because gravity needs to remain unchanged. My script, when Q or E is hit, rotates the entire level. (Currently in the X/Y plane, rotating around the z)
I was able to get it working without a pivot (it would rotate around 0,0,0) In the interest of being able to have multiple rotation points as levels get bigger, i was adjusting my script. I am having trouble getting it to stop - I have tried a bunch of different ways: my current version is setting a vector at an angle equal to the desired rotation and then using vector3.dot to see if they line up as the script rotates it.
The rotation is also in a coroutine.
If you could please help me figure out how to get this while loop to recognize that the vectors have aligned, I woudl be very grateful
[SerializeField] public GameObject level; // levels will change.
[SerializeField] private float rotationDegree = 90f; // how far you want the level to rotate. May need to be made public in order to change it for different levels.
[SerializeField] private float rotateSpeed = 15f; // speed of the rotation
private bool levelRotating = false,
Quaternion toAngle, startAngle;
private float startDegree;
private Transform levelTrans;
private Transform pivot;
private void Awake()
{
levelTrans = level.transform; // shorthand for the transform of the level vrs the GO
startAngle = Quaternion.identity; // Make sure the level startAngle is set to No Rotation to start.
foreach(Transform child in levelTrans)
{
// searches for each child in the Level for the pivot point on layer 9 (pivot layer) and then sets it for use later. Should only be one pivot per camera move.
// Note: Camera Move script (to change levels/scenes) will need to re find pivot!!
if(child.gameObject.layer == 9)
{
pivot = child;
break;
}
}
}
private void LateUpdate()
{
if (!levelRotating)
{
startDegree = levelTrans.eulerAngles.z;
if (Input.GetAxisRaw("Rotate") < 0)
{
toAngle = Quaternion.AngleAxis(startDegree + rotationDegree, levelTrans.forward); // set the destination angle as an offset from the start angle
this.transform.SetParent(levelTrans); // adds the player object to the level, so it will rotate with the level and not get tossed out
rotatingClockwise = true; // set the direction flag
levelRotating = true;
StartCoroutine(SpinLevel(rotateSpeed, Vector3.forward, pivot));
}
else if (Input.GetAxisRaw("Rotate") > 0)
{
toAngle = Quaternion.AngleAxis(startDegree + rotationDegree, -levelTrans.forward);
this.transform.SetParent(levelTrans);
rotatingCounterClock = true;
levelRotating = true;
StartCoroutine(SpinLevel(rotateSpeed, -Vector3.forward, pivot));
}
} // else do nothing if the level is moving. No change in current location, no change in flags, no change in toAngle
}
private IEnumerator SpinLevel(float overTime, Vector3 rotDirection, Transform pivot)
{
Vector3 pivotPoint = pivot.position;
Vector3 destination = FindEndRotation(rotationDegree);
Vector3 start = startAngle.eulerAngles;
float dotRotateCheck = 0.0f;
// if they are different, rotate the level a small amount, and set the level rotating to True
while (!Mathf.Approximately(dotRotateCheck,0.0f))
{
levelRotating = true;
levelTrans.RotateAround(pivotPoint, rotDirection, overTime * Time.deltaTime);
dotRotateCheck = Vector3.Dot(levelTrans.transform.right, destination);
yield return null;
}
levelRotating = false;
this.transform.parent = null;
}
private Vector3 FindEndRotation(float degree)
{
Vector3 end = new Vector3(0,0,0);
float radians = degree * Mathf.Deg2Rad;
end.x = Mathf.Cos(radians);
end.y = Mathf.Sin(radians);
return end;
}
Thanks for any help you can provide
( ai also have tried using local forward z compared to rotation degrees, and vector3.angle to find the current angle in the loop until it reaches 0. I suspect that the issue is Float and Epsilon, but…