6
\$\begingroup\$

I have a semicircle like game object which I made by putting two arcs in an empty game object (SCircle) and rotating the 15° (for left arc) and -15° (for right arc) as seen below.

enter image description here

SCircle has an Orientation enum with two valuesLeft (rotates SCircle to 45°) and Right (rotates SCircle to -45°) as seen in the image below.

enter image description here

I use the following coroutine to move SCircle between orientations.

IEnumerator RotateLeftOrRight(Vector3 byAngles, float inTime)
{
    Quaternion fromAngle = gameObject.transform.rotation ;
    Quaternion toAngle = Quaternion.Euler (transform.eulerAngles);


    if (circOrientation == Orientation.Left) {
        toAngle = Quaternion.Euler (gameObject.transform.eulerAngles - byAngles);
        circOrientation = Orientation.Right;

    }
    else if (circOrientation == Orientation.Right) {

        toAngle = Quaternion.Euler (gameObject.transform.eulerAngles + byAngles);
        circOrientation = Orientation.Left;
    }


    for(float t = 0f ; t <= 1f ; t += Time.deltaTime/inTime)
    {
        gameObject.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t) ;
        yield return null ;

        gameObject.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, 1);
    }

}

I also used a very similar coroutine to move the individual arcs by 30° (in opposite directions) from say, Orientation Left, as seen below:

enter image description here

Since SCircle Coroutine is activated by a mouse click, I have the case where the individual arcs coroutine is run and before it is complete the parent SCircle coroutine is also run. In this case the arcs end up moving from Left to A, which is not the behavior I need. I would want the behavior of them ending up at B when moving from the Left. Likewise, from B, when the SCircle coroutine is run while the arcs coroutine is in progress the orientation will return to the Left.

Please note that the blue arrow represents the movement of the left Arc, the red represents the right Arc and the black represents movement of SCircle - the parent object.

How can I achieve the behavior from Left to B and from B back to Left?

enter image description here

\$\endgroup\$
  • \$\begingroup\$ You should probably separate the two since they'll be doing different rotations. If not, you can always use the GetComponentInChildren or a similar function to move the localRotation. \$\endgroup\$ – Genevra Oct 3 '17 at 21:02
  • \$\begingroup\$ answers.unity3d.com/questions/205391/… \$\endgroup\$ – Genevra Oct 3 '17 at 21:05
  • \$\begingroup\$ @GMR516 I need one to be contained in the other. I have been accessing the child object using transform.GetChild (0).gameObject \$\endgroup\$ – Bane Oct 3 '17 at 21:36
  • \$\begingroup\$ @GMR516 I am still trying to solve this issue \$\endgroup\$ – Bane Oct 5 '17 at 17:52
  • \$\begingroup\$ I'm not sure what the need is to contain it inside the other. It's gonna make moving them differently more difficult, as any modification to the parent will affect the child. I highly recommend separating the gameobjects in the hierarchy. \$\endgroup\$ – Genevra Oct 5 '17 at 20:58
0
\$\begingroup\$

Your approach SHOULD work if you keep your local rotations straight. Essentially you have two rotations you want to act independent, and somehow they're coupling. The following scenario SHOULD work, and if not you may not have set it up correctly. Try attaching a script like this to each object you wish to rotate independently:

public class TransformOffsetRotatable : MonoBehaviour
{
    public float rotationSpeed;

    private Quaternion targetRotation;
    private Quaternion startingRotation;

    private void Awake()
    {
        startingRotation = transform.localRotation;
        targetRotation = startingRotation;
    }

    private void OnEnable()
    {
        StartCoroutine(RotateToTargetCoroutine());
    }

    public void SetRotationOffset(float deg)
    {
        targetRotation = startingRotation * Quaternion.Euler(0, 0, deg); // Assuming standard 2D axis
    }

    // This coroutine is simple and handles changing of rotation value
    // mid execution. If you don't want it running all the time, you can
    // end the coroutine after completing rotation, and restart when needed.
    private IEnumerator RotateToTargetCoroutine()
    {
        while (true)
        {
            yield return new WaitForFixedUpdate(); // Should probably rotate on fixed update
            // maxDeg = speed * time
            transform.localRotation = Quaternion.RotateTowards(transform.localRotation, targetRotation, Time.fixedDeltaTime * rotationSpeed);
        }
    }
}

This solution has the bonus that it can be attached to any game object. You can have your existing classes simply use a reference to this script. It's plug and play!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.