- Home /
How do I smooth the movement of three transforms moving at different rates along a single axis?
I'm moving three cubes along their Z axis by their transform component at different rates while having a camera following one of them.
How would I be able to rid of the jerkiness that represents from the other two if they are moving at random rates every update to have all three cubes appear smooth?
using UnityEngine;
using System.Collections;
public class CarControllerAI : MonoBehaviour {
private float speed;
private Transform _endPoint;
void Start() {
//The point we want our transform to reach.
_endPoint = GameObject.FindGameObjectWithTag("FinishLine").GetComponent<Transform>();
//The speed from .1 to 1 for our lerp
speed = Random.Range(.1f, .5f);
}
void Update() {
speed = Random.Range (.1f, .5f);
}
void FixedUpdate() {
transform.position = Vector3.Lerp (transform.position, new Vector3(transform.position.x, transform.position.y, _endPoint.position.z), speed * Time.deltaTime);
}
}
Answer by lordlycastle · Apr 02, 2015 at 10:00 PM
I would recommend you not use Lerp
function to move, as long as you have other options. Most people don’t really understand and freak when get unexpected behaviour. @kingcoyote’s solution will wok if you are using constant speed, but still I wouldn’t use Lerp
. Anyways, if you don’t want to use constant speed then you can use SmoothDamp to move. In that you’ll have to set the smoothTime
using your previous velocity and present velocity.
Vector3 lastSpeed = Vector3.zero;
Vector3 currentSpeed = Vector3.zero;
void Update(){
float newSpeedMagnitude = Random.Range(1, 5);
var deltaTranform = Mathf.Abs((currentSpeed * newSpeedMagnitude - lastSpeed)) * Time.deltaTime;
tansform.positon = Vector3.SmoothDamp(tansform.positon, transform.positon + deltaTranform, currentSpeed, Time.deltaTime);
lastSpeed = currentSpeed * newSpeedMagnitude;
}
I do have to warn you that this isn’t a good way to move either. It’s just suitable for you situation where you are randomly change speed. You probably shouldn’t use random speed, that does give it odd behaviour.
Hope this works out, I haven’t tried it. Comment if it does or not.
This is what gave me the best results, completely smooth and random.
using UnityEngine;
using System.Collections;
public class CarControllerAI : $$anonymous$$onoBehaviour {
private Transform target;
private float smoothTime = .5f;
private float yVelocity = 0.0f;
void Start() {
target = GameObject.FindGameObjectWithTag("FinishLine").GetComponent<Transform>();
}
void Update() {
float speed$$anonymous$$od = Random.Range(0f, 20f);
float newPosition = $$anonymous$$athf.SmoothDamp(transform.position.z, target.position.z, ref yVelocity, 20f % speed$$anonymous$$od, 20f);
transform.position = new Vector3(transform.position.x, transform.position.y, newPosition);
}
}
Your code snippet didn't really work at all for me :/
Answer by kingcoyote · Apr 02, 2015 at 09:30 PM
First off, if they change speed every frame, of course it's going to be jerky! Is that what you really wanted, or did you want each object to move steadily at a random rate that is defined on start?
Second, you might want to change how you are using Vector3.Lerp. That might be a part of your problem. Rather than doing a small, almost fixed size linear interpolate between current position and end position, you should linear interpolate between start and end, and smoothly grow the intermediate value. Like this:
using UnityEngine;
using System.Collections;
public class CarControllerAI : MonoBehaviour {
private float speed;
private float _location;
private Transform _startPoint;
private Transform _endPoint;
void Start() {
//The point we want our transform to reach.
_endPoint = GameObject.FindGameObjectWithTag("FinishLine").GetComponent<Transform>();
// The starting point
_startPoint = transform;
// the speed should be the number of 1/s where s is the
// number of seconds needed to get to the end.
speed = 1 / Random.Range(5, 10);
// default the location to 0
_location = 0;
}
void Update() {
// increment the location based on speed.
_location += speed * Time.deltaTime;
transform.position = Vector3.Lerp(
_startPoint.position,
_endPoint.position),
_location);
}
}
Your solution worked well, some syntax errors; also noticed that it doesn't implicitly widen integers to floats in this compiler? So your 5 and 10 arguments were truncating to 0 :/. Weird stuff, but I have them smoothly moving to a point, yet I'm going to try the other one as well to get random speeds every frame.
using UnityEngine;
using System.Collections;
public class CarControllerAI : $$anonymous$$onoBehaviour {
private float speed;
private float _location;
private Transform _startPoint;
private Vector3 _endPoint;
void Start() {
// The starting point
_startPoint = transform;
//The point we want our transform to reach.
_endPoint = new Vector3(_startPoint.position.x, _startPoint.position.y, GameObject.FindGameObjectWithTag("FinishLine").GetComponent<Transform>().position.z);
// the speed should be the number of 1/s where s is the
// number of seconds needed to get to the end.
speed = 1 / Random.Range(20f, 60f);
// default the location to 0
_location = 0;
}
void Update() {
// increment the location based on speed.
_location += speed * Time.deltaTime;
transform.position = Vector3.Lerp(_startPoint.position, _endPoint, _location);
}
}
Sorry about the compiler errors. I'm not in front of Unity at the moment and had to free hand that. And yeah, the range would truncate to 0 since 1/5, if both are cast as integer types, rounds down to 0. It could also be fixed by changing the 1 to 1.0 or 1f.
Your answer
Follow this Question
Related Questions
Add specific movement on double click 1 Answer
Learning to move 1 Answer
Unity 2D Scripted Movement 2 Answers
Add Force To One Object in Relation to the Rotation of Another Object (C#) 1 Answer
Help using arrow keys to move 1 Answer