Rocking Boat Script -- Can be made better, can you help?

I’ve written a script to rock a boat, side to side, front to back and up and down. However, it could be made better, more efficient I’m sure.

One thing that would help is to have it dampen near the edges of the min/max, so it’s more “wave” like, rather than back and forth ping-pong like.

Anyone want to help modify it?

#pragma strict

var heightMax			: float		= 1.0;			// Maximum up and down
var sideMax				: float		= 25.0;			// Maximum rotation side to side
var frontMax			: float		= 10.0;			// Maximum rotation front to back
var heightSpeed			: float		= 0.5;			// Speed of waves
var rockSpeed			: float		= 1.0;			// Speed of rocking
var speedVariable		: float		= 0.2;			// Variable of speeds.

var curSideSpeed		: float;
var curFrontSpeed		: float;
var curHeightSpeed		: float;

var sideVariable		: float;
var frontVariable		: float;
var heightVariable		: float;

var curSideMultiplier	: int	= 1;
var curFrontMultiplier	: int	= 1;
var curHeightMultiplier	: int	= 1;

var startPosition		: Vector3;
var startRotation		: Vector3;

var curSideDif			: float;
var curFrontDif			: float;

function Start () {
	startPosition 	= transform.position;
	startRotation 	= transform.eulerAngles;
	sideVariable	= rockSpeed + Random.Range(-speedVariable, speedVariable);
	frontVariable	= rockSpeed + Random.Range(-speedVariable, speedVariable);
	heightVariable	= heightSpeed + Random.Range(-speedVariable, speedVariable);
}

function Update () {
	// Height of boat
	transform.position.y 	+= Time.deltaTime * heightVariable * curHeightMultiplier;
	
	// Side to side rocking
	curSideDif				+= Time.deltaTime * sideVariable * curSideMultiplier;
	transform.eulerAngles.x = startRotation.x + curSideDif;
	
	// Front to Back rocking
	curFrontDif				+= Time.deltaTime * frontVariable * curFrontMultiplier;
	transform.eulerAngles.z = startRotation.z + curFrontDif;
	
	// Check Max
	if (transform.position.y 	>= startPosition.y + heightMax)
	{
		curHeightMultiplier 	= -1;
		heightVariable			= heightSpeed + Random.Range(-speedVariable, speedVariable);
	}
	if (transform.position.y 	<= startPosition.y - heightMax)
	{
		curHeightMultiplier 	= 1;
		heightVariable			= heightSpeed + Random.Range(-speedVariable, speedVariable);
	}
	if (curSideDif			 	>= sideMax)
	{
		curSideMultiplier 		= -1;
		sideVariable			= rockSpeed + Random.Range(-speedVariable, speedVariable);
	}
	if (curSideDif 				<= -sideMax)
	{
		curSideMultiplier 		= 1;
		sideVariable			= rockSpeed + Random.Range(-speedVariable, speedVariable);
	}
	if (curFrontDif			 	>= frontMax)
	{
		curFrontMultiplier 		= -1;
		frontVariable			= rockSpeed + Random.Range(-speedVariable, speedVariable);
	}
	if (curFrontDif 			<= -frontMax)
	{
		curFrontMultiplier 		= 1;
		frontVariable			= rockSpeed + Random.Range(-speedVariable, speedVariable);
	}
}

I think you would be better off using iTween (iTween | Animation Tools | Unity Asset Store) or one of its relatives.

I wanted to do this all in script. It actually works quite well - the script above, but could just be a bit better if it wasn’t’ so sharp when it changed directions.

Here’s a video with the script working – skip to maybe 60 seconds for it:

https://vimeo.com/87328541

Nice video.

iTween is ‘all in script’. And it would solve the jerky movements.

TheRealBanbury is right, iTween gives you a lot of math functions for free which will do exactly what you want. Why re-invent the wheel?

Then I’d rephrase: I’d like to do it without 3rd party tools. I’d like to have written a script myself / with community help, learning in the process how to do it. Not saying that iTween won’t work, just that I’d like to know how to do it with code instead. Not reinventing the wheel, just learning how to build the wheel without the fancy power tools :slight_smile:

Mayhaps it would then be wise to look into easing functions that are used in these tweening tools so that you may get the desired motion.

This could serve as the text book definition of ‘reinventing the wheel’ :). It’s well enough, if you want to learn about tweening. But when working on a real project, I advise against it. As a general rule, a self written solution is always inferior to an established existing solution.
To stay within the wheel analogy, you may be able to create a wheel without power tools, but it will prove to be an uncomfortable ride once it’s installed on your carriage.

I learn by doing, and am not employed by someone else, so I suppose I can take the time, the risks, and all that, in order to learn something :slight_smile:

Hey all, I smoothed the motion in your code using Lerps and converted the code to c#. Incase anyone finds this like I did here is this version:

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

public class Bob : MonoBehaviour
{



   public float heightMax = 1.0f;          // Maximum up and down
   public float sideMax = 25.0f;         // Maximum rotation side to side
   public float frontMax = 10.0f;         // Maximum rotation front to back
   public float heightSpeed = 0.5f;          // Speed of waves
   public float rockSpeed = 1.0f;          // Speed of rocking
   public float speedVariable = 0.2f;          // Variable of speeds.
   public float curSideSpeed;
   public float curFrontSpeed;
   public float curHeightSpeed;
   public float sideVariable;
   public float frontVariable;
   public float heightVariable;
   public int curSideMultiplier = 1;
   public int curFrontMultiplier = 1;
   public int curHeightMultiplier = 1;
   public Vector3 startPosition;
   public Vector3 startRotation;
   public float curSideDif;
   public float curFrontDif;

    void Start()
    {
        startPosition = transform.position;
        startRotation = transform.eulerAngles;
        sideVariable = rockSpeed + Random.Range(-speedVariable, speedVariable);
        frontVariable = rockSpeed + Random.Range(-speedVariable, speedVariable);
        heightVariable = heightSpeed + Random.Range(-speedVariable, speedVariable);
    }

    void Update()
    {
        // Height of boat
        transform.position.Set(transform.position.x, transform.position.y + Time.deltaTime * heightVariable * curHeightMultiplier, transform.position.z);

        // Side to side rocking
        curSideDif += Time.deltaTime * sideVariable * curSideMultiplier;
        // Front to Back rocking
        curFrontDif += Time.deltaTime * frontVariable * curFrontMultiplier;
        transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(new Vector3(startRotation.x + curSideDif, transform.eulerAngles.y, startRotation.z + curFrontDif)),0.01f);




        // Check Max
        if (transform.position.y >= startPosition.y + heightMax)
        {
            curHeightMultiplier = -1;
            heightVariable = heightSpeed + Random.Range(-speedVariable, speedVariable);
        }
        if (transform.position.y <= startPosition.y - heightMax)
        {
            curHeightMultiplier = 1;
            heightVariable = heightSpeed + Random.Range(-speedVariable, speedVariable);
        }
        if (curSideDif >= sideMax)
        {
            curSideMultiplier = -1;
            sideVariable = rockSpeed + Random.Range(-speedVariable, speedVariable);
        }
        if (curSideDif <= -sideMax)
        {
            curSideMultiplier = 1;
            sideVariable = rockSpeed + Random.Range(-speedVariable, speedVariable);
        }
        if (curFrontDif >= frontMax)
        {
            curFrontMultiplier = -1;
            frontVariable = rockSpeed + Random.Range(-speedVariable, speedVariable);
        }
        if (curFrontDif <= -frontMax)
        {
            curFrontMultiplier = 1;
            frontVariable = rockSpeed + Random.Range(-speedVariable, speedVariable);
        }
    }
}
2 Likes
using UnityEngine;
using System.Collections;

public class bob : MonoBehaviour
{
    [Space(20)]
    #region movement
    public float offset_lerp=5;

    public Vector3 move_wave_amp=new Vector3(0.1f,0.1f,0.1f);
    public Vector3 move_speed=new Vector3(5f,5f,5f);
    public Vector3 move_clamp=new Vector3(0.5f,0.5f,0.5f);
    #endregion

    [Space(20)]
    #region rotation
    public float rotate_lerp=5;
   
    public Vector3 rotate_wave_amp=new Vector3(10f,10f,10f);
    public Vector3 rotate_speed=new Vector3(5f,5f,5f);
    #endregion
   
    void Update ()
    {

        //movement
        float offx=move_wave_amp.x*Mathf.Sin ((Mathf.PerlinNoise (Time.time,1) *move_speed.x));
        float offy=move_wave_amp.y*Mathf.Sin ((Mathf.PerlinNoise (Time.time,2) *move_speed.y));
        float offz=move_wave_amp.z*Mathf.Sin ((Mathf.PerlinNoise (Time.time,3) *move_speed.z));
               
        Vector3 movement=Vector3.Lerp(transform.position,new Vector3(offx,offy,offz),Time.deltaTime*offset_lerp);
        movement.x=Mathf.Clamp (movement.x,-move_clamp.x,move_clamp.x);
        movement.y=Mathf.Clamp (movement.y,-move_clamp.y,move_clamp.y);
        movement.z=Mathf.Clamp (movement.z,-move_clamp.z,move_clamp.z);
        transform.position=movement;

        //rotation
        float rotx=rotate_wave_amp.x*Mathf.Sin ((Mathf.PerlinNoise (Time.time,4) *rotate_speed.x));
        float roty=rotate_wave_amp.y*Mathf.Sin ((Mathf.PerlinNoise (Time.time,5) *rotate_speed.y));
        float rotz=rotate_wave_amp.z*Mathf.Sin ((Mathf.PerlinNoise (Time.time,6) *rotate_speed.z));
       
        Quaternion rotation=Quaternion.Lerp(transform.rotation,Quaternion.Euler (rotx,roty,rotz),Time.deltaTime*rotate_lerp);
        transform.rotation=rotation;
       
    }

}