How can i script a wiggle?

Hi folks,

I’m trying to script a “wiggle” like After Effects wiggle expression (After Effects: Create a wiggle effect - YouTube), but i dont have it yet.

So, if i use a Random number, this is going to give me a random number each frame. I do not want this, because the number “jumps” each frame to the new random number. I want an expression that moves my number randomly but also that allows me to control the frequency on time and that my number moves smooth from one to the other random number. Like a lerp.

If you know the After Effects wiggle expression, you are going to know what i am talking about.

I would appreciate any help.

Hi, here’s a little wiggle script I knocked up…

My first Script in Unity, and it seems to work… Crikey!!.

Just attach the script to any object,.

Set the curve you want to use, eg. Linear, ease-in, ease-out

Set what you want to Wiggle by in the Distance, you can make it wiggle in the x,y & z.

Set the speed, eg. 0.5 would wiggle 2 times a second.

using UnityEngine;
using System.Collections;

public class Wiggle : MonoBehaviour {

	public AnimationCurve curve;
	public Vector3 distance;
	public float speed;

	private Vector3 startPos, toPos;
	private float timeStart;

	void randomToPos() {
		toPos = startPos;
		toPos.x += Random.Range(-1.0f, +1.0f) * distance.x;
		toPos.y += Random.Range(-1.0f, +1.0f) * distance.y;
		toPos.z += Random.Range(-1.0f, +1.0f) * distance.z;
		timeStart = Time.time;
	}

	// Use this for initialization
	void Start () {
		startPos = transform.position;
		randomToPos();
	}
	
	// Update is called once per frame
	void Update () {
		float d = (Time.time - timeStart) / speed, m = curve.Evaluate(d);
		if (d > 1) {
			randomToPos();
		} else if (d < 0.5) {
			transform.position = Vector3.Lerp(startPos, toPos, m * 2.0f);
		} else {
			transform.position = Vector3.Lerp(toPos, startPos, (m - 0.5f) * 2.0f);
		}
	}
}

If anyone is still interested, I created a fairly simple non-linear wiggle:

public float speed = 1;
public float amplitude = 2;
public int octaves = 4;

Vector3 destination;
int currentTime = 0;

void FixedUpdate ()
{
	// if number of frames played since last change of direction > octaves create a new destination
	if (currentTime > octaves)
	{
		currentTime = 0;
		destination = generateRandomVector(amplitude);
		print("new Vector Generated: " + destination);
	}
		   
	// smoothly moves the object to the random destination
	transform.position = Vector3.SmoothDamp(transform.position, destination, ref vel, speed);

	currentTime++;
}

// generates a random vector based on a single amplitude for x y and z
Vector3 generateRandomVector(float amp)
{
	Vector3 result = new Vector3();
	for (int i = 0; i < 3; i++)
	{
		float x = Random.Range(-amp, amp);
		result *= x;*
  • }*
  • return result;*
    }

cowemoji’s had a few issues for me, so I’ve cleaned it up, given you the choice to loop back or not, and removed any issues with signed/unsigned rotations

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

public class Wiggle : MonoBehaviour
{
    [Header("Animation Size")]
    public float animationLoopTime = 1.0f;
    public float posRange = 2.0f;
    public float rotRange = 1.0f;

    [Header("Settings")]
    public bool noZMove = true;
    public bool shouldReturnToStart = false;
    public bool lockRotToZ = false;

    Vector3 initPos, initRot, startPos, startRot, endPos, endRot;
    float timePassed;

    // Use this for initialization
    void Start()
    {
        initPos = startPos = transform.position;
        initRot = startRot = transform.localRotation.eulerAngles;

        SetNewPositions();
    }

    float RandomFromOrderCorrectedRange(float a, float b)
    {
        if (a > b)
        {
            return Random.Range(b, a);
        }
        else
        {
            return Random.Range(a, b);
        }
    }

    void SetNewPositions()
    {
        if (shouldReturnToStart)
        {
            startPos = initPos;
            startRot = initRot;
        }
        else
        {
            startPos = transform.position;
            startRot = transform.localRotation.eulerAngles;
        }

        endPos = new Vector3(
              RandomFromOrderCorrectedRange(initPos.x - posRange, initPos.x + posRange),
              RandomFromOrderCorrectedRange(initPos.y - posRange, initPos.y + posRange),
              noZMove ? 0 : RandomFromOrderCorrectedRange(initPos.z - posRange, initPos.z + posRange)
          );

        endRot = new Vector3(
            lockRotToZ ? 0 : RandomFromOrderCorrectedRange(initRot.x - rotRange, initRot.x + rotRange),
            lockRotToZ ? 0 : RandomFromOrderCorrectedRange(initRot.y - rotRange, initRot.y + rotRange),
            RandomFromOrderCorrectedRange(initRot.z - rotRange, initRot.z + rotRange)
        );
    }

    // Update is called once per frame
    void Update()
    {
        timePassed += Time.deltaTime / animationLoopTime;



        if (timePassed < 0.5f)
        {
            transform.position = Vector3.Lerp(startPos, endPos, timePassed * 2f);
            transform.localRotation = Quaternion.Lerp(Quaternion.Euler(startRot), Quaternion.Euler(endRot), timePassed * 2f);
        }
        else if (shouldReturnToStart && timePassed < 1.0f)
        {
            // tween back
            float pct2 = (1.0f - timePassed) * 2f;
            transform.position = Vector3.Lerp(startPos, endPos, pct2);
            transform.localRotation = Quaternion.Lerp(Quaternion.Euler(startRot), Quaternion.Euler(endRot), pct2);

        }
        else if (!shouldReturnToStart || timePassed >= 1.0f)
        {
            timePassed = 0;
            SetNewPositions();
            return;
        }

    }
}

Here’s another one for anyone from Google

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

public class wiggle : MonoBehaviour {

	float startTime;
	public float animDur = 1.0f;

	Vector3 startPos, endPos;
	public float posRange = 2.0f;
	public bool noZMove = true;

	Vector3 startRot, endRot;
	public float rotRange = 1.0f;
	public bool lockRotToZ = false;

	// Use this for initialization
	void Start()
	{
		startPos = transform.position;
		startRot = transform.eulerAngles;

		makeNewEnds();
	}

	float randomRange(float a, float b)
	{
		if (a > b)
		{
			return Random.Range(b, a);
		}
		else
		{
			return Random.Range(a, b);
		}
	}

	void makeNewEnds()
	{
		startTime = Time.time;

		endPos = new Vector3(
			randomRange(startPos.x-posRange, startPos.x+posRange),
			randomRange(startPos.y-posRange, startPos.y+posRange),
			noZMove? 0 : randomRange(startPos.z-posRange, startPos.z+posRange)
		);

		endRot = new Vector3(
			lockRotToZ? 0 : randomRange(startRot.x-rotRange, startRot.x+rotRange),
			lockRotToZ? 0 : randomRange(startRot.y-rotRange, startRot.y+rotRange),
			randomRange(startRot.z-rotRange, startRot.z+rotRange)
		);
	}

	// Update is called once per frame
	void Update()
	{
		float timePassed = Time.time - startTime;
		float pctComplete = timePassed / animDur;

		if (pctComplete >= 1.0f)
		{
			makeNewEnds();
			return;
		}

		if (pctComplete < 0.5f)
		{
			transform.position = Vector3.Lerp(startPos, endPos, pctComplete*2f);
			transform.eulerAngles = Vector3.Lerp(startRot, endRot, pctComplete*2f);
		}
		else
		{
			// tween back
			float pct2 = (1.0f - pctComplete) * 2f;
			transform.position = Vector3.Lerp(startPos, endPos, pct2);
			transform.eulerAngles = Vector3.Lerp(startRot, endRot, pct2);
		}
	}
}