- Home /
Mathf.SmoothDamp not changing speed (reference variable not changing)
Hi,
I want my moveForwards speed to change from 0f to -2f over 3 seconds if one condition is true, and from 0f to -2f if another condition is true.
So instead of the commented out lines where the speed is set instantly: I would like them to be gradually set to this final speed over 3 seconds.
But I can't get this to work correctly: the speed is just set once to -0.2f (and the reference variable to -27) and doesn't increase. Does anyone know what I've done wrong?
public float moveForwards = 0f;
public float speed2 = 0f;
public float speed1 = 0f;
void Update () {
if (lastspeed < 40f && speedGPS.speedInKmPerHour >= 40f)
{
moveForwards = Mathf.SmoothDamp (moveForwards, -2f, ref speed2, 3f * Time.deltaTime);
//moveForwards = -2f;
}
if (lastspeed >= 40f && speedGPS.speedInKmPerHour < 40f)
{
moveForwards = Mathf.SmoothDamp (moveForwards, 0f, ref speed1, 3f * Time.deltaTime);
//moveForwards = 0f;
}
All the best, Laurien
Edit: This is the working script.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TerrainMover : MonoBehaviour {
public float moveForwards = 0f;
public GameObject terrain1;
public Vector3 targetPos = new Vector3 (0,0 -384);
public GameObject terrain2;
public Speedometer speedGPS;
public PerspectiveSwitcher persp;
public TouchDetect touch;
public GameObject [] terrainMultiples;
private List<GameObject> terrainDeck;
public Vector3 startPos = new Vector3 (0,0,0);
public Vector3 endPos;
static public float speed = 15f;
float lastspeed = 0f;
public float speed2 = 0f;
public float targetSpeed = 0.0f;
void Start()
{
terrainDeck = new List<GameObject>(terrainMultiples);
foreach (var t in terrainMultiples)
{
t.SetActive (false);
}
terrain1 = ChooseTerrain();
terrain1.transform.position = new Vector3 (-4.5f, -16f, 267.5f);
terrainDeck.Remove(terrain1);
terrain2 = ChooseTerrain();
terrain2.transform.position = new Vector3(-4.5f, -16f, 817.5f);
terrainDeck.Remove(terrain2);
terrain1.SetActive(true);
terrain2.SetActive(true);
}
void Update () {
if (lastspeed < 40f && speedGPS.speedInKmPerHour >= 40f)
{
persp.orthoToggle(false);
targetSpeed = -3.5f;
speed2=0;
}
if (lastspeed >= 40f && speedGPS.speedInKmPerHour < 40f)
{
persp.orthoToggle(true);
targetSpeed = 0;
speed2=0;
}
if (Mathf.Abs(moveForwards - targetSpeed) > 0.01f )
moveForwards = Mathf.SmoothDamp (moveForwards, targetSpeed, ref speed2, 3f);
else
moveForwards = targetSpeed;
terrain1.transform.Translate(Vector3.forward * Time.deltaTime * moveForwards * speed);
terrain2.transform.Translate(Vector3.forward * Time.deltaTime * moveForwards * speed);
lastspeed = speedGPS.speedInKmPerHour;
if (Input.GetKeyDown("w"))
speedGPS.speedInKmPerHour = 60f;
if (Input.GetKeyUp("e"))
speedGPS.speedInKmPerHour = 0f;
if (touch.moveToCentre == true)
{
terrain1.transform.Translate(Vector3.forward * Time.deltaTime * - touch.bagCurrentPosFloat * 0.4f);
terrain2.transform.Translate(Vector3.forward * Time.deltaTime * - touch.bagCurrentPosFloat * 0.4f);
}
}
void LateUpdate()
{
if (targetPos.z - terrain1.transform.position.z > - 10f)
{
terrain1.SetActive(false);
terrainDeck.Add(terrain1);
terrain1 = ChooseTerrain();
terrainDeck.Remove(terrain1);
terrain1.transform.position = terrain2.transform.position + new Vector3(0.0f, 0.0f, +550);
terrain1.SetActive(true);
}
else if (targetPos.z - terrain2.transform.position.z > - 10f)
{
terrain2.SetActive(false);
terrainDeck.Add(terrain2);
terrain2 = ChooseTerrain();
terrainDeck.Remove(terrain2);
terrain2.transform.position = terrain1.transform.position + new Vector3(0.0f, 0.0f, +550);
terrain2.SetActive(true);
}
}
GameObject ChooseTerrain()
{
int index = Random.Range (0, terrainDeck.Count -1);
return terrainDeck [index];
}
}
Answer by jlmakes · Jun 09, 2016 at 11:03 PM
Using SmoothDamp
Looking at the pertinent aspects of the SmoothDamp signature:
SmoothDamp(float current, float target, ref float currentVelocity, float smoothTime);
You are multiplying your desired smooth time (i.e. 3f
) by Time.deltaTime
—meaning your smooth time is actually a fraction of your desired smooth time.
If you were to remove your reference to Time.deltaTime
in the 4th parameter, e.g: moveForwards = Mathf.SmoothDamp (moveForwards, -2f, ref speed2, 3f);
I believe you’ll be much closer to the effect you’re after.
Hi - thanks so much for replying! I didn't realise that - I've just removed that now!
But I'm still having the same problem where the speed is set to 0.2 at the first frame and then doesn't update/increase. Am I setting it up correctly by storing the reference variable inside the main class?
It’s perfectly fine to create/use the reference to current velocity the way you have (although they don't need to be public). As far as the usage of SmoothDamp, it appears correct to me (I have a sample project open with it).
You haven’t included the code where you’re applying the motion, so I assume the problem lies there—not with how you’ve implemented $$anonymous$$athf.SmoothDamp
. Perhaps you could update your original question with a slightly larger code sample?
For what it’s worth, you can take this script… attach it to an empty game object, hit play and watch the velocity progress towards 50 over 5 seconds.
using UnityEngine;
using System.Collections;
public class SmoothDamp : $$anonymous$$onoBehaviour
{
public float velocity;
private float velocitySmoothing;
void Update()
{
velocity = $$anonymous$$athf.SmoothDamp(velocity, 50f, ref velocitySmoothing, 5f);
}
}
Thanks so much for posting the code - it's a relief to see I had understood at least that part right! I've posted my full script: I'm still unsure why it's not working in $$anonymous$$e, as it seems to be set up in the same way?
Answer by Bunny83 · Jun 12, 2016 at 05:02 PM
I haven't read through all your code and haven't even tried to understand what it's supposed to do. However those two lines are causing problems:
if (lastspeed < 40f && speedGPS.speedInKmPerHour >= 40f)
and
lastspeed = speedGPS.speedInKmPerHour;
This will make your if statement only true for one frame whenever your speed crosses the 40f mark. SmoothDamp has to be called every frame in order work properly. That method does not "start" some magic code that runs in the background. It just calculates a new value each time you call the method. The "ref" speed variable is used to track the current state of the damping.
That's really great - thanks, I've got it working by moving it all to the update function. (Sorry - only just started picking up program$$anonymous$$g, still not really there yet)
Note: I've updated the movement script in case its helpful for anyone to see the working version!
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
How does Mathf.SmoothDamp's max speed work? 1 Answer
Making a bubble level (not a game but work tool) 1 Answer
Mathf.Lerp not working, why? 1 Answer