Is there a way to kill all right velocity with forces without setting the velocity manually? I can do it by setting the velocity directly but it affects the simulation as Unity states in the manual. I tried to do it with forces but its not working, I thought this should work: float lateralAcceleration = RightVelocity().magnitude; Vector3 lateralDownforce = RightVelocity().normalized * lateralAcceleration; rb.AddForce(-lateralDownforce); // function to return right velocity only. Vector3 RightVelocity() { return transform.right * Vector3.Dot(rb.velocity, transform.right); }
Actually I did a little more research and discovered how velocity is added. I think if the addForce line is changed to this: rb.AddForce(-lateralDownforce * RightVelocity().magnitude * (50 * rb.mass)); that seems to be working. If anyone knows for sure can you confirm that this is a correct way of doing it? I would appreciate it.
I don't know if what you did there is correct or not(but if it works it works, it's all smoke & mirrors anyway), but i would use a PID controller to kill sideways velocity. also, please use code tag. https://forum.unity.com/threads/using-code-tags-properly.143875/
AddForce has a mode flag that allows you to apply delta-v directly: Code (CSharp): rb.AddForce(-Vector3.Dot(rb.velocity,rb.transform.right), ForceMode.VelocityChange) In theory this way you don't need to know anything like the mass, integration method, etc. However, I have found even the call: Code (CSharp): rb.AddForce(-rb.velocity, ForceMode.VelocityChange) Does not actually *completely* cancel the velocity*. I don't know why (perhaps its adding the drag to it before applying or something?) but I'll post back if I figure it out. *as a minimal working example, create a plane with a slight incline, put a cube on it, give a physics material with no friction, then make a script that applys the above and watch the cube slide ever so slowly down the plane...
I was able to kill my right velocity but I tried your code just to see if I could condense it to one line and I'm getting an error cannot convert from float to UnityEngine.Vector3
You're welcome! I thought about this some more and identified where the error comes from as well. The rb.Velocity member describes the velocity as a result of the position change over the last frame (not the velocity for the current frame being simulated), so, if the next frame is x+1 = x + vdt + adt*dt cancelling the velocity will make v zero, but won't affect any accelerations incurred during the frame... such as the acceleration due to gravity. So, in addition to cancelling velocity, its necessary to counteract any forces in the direction of interest. PhysX does not provide an api to get these for any particular rigid body, so you need to estimate them yourself from what you know about the scene. In my code, I cancel the velocity as above, and in addition cancel gravity: Code (CSharp): var g_acceleration = Vector3.Dot(Physics.gravity, right) * right; var g_force = g_acceleration * (rigidBody.mass / wheelsInContact); rigidBody.AddForce(-g_force, ForceMode.Force); Obviously with appropriate limits to avoid, e.g. a car climbing a vertical face or something!
Just me wondering, why do you wanna do it with forces? you could also get the velocity as a local vector, make x = 0 and convert it back to world space and assign it back. Code (CSharp): Vector3 vel = transform.InverseTransformVector(rb.velocity); vel.x = 0.0f; rb.velocity = transform.TransformVector(vel); *untested.
That's exactly what I did. It works but it effects the simulation somehow as Unity states, mainly from what I can tell is the gravity. I found a way to "not mess with gravity" but I can tell it still is not the same when I mess with the velocity directly. For example when my car goes airborne it might float for a while and spin and then come back down. If I just use forces it appears as if gravity is fully simulated as intended.