- Home /
2D Newtonian Braking Acceleration
The Scenario:
I have a 2D ship AI which needs to rotate around the z axis to face its target. All over the ship are thrusters (empties). The script must use Rigidbody2D.AddForceAtPosition() in the Update() or FixedUpdate() methods to move and rotate the ship. The ship is restricted to a maximum torque, which is calculated per thruster using the following at Start():
angularForce = 0f;
foreach (Transform t in ThrusterParent) {
if (t.GetComponent<P_Thruster>()) {
P_Thruster tp = t.GetComponent<P_Thruster>();
Thrusters.Add(tp);
if (tp.roll == 1) { // Dealing with rightward rotation only
// Calculate angularForce (additive)
float effectiveness = 0f;
if (tp.y != 0) { // If we can push upwards
effectiveness = Mathf.Abs(tp.transform.localPosition.x);
}
if (tp.x != 0) { // If we can push rightwards
effectiveness = Mathf.Abs(tp.transform.localPosition.y);
}
angularForce += effectiveness * tp.Force * Mathf.Sin(Vector2.Angle(tp.transform.forward, transform.right)); // Torque formula
}
}
}
Feel free to suggest ways to clean up the code above. It looks chunky and clumsy to me as it stands. When output is sent, and there is still movement/rotation, the AI's script sends outputs to the thrusters to stop motion.
The Problem:
Using a kinematic equation, it is perhaps easy to work things out such as braking distance and stopping distance, but those values have displacement as the subject. Instead, I need acceleration to be the subject.
For a stationary target, that is perhaps behind the AI, it is safe to say that the AI can apply maximum torque and then apply opposing torque at halfway to come to a stop, facing its target. But when the target is moving, such an assumption is no longer relevant.
Presently, I get the angle between the AI and the target, and clamp that to 0 and 1. This works, but the AI ship ends up 'oscillating' - as it's rotation passes its target, it applies opposing force, and goes back the other way, like a pendulum. Instead, the AI needs to output a constantly updating torque.
I'm thinking I'm just overlooking things and the answer is really simple. Hopefully someone can help me out.
Unrelated question: How do I add line breaks to my question? I already tried using the enter/return key, but it seems to have ignored it. The $$anonymous$$arkup help also says to use double space, but it's ignored that too...
I use 2 line breaks then --- then 2 line breaks again. $$anonymous$$akes a nice large break.
Like that
Your first code actually seems like the cleanest I can think of, so that's good. As for the kinematics in the second one, that seems a little more complicated. I'd say recalculate the target angle every tick and use the maximum angular acceleration and the current angular velocity to calculate when you should start slowing down. Like the d=v^2/(2a) but the angular one that I forgot. It'll be a bit of a monster in 3d too.
Thanks. The line break trick works nicely.
As for the formula: I have tried that kinematic equation, but the tricky thing is that a form of acceleration needs to be on both sides. The output acceleration is the subject, and the maximum acceleration goes on the right side of the equation. D:
I don't think this should have much to do with angular equations because this theoretically is still occurring on a linear scale. It's just applying an acceleration on a velocity to reach a displacement. Thankfully this is only in 2D!
You can also add paragraphs by writing:
"LEFT ARROW"br"RIGHT ARROW" Your paragraph. "LEFT ARROW"/br"RIGHT ARROW"
But... Don't take that LEFT and RIGHT ARROW so seriously. You're not meant to write that as is but rather to use the left and right arrows for html code ins$$anonymous$$d.
Don't forget, always add "one enter of space" between each paragraph, otherwise this won't work. :)
Answer by Bunny83 · Jul 25, 2018 at 03:52 PM
This is wrong:
Mathf.Sin(Vector2.Angle(tp.transform.forward, transform.right))
It should be
Mathf.Sin(Vector2.Angle(tp.transform.forward, transform.right) * Mathf.Deg2Rad)
Note that calculating the required thruster force to actually apply only a torque on an irregular object is quite difficult. Keep in mind that linear forces that are applied off-center create both, linear acceleration as well as an angular acceleration. Also keep in mind that the angular acceleration depends on the inertia tensor.
Finally i like to add that Unity's physics system
does not preserve
angular momentum. It just preserves angular velocity. This might actually make it a bit easier
edit
I just realized that we talk about 2d physics ^^.
$$anonymous$$ight I ask for an explanation as to why it is wrong? Also this is a method that additively calculates the total available torque, but does not function to instruct the AI how to properly face its target using variable torque.
Vector2.Angle returns an angle in degree (0 - 180°) while all trigonometric functions take an angle in radians (0 - 2PI)
$$anonymous$$athf.Deg2Rad == $$anonymous$$athf.PI / 180f;
$$anonymous$$athf.Rad2Deg == 180f / $$anonymous$$athf.PI;
Okay, thank you for the correction. In your response to the question, you state that it is difficult to apply only a torque on an irregular object, as it also generates a linear acceleration. I am aware of this and have another method of counteracting motion, which works as intended. $$anonymous$$y initial question asks for how to manage required acceleration to face a target.
Your answer
Follow this Question
Related Questions
How to make object bounce from one bound to another? 0 Answers
Coroutine not working properly 1 Answer
Is it recommended to do scientific modelling in unity or should i write a standalone program 3 Answers
Need help with my movement script.. :( 1 Answer
Inconsistent gravity/random forces/solver problem? (forum crosspost) 0 Answers