Fish Tail Movement

Hi all,

I want to move an object in the world like the fish tail by changing its velocity. Due to the logic in my game, I have to change the velocity.

The movement I want is like in this image. (The view is top down)

Simplified version of this is: I spawn an object with a fixed velocity and it should move like the blue line. How much it gets away from the red line should be same for both left and right (“r” in the image). How can I do that by changing the velocity?

Spline as the solution won’t work because I need to move the object with velocity and, how far the object can go depends.

I love code-able motion like this… so much fun to script out!

This “buttonhole” kinda motion could just be parametrically expressed with sine and cosine, driven with speed of motion and rate of angle change.

Check it (full package attached):

using UnityEngine;

// @kurtdekker:
// stick me on a visible object, watch me go fishy fish forward
// we consider our original transform.forward to be +Z forward.
// This is also called a buttonholing motion.

public class TrigFish : MonoBehaviour
{
    // how quickly I move forward locally along the curve
    public float LinearSpeed = 5;

    // how quickly I change my angle
    public float AngularSpeed = 90;

    // TODO: change this in real time to steer me around the world
    public float ForwardAngle = 0;

    void StepRotateAndDrivePositionFromPhase()
    {
        // forward march!
        transform.position += transform.right * (LinearSpeed * Time.deltaTime);

        float angle = phase % 360;

        // are we zigging or are we zagging??
        if (angle < 180)
        {
            angle = 360 - angle;
        }

        // this lets you steer it
        angle += ForwardAngle;

        // this makes it rotate around Y;
        // if you want around Z, put angle in the 3rd spot
        // and use transform.up for the above
        transform.rotation = Quaternion.Euler( 0, angle, 0);
    }

    // this is the accumulator that tracks your cycle around one full buttonhole
    float phase;

    void Update ()
    {
        StepRotateAndDrivePositionFromPhase();

        phase += AngularSpeed * Time.deltaTime;   
    }
}

7601497–943399–TrigFish.unitypackage (45.3 KB)

Thank you for the effort, but I need to change the object’s velocity not its position. Changing its position messes up the physics.

Manipulating velocity to achieve this kind of movement is very hard and unpredictable, but any movement that is close to what I want is okay.

Huh? Not really!!

Steps to success:

  1. Replace this line with the following (in the above):
//        transform.position += transform.right * (LinearSpeed * Time.deltaTime);
        GetComponent<Rigidbody>().velocity = transform.right * LinearSpeed;
  1. Put a Rigidbody in the same GameObject with this Script

  2. Call it all from FixedUpdate() instead of Update().

  3. EDIT: Also probably want to change these lines:

//        transform.rotation = Quaternion.Euler( 0, angle, 0);
        GetComponent<Rigidbody>().MoveRotation(Quaternion.Euler( 0, angle, 0));
1 Like

@Kurt-Dekker It works like a charm. Thank you

1 Like

You’re welcome! I thank my high school Calculus AB teacher, Mr Miki Bowers.