I am currently trying out Unity 3D and I've run into a problem. The problem is I have a car that moves along a road and then when it reaches a corner I would like it to turn the corner and have the model rotate based on its current velocity.
Here is the code I have for moving the object forward:
_velocity += (_velocity * Time.deltaTime) + (_acceleration / 2f) * Time.deltaTime * 2f;
_velocity = Mathf.Clamp(_velocity, 0f, MaxVelocity);
Vector3 position = this.transform.position;
position += -this.transform.forward * _velocity * Time.deltaTime;
this.transform.position = position;
The variables are declared as class members:
private const float MaxVelocity = 10;
private float _velocity;
private float _acceleration;
This appears to work OK for moving forward. If I applied a rotation it may look OK for a certain velocity, but if the velocity changes, then the rotation seems to quick or to slow.
What I would like (but completely failing at accomplish) is when it comes time to turn, then I would look at the velocity and calculate a smooth rotation so when an object performs a turn it will always end up at the same point regardless of how quick it approaches the corner.
I have tried a number of options, over countless hours, but I'm not having any luck!
Any ideas?
UPDATE #1:
Below is a half-way solution I got, but for now I will add it here and leave the question open for a bit in case someone can provide a better approach.
From what I worked out a LERP rotation from the current direction to the new direction did the trick (kind of!). So, I created a behaviour called VehicleController
and in the Awake
method I added this:
_target = this.transform.rotation * Quaternion.Euler(0f, 90f, 0f);
This gave me the target rotation relative to my current rotation, i.e. my rotation would have to equal _target
for me to be facing in the desired direction. I then added the following to the FixedUpdate
method:
// Rotate
if(_doTurn)
{
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, _target, Time.fixedDeltaTime * _velocity);
}
This performed the actual rotation. The key part was setting the third parameter Time.fixedDeltaTime * _velocity
. This meant that my rotation speed matched my velocity.
My final FixedUpdate
method looked like this:
// Forward
_velocity += (_velocity * Time.deltaTime) + (_acceleration / 2f) * Time.fixedDeltaTime * 2f;
_velocity = Mathf.Clamp(_velocity, 0f, MaxVelocity);
Vector3 position = this.transform.position;
position += -this.transform.forward * _velocity * Time.fixedDeltaTime;
this.transform.position = position;
// Rotate
if(_doTurn)
{
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, _target, Time.fixedDeltaTime * _velocity);
}
In this sample I had a BoxCollider
that triggered the turn, so in the OnTriggerEnter
method I simply set _doTurn
to true
.
Now there are a few things with this:
- After the turn I had to fix the positioning and rotation a little. The values were off by about .2, but I couldn't really notice any oddness to care.
- This approach gives a quick snap change in direction which wasn't what I was really after. Ideally I wanted a situation where the turn would be gradual at a certain angle and end in the same point. But, to be honest, it looks OK and that gets me moving on for now! :)
With regards to #1 I think I had to fix some of the position/rotation values because I was using a BoxCollider
to trigger the turn so there may be better approaches.
No comments:
Post a Comment