1
\$\begingroup\$

I'm trying to take a RotateAround function and make it happen over time. I've been tinkering with Quaternions to try and get it to work but I can't quite figure it out.

This is the code:

public class RotateCamera : MonoBehaviour {

public Vector3 rotatePoint = new Vector3(0,0,5);

public void RotateLeft ()
{
    transform.RotateAround (rotatePoint, Vector3.up, 90);
}

public void RotateRight ()
{
    transform.RotateAround (rotatePoint, Vector3.up, -90);
}

I'm applying each void to a button, and this works like a Final Fantasy Tactics camera - rotate an isometric camera 90 degrees. But it happens instantly, and I want to make it happen over time, like a second or a half a second. I'm super new to programming and I can't find any guides on this or any other posts using google, so I'm asking on here as a last resort. Thanks for any help.

\$\endgroup\$
1
\$\begingroup\$

There would be numerous ways to implement this effect, because there are many ways to do timed transitions and rotations.

The general steps to take could be something like this

  • Store start_time = now
  • Store start_rotation = x
  • Calculate end_time = now + 60
  • Calculate end_rotation = y

Now at any time you can calculate a linear parameter p = (time - start_time) / (start_time - end_time). If time is between start_time and end_time then p will be between 0 and 1.

This allows us now to do linear interpolation of any value, for example the rotation value. You can choose to do linear interpolation on the Euler angle,

start_rotation = 90
end_rotation = -90
r = start_rotation + p * (end_rotation - start_rotation)   
transform = initial_transform
current_rotation = transform.Rotate(0, -45, r)

uusing RotateAround from a default position,

start_rotation = 90
end_rotation = -90
r = start_rotation + p * (end_rotation - start_rotation)   
transform = initial_transform
current_rotation = transform.RotateAround(rotatePoint, Vector3.up, r)

or using quaternions

current_rotation = Quaternion.Slerp(start_rotation, end_rotation, p)
\$\endgroup\$
1
\$\begingroup\$

When you want to kick off an action that will play out over several frames, a Coroutine is often a convenient way to do this. Here's one way to use a Coroutine for this purpose:

public Vector3 rotatePoint = new Vector3(0,0,5);
public float rotationSpeed = 90f;

Quaternion _targetRotation;
Vector3 _localOffset;
Coroutine _rotationCoroutine;

public void Start() {
    // Remember where the center of rotation should be in our local space.
    _localOffset = transform.InverseTransformPoint(rotatePoint);
    _targetRotation = transform.rotation;
}

public void RotateLeft () { Rotate(90); }

public void RotateRight () { Rotate(-90); }

void Rotate(float increment) {    
    // Spin our target rotation in the desired direction.
    _targetRotation = Quaternion.Euler(0, increment, 0) * _targetRotation;

    // If we're not already rotating, start a new rotation.
    // (Otherwise, the coroutine will automatically handle the new target)
    if(_rotationCoroutine == null)
        _rotationCoroutine = StartCoroutine(RotationCoroutine());
}

IEnumerator RotationCoroutine() {
    // Until our current rotation aligns with the target...
    while(Quaternion.Dot(transform.rotation, _targetRotation) < 1f) {
        // Rotate at a consistent speed toward the target.
        transform.rotation = Quaternion.RotateTowards(
            transform.rotation,
            _targetRotation,
            rotationSpeed * Time.deltaTime
        );

        // Adjust our position to preserve the relationship to the pivot.
        Vector3 offset = transform.TransformPoint(_localOffset);
        transform.position = rotatePoint - offset;

        // Wait a frame, then resume.
        yield return null;
    }

    // Clear the coroutine so the next input starts a fresh one.
    _rotationCoroutine = null;
}
\$\endgroup\$
0
\$\begingroup\$

In the inspector rotate your camera to the desired position and enter those values in the script area. Click left and right arrows on your keyboard, and adjust the time.

public class RorateCamera : MonoBehaviour
{
    public Vector3 rightRotation;
    public Vector3 leftRotation;
    public float speed = 0.1F;

    private bool rotateRight;

    public void RotateLeft()
    {
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(leftRotation), Time.deltaTime * speed);
    }

    public void RotateRight()
    {
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(rightRotation), Time.deltaTime * speed);
    }


    void Update()
    {
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            rotateRight = false;
        }
        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            rotateRight = true;
        }

        if (rotateRight)
        {
            RotateRight();
        }
        else
        {
            RotateLeft();
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ But when I do the RotateAround function, the camera's position also changes. Won't these functions just change the rotation of the camera? I'm probably missing something, but I'm assuming where transform.rotation is, I would type something like (0,90,0) - to turn the camera 90 degrees clockwise? Just for reference, I checked all the angles and positions the camera would have: South: position = (1, 5, -5), angle = (35, 0, 0) West: position = (-12, 5, 8), angle = (35, 90, 0) North: position = (1, 5, 21), angle = (35, -180, 0) East: position = (14, 5, 8), angle = (35, -90, 0) \$\endgroup\$ – Dungus Jan 20 '18 at 17:32
  • \$\begingroup\$ They will rotate the camera over a period of time and NOT snap instantly. You need to adjust the Speed variable. As you increase the Speed the camera will take longer to rotate. \$\endgroup\$ – Fabio S. Jan 20 '18 at 20:51

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.