Extended Oscillate script

Sooo… I had a little trouble scaling a quaternion, so I cheated and used eulerAngle… but I added oscillation for rotation and scale to the method using an enum and a switch. Lots of fun. Also got rid of the disallow so you can add multiples for different transforms and periods. Loving this course.

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

//[DisallowMultipleComponent]
public class oscillate : MonoBehaviour
{
    public enum TransformType {position, rotation, scale};
    public TransformType targetTransform = TransformType.position;

    Quaternion
    Vector3 startingPosition;
    Vector3 startingRotation;
    Vector3 startingScale;
    [SerializeField] Vector3 movementVector = new Vector3(10f, 10f, 10f);
    [SerializeField] float period = 2f;

    const float tau = Mathf.PI * 2;
    // [Range(0, 1)] [SerializeField] float movementScale;
    // ^^^^^^^^^^^^^--- the range bit in front adds a slider to the unity UI

    void Start()
    {
        startingPosition = transform.position;
        startingRotation = transform.rotation.eulerAngles;
        startingScale    = transform.localScale;
    }

    void Update()
    {
        if (period <= Mathf.Epsilon) { return; }

        float sinNormalized;
        Vector3 offset;

        switch (targetTransform)
        {
            case (TransformType.position):
                sinNormalized = getSine(true);
                offset = movementVector * sinNormalized;
                transform.position = startingPosition + offset;
                break;

            case (TransformType.rotation): // Can't quite figure out how to scale a quaternion yet.
                sinNormalized = getSine(false);
                offset = movementVector * sinNormalized;
                transform.Rotate(startingRotation + offset);
                break;

            case (TransformType.scale):
                sinNormalized = getSine(true);
                offset = movementVector * sinNormalized;
                transform.localScale = startingScale + offset;
                break;
        }
    }

    float getSine(bool normalize)
    {
        if (period <= Mathf.Epsilon) { return 0f; } // catch a period of 0

        float cycles = Time.time / period;     
        float sin = Mathf.Sin(cycles * tau);

        if (!normalize) { return sin; }
        else { return (sin / 2f) + .5f; }
    }
}
 
2 Likes

You may have cheated but you still did it! Great job man! How did you figure it out?

So just the straight sine function returns a value from -1 to 1 which naturally oscillates.

We had the second line of code which normalized it from 0 to 1 for easy use in position. To take advantage of the natural oscillation, I broke out the sine bits to their own method and added a variable for normalizing or not. sooo if getSine gets passed true (for position and scale), then a normalized value is returned, for false (rotation), I just return the raw data.

As far as figuring out scaling quaternions, I looked into it, and it was a little trickier than I’m quite ready for mathematically… The values in the inspector are euler angles, so I just figured out how to manipulate them directly.

1 Like

Ok, makes sense. Wow how did you know you had to use sine? How long do you spend figuring all of this?

heh. The sine function was part of the lecture, the rest was just a natural progression from there. Didn’t take long at all really.

Privacy & Terms