- Home /
Translating a rigidbody smoothly
Hello,
I have a car, which is a rigidbody, and it's moving on the Z axis only. I wish to change lanes on the press of a button. So for example; the car is now driving on x:220, when i press a button, the car moves to x:215. Now, moving the car to that position is not really a problem, but i want it to look smooth, so it kinda steers towards it, and doesn't lose speed or anything, and it will stay on x:215 until i switch again. I can't find anything about translating rigidbodies smoothly, except the lerp function, which does not quite do what i want.
Can anyone point me in the right direction? Any help is appreciated!
Answer by aldonaletto · Feb 27, 2012 at 12:34 AM
Doing this with forces is very complex - you would have to write a PID controller, and it's not easy to adjust its parameters. A much easier way to do that is using Mathf.MoveTowards:
var sideSpeed: float = 2.5; var xPosition: float;
function Start(){ xPosition = transform.position.x; }
function FixedUpdate(){ var pos = rigidbody.position; pos.x = Mathf.MoveTowards(pos.x, xPosition, sideSpeed * Time.deltaTime); rigidbody.position = pos; } This will smoothly move the rigidbody in the X axis only to the desired xPosition. To change the car to a lane 5 meters to the right, for instance, just do this:
xPosition -= 5;
and the car will move at sideSpeed meters per second to the new coordinate.
If you want a smoother change, use Lerp instead:
pos.x = Mathf.Lerp(pos.x, xPosition, sideSpeed * Time.deltaTime);
The car will not move at constant speed, but in a constant time: it will start moving fast, and reduce the lateral speed slowly when reaching the desired position, taking the same time no matter how far the new lane is. Just to give you an idea, sideSpeed = 5 will move the car to the new lane in about 1 second.
NOTE: The car will not steer to the new lane; you can fake this steering by changing the car rotation based on the distance pos.x->xPosition:
...
pos.x = Mathf.MoveTowards(pos.x, xPosition, sideSpeed * Time.deltaTime);
rigidbody.position = pos;
// adjust this number to get the desired angle:
var angle = (xPosition - pos.x) * 2.3;
transform.eulerAngles = Vector3(0, angle, 0);
...
Thanks for the answer, this works pretty well, except for the fact that my car is locked to 1 driving line, so this code still can't move the car. If i remove the axis lock, it works like a charm, but then a new problem arises, the car won't continue on a straight line.
This is the code i use for the axis lock, do i have to make it 4 times, for each of the lanes, or is there a easier/cleaner way? It would be best if i could just use A or Z and the car will move 5 meters left or 5 meters down, and then stay locked to that line.
if(transform.localPosition.x != 220){ transform.localPosition.x = 220;}
You can remove your position lock code and let physics do the job for you: set Freeze Position X and Y under Rigidbody/Constraints in the Inspector (set Freeze Rotation X Y and Z too) - physics will only move the rigidbody in the Z axis, but you can move it with the script above. This way you can move the car using the A and Z keys as you want:
var curLane = 0; var maxLanes = 4;
function Update(){ if (curLane > 0 && Input.Get$$anonymous$$eyDown("a")){ xPosition -= 5.0; curLane--; } if (curLane < maxLanes && Input.Get$$anonymous$$eyDown("z")){ xPosition += 5.0; curLane++; } }
It works now, thank you very much for the explanation. :)
which method finally solved this for you? I have pretty much exactly the same problem
Your answer
Follow this Question
Related Questions
Airplane smooth acceleration problem 0 Answers
Moving objects with attached colliders not colliding? 1 Answer
What's the best move/rotate method to simulate a herd of animals moving around? 2 Answers
Rigidbody Movement 1 Answer
Aligning a rigidbody smoothly with the perpendicular of a vector angle 0 Answers