boop
boop

Reputation: 7787

How to slow down a sine wave?

I want to program a bouncing ball. The actual bounce shouldn't follow real physic laws but rather build an absolute sine wave. Like in this image

enter image description here

That is pretty easy so far. See the attached code.

However I want to slow down the movement of my ball as soon as I press a button.

I'll reduce the movement speed which will slow down the transformation on the x axis. But the ball is still bouncing pretty fast up and down, because neither frequency nor magnitude of the sine wave has changed. But when I change one or both, this will end in a weird behavior.

Imagine the ball is on the downmove at 20% of the distance from top to bottom. When I now change any sine parameters the ball will instantly move on the y axis which looks really weird and not smooth.

So my actual question is: How can I slow down an absolute sine wave (x/y axis translation) without choppy movement?

float _movementSpeed = 10.0f;
float _sineFrequency = 5.0f;
float _sineMagnitude = 2.5f;

Vector3 _axis;
Vector3 _direction;
Vector3 _position;

void Awake()
{
    _position = transform.position;
    _axis = transform.up;
    _direction = transform.right;
}

void Update()
{
    _position += _direction * Time.deltaTime * _movementSpeed;
    // Time.time is the time since the start of the game
    transform.position = _position + _axis * Mathf.Abs(Mathf.Sin(Time.time * _sineFrequency)) * _sineMagnitude;
}

Upvotes: 2

Views: 3574

Answers (1)

Krzysztof Bociurko
Krzysztof Bociurko

Reputation: 4661

I guess you want this (more red - lower freq, more blue - higher):

A graph of a sine wave in time with changing frequency The easiest way to achieve this is to scale deltatime, for example this was generated with:

using UnityEngine;
using System.Collections;

public class Bounce : MonoBehaviour {

    // for visualisation of results
    public Graph graph;

    [Range(0, 10)]
    public float frequency = 1;

    float t;

    void Update()
    {
        t += Time.deltaTime * frequency;

        float y = Mathf.Abs(Mathf.Sin(t));
        float time = Time.realtimeSinceStartup;

        graph.AddPoint(time, y, Color.Lerp(Color.red, Color.blue, frequency/10));
    }

}

And for the completeness, the Graph class:

using UnityEngine;
using System.Collections.Generic;

public class Graph : MonoBehaviour {

    struct PosAndColor
    {
        public Vector3 pos;
        public Color color;
    }


    List<PosAndColor> values=new List<PosAndColor>();


    public void AddPoint(float x, float y, Color c)
    {
        values.Add(new PosAndColor() { pos = new Vector3(x, y, 0), color = c });
    }


    void OnDrawGizmos()
    {
        for (int i = 1; i < values.Count; i++)
        {
            Gizmos.color = values[i - 1].color;
            Gizmos.DrawLine(values[i - 1].pos, values[i].pos);
        }
    }

}

Another aproach would be to change the frequency with the offset of your sine to match the current amplitude. I don't think you'd need this here, but if you want to I can post some more on the subject.

Upvotes: 1

Related Questions