- Home /
Calculate a wanted velocity/direction?
Say I have a GameObject with a ridgidbody that is motionless. Given a direction and a force I use addforce() to accelerate the object in that direction. When the GameObject reaches a max velocity the force is no longer applied and the GameObject drifts along its path.
Now say I want to change direction, currently I'm using the ridgidbody's drag setting to counteract the inertia. This works fine, but the problem is how do I determine when the GameObject is traveling in the new direction. I want the drag to be 0 when the GameObject is traveling in the correct direction so that I don't have to apply force to keep the object up to speed and the drag to only be applied while the GameObject is changing direction.
Hope i made that clear enough to understand, Thanks.
Update:
This is called in FixedUpdate()
wantedDirection is a raycast direction from the mouse when no object or destination vector is given.
direction = Vector3.MoveTowards(direction, wantedDirection, turnSpeed * Time.deltaTime);
targetRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
if (Vector3.Angle(direction, rigidbody.velocity) < 0.01f)
rigidbody.drag = 1.0f;
else
rigidbody.drag = 0.0f;
if(currentSpeed < currentTopSpeed ){
rigidbody.AddForce(direction * acceleration, ForceMode.Acceleration);
}
Looks to me like you want to use 'wantedDirection' ins$$anonymous$$d of 'direction' on line 5. Depending on your goals, that may also be true on line 11. In fact, this code is a bit like the cart dragging the horse. I'd probably do it this way:
if (Vector3.Angle(wantedDirection, rigidbody.velocity) > 0.01f)
rigidbody.drag = 1.0f;
else
rigidbody.drag = 0.0f;
if (currentSpeed < currentTopSpeed) {
rigidbody.AddForce(wantedDirection * acceleration, Force$$anonymous$$ode.Acceleration);
}
transform.rotation = Quaternion.LookRotation(rigidbody.velocity);
You'll have to adjust 'drag' as appropriate to your situation. And I had the comparison or the 'if' backwards in the original answer.
I had the slerp for the rotation because the ship was "snaping" to the new direction rather than gradually rotating around.
The code sort of works, but once the top speed is reached the force is no longer applied and the drag always remains at 0 after the first click, so there is no drag to slow the ship down to then apply the force in the correct direction.
Actually the drag flickers between 0 and 1 after I first set the direction and then once the direction is changed again it stays at 0.
$$anonymous$$y code suggestion won't make it snap. The rotation follows the ship rather than the force following the rotation. If it is rotating too fast then lower the drag.
You need to debug the flicker. Start by outputting the Angle calculated each frame.
float angle = Vector3.Angle(wantedDirection, rigidbody.velocity);
Debug.Log(angle);
I would assume resetting drag frequently would work, but as an alternate, you could set Drag to 0.0, and do:
if (Vector3.Angle(wantedDirection, rigidbody.velocity) > 0.01f)
rigidbody.velocity *= 0.99;
Adjust the '0.99' as appropriate, but it needs to be near but less than 1.0.
The same angle calculation can work for both:
bool turning = Vector3.Angle(wantedDirection, rigidbody.velocity) > 0.01f;
then:
if (turning)
rigidbody.drag = 1.0f;
else
rigidbody.drag = 0.0f;
and:
if (currentSpeed < currentTopSpeed || turning) {
rigidbody.AddForce(wantedDirection * acceleration, Force$$anonymous$$ode.Acceleration);
}
The only problem I can see is that you can come out of the turn with a higher velocity than your 'currentTopSpeed'. One solution would be to modify the drag clause:
if (turning || currentSpeed > currentTopSpeed)
rigidbody.drag = 1.0f;
else
rigidbody.drag = 0.0f;
That way the drag would stay on until the speed was again below 'currentTopSpeed'.
Answer by robertbu · Dec 20, 2013 at 08:59 PM
You can use either Vector3.Angle() or Vector3.Dot() to determine if the ship is going in the same direction as the force is being applied.
if (Vector3.Angle(forceDirection, rigidbody.veloicty) > 0.01f)
rigidbody.drag = 2.0f;
else
rigibody.drag = 0.0f;
I tried this code; the first time I set a destination the drag set correctly, after that it remained at 0. I updated my question with some code.
I just posted more info as a comment to your question. The primary issue was that the 'if' comparison was backwards. Fixed now.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
How do I use addforce relative to a parent's rotation 0 Answers