Itterating GameObject's Rotation through a For Loop.

I have a movement script, which takes in a GameObject (to move), a Goal Transform (to travel to) and a Float speed (rate to move towards destination). It adds the variables to unique lists, and in the Update function it moves the GameObject step by step towards to goal location. Here is the code for how this works:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {

    public GameObject[] cardPosons;
    private static GameObject[] cardPosns;

    //each script can choose speed. Most(if not all) will pull this value.
    public static float cardSpeed = 2;

    private static List<GameObject> movingCards = new List<GameObject>();
    private static List<float> movingCardSpeed = new List<float>();
    private static List<Vector3> movingCardGoalPosition = new List<Vector3>();
    private static List<Quaternion> movingCardGoalRotation = new List<Quaternion>();
    private static float speedMultiplier = 0.1f;


    void Start() {
        cardPosns = cardPosons;
    }

    void Update() {
        StepMovement();
    }


    public static void MoveCard(GameObject card, int goal, float speed) {
        Transform cardStartPosition = card.transform;
        Transform goalLocation = cardPosns[goal].transform;
        float posOfset = card.GetComponent<Card>().CardHeightOffset();

        Vector3 ofsetPosition = new Vector3(goalLocation.position.x, goalLocation.position.y + +posOfset, goalLocation.position.z);

        if (speed == 0) {
            card.transform.position = ofsetPosition;
            card.transform.rotation = goalLocation.rotation;
        }
        else {
            movingCards.Add(card);
            movingCardSpeed.Add(speed);
            movingCardGoalPosition.Add(ofsetPosition);
            movingCardGoalRotation.Add(card.transform.rotation);
        }
    }

    private static void StepMovement() {
        int counter = -1;
        for (int i = 0; i < movingCards.Count; i++) {
            counter++;
            Transform currentTransform = movingCards[counter].transform;
            float movSpeed = movingCardSpeed[counter] * speedMultiplier;
            Vector3 remainingDistance = movingCardGoalPosition[counter] - movingCards[counter].transform.position;

            // Individualize remainingDistance's floats, turn all positive.
            float remX = remainingDistance.x; if (remX < 0) { remX = -remX; }
            float remY = remainingDistance.y; if (remY < 0) { remY = -remY; }
            float remZ = remainingDistance.z; if (remZ < 0) { remZ = -remZ; }
            // Work out which float is the largest.
            float maxAxisLength = 0;
            if (remX >= remY && remX >= remZ) { maxAxisLength = remX; }
            if (remY >= remX && remY >= remZ) { maxAxisLength = remY; }
            if (remZ >= remX && remZ >= remY) { maxAxisLength = remZ; }
            //Limit Movement distance to not overshoot largest target.
            if (movSpeed > maxAxisLength) { movSpeed = maxAxisLength; }
            // Use new movSpeed to find deltaX, deltaY and deltaZ respectively.
            float xResult = movSpeed * (remainingDistance.x / maxAxisLength);
            float yResult = movSpeed * (remainingDistance.y / maxAxisLength);
            float zResult = movSpeed * (remainingDistance.z / maxAxisLength);
            // Set new position based on 3 deltaValues.
            currentTransform.position += new Vector3(xResult, yResult, zResult);


            if (currentTransform.position == movingCardGoalPosition[counter]) {
                // On arrival at destination, respective variables are removed from their Lists.
                movingCards.Remove(movingCards[counter]);
                movingCardSpeed.Remove(movingCardSpeed[counter]);
                movingCardGoalPosition.Remove(movingCardGoalPosition[counter]);
                movingCardGoalRotation.Remove(movingCardGoalRotation[counter]);
            }
        }
    }

}

I’ve hit a problem trying to replicate this for rotation. I am trying to make it work so that no matter what 2 rotations I insert (be they just on 1 axis or in all 3), it will still successfully transition between the 2 Quaternions. Here is the code I attempted to use (inserted into the previous script, lines 73-74):

Quaternion goalRotation = movingCardGoalRotation[counter];
Quaternion currentRotation = currentTransform.rotation;
float maxAxisRotation = 0;
float rotX = currentRotation.x; if (rotX < 0) { rotX = -rotX; }
float rotY = currentRotation.y; if (rotY < 0) { rotY = -rotY; }
float rotZ = currentRotation.z; if (rotZ < 0) { rotZ = -rotZ; }
float rotW = currentRotation.w; if (rotW < 0) { rotW = -rotW; }
if (rotX >= rotY && rotX >= rotZ && rotX >= rotW) { maxAxisRotation = rotX; }
if (rotY >= rotX && rotY >= rotZ && rotY >= rotW) { maxAxisRotation = rotY; }
if (rotZ >= rotX && rotZ >= rotY && rotZ >= rotW) { maxAxisRotation = rotZ; }
if (rotW >= rotX && rotW >= rotY && rotW >= rotZ) { maxAxisRotation = rotW; }
float rotSpeed = movingCardSpeed[counter] * 5;
if (rotSpeed > maxAxisRotation) { movSpeed = maxAxisRotation; }
float xRotResult = rotSpeed * (currentRotation.x / maxAxisRotation);
float yRotResult = rotSpeed * (currentRotation.y / maxAxisRotation);
float zRotResult = rotSpeed * (currentRotation.z / maxAxisRotation);
float wRotResult = rotSpeed * (currentRotation.w / maxAxisRotation);

currentTransform.rotation += new Quaternion(xRotResult, yRotResult, zRotResult, wRotResult);

Fairly unsurprisingly, Quaternion (as a method) kicked off, not allowing the modification += to add 2 Quaternions together. You cannot add 2 Quaternions together either (i.e. Quaternion abc = Quat1 + Quat2 ).

Can anyone help me find a way to rotate an object steadily between 2 locations (I have the transform for the current object, a transform for the resultant rotation aim, and a uniform speed that the object is approaching it’s transform destination).

When doing transitions like this, it’s often better to remember the original rotation, rather than just relying on the current rotation. If you have the original rotation, target rotation, transition start time, and transition duration, then you can easily use Quaternion.Slerp() to figure out what the current intermediate rotation between the original and target rotations is, based on how far along the transition duration you’ve come since the start time.

float t = (Time.time - startTime) / duration;
Quaternion currentRotation = Quaternion.Slerp(originalRotation, targetRotation, t);
1 Like

Update: a solution was found to the syntax error, adding the 4 variables to the original quaterion by doing the following:

    Quaternion result = new Quaternion(currentTransform.rotation.x + xRotResult, currentTransform.rotation.y + yRotResult,
                currentTransform.rotation.z + zRotResult, currentTransform.rotation.w + wRotResult);
            print("Card " + currentTransform.GetInstanceID() + " , Quaternion: " + xRotResult + " " + yRotResult + " " + zRotResult + " " + wRotResult);
            currentTransform.rotation = result;

This is outputting Quaternion values of 0,0,0,20 for X,Y,Z and W respectively, and the GameObject is not rotating at all. I definitely feel like I’m approaching this situation from the wrong angle (no pun intended…), anyone have any ideas on how I could rotate in relation to the objects distance from goal (so that it rotates consistently in relation to the distance traveled)? As you might have guessed, my knowledge-base on Quaternions is lacking to say the least.

Quaternion.Slerp sounds like a great tool for this job!I will give it a go at incorporating this into the code, thanks!