2D: Need advice on implementing torque in a custom physics engine

Hi guys! So I’m a good way into creating a custom physics engine for my game, and I’ve hit a brick wall regarding rotation and torque. Note that I’m using unity’s supplied collider2D, raycast2D, and kinematic rigidbody2D components for my custom physics.

So the method that makes most sense to me is to fire raycasts from the edges of a physics object’s collider in that object’s direction of motion, and on a collision, calculate the perpendicular distance of the raycast origin from the COM, find torque, and use this to rotate. Obviously the raycasts need to be fired from the edges of the object’s collider (or better, some point inset by the object’s skin width).

Now the biggest problem I foresaw in implementing this was finding the moment of inertia for some complex polygon, I figured I’d use a hack for this by assuming all of the bodies mass is located in some simple shape like a circle or box near the objects COM. But I haven’t even gotten that far, because:

Unity doesn’t provide a method for finding the edges of their colliders when rotated. (Using collider.bounds gives me the axis aligned bounding box, which doesn’t work for a rotated object). I’ve found some techniques for finding the world space coordinates of collider vertices online, from which I could feasibly extract line equations defining the collider edges, use the dot product of edge normal vectors with velocity to determine which edges are facing in the same direction as the object is travelling, then fire a number of raycasts from these points.

That all seems like a crapload of busywork for what I’m feeling should be a simple problem, I am working in 2D after all. Also the number of for loops required for raycasting from each edge of each object using this method makes my head hurt, and is likely to tank my performance. Now the only other alternative I can think of is to create my own box collider scripts and include a method in these for raycasting from the edges, instead of working backwards using the collider methods unity provides. This also sounds like it’ll be a real headache, and I fear this method will end with me needing to create my own scripts for raycast2D and maybe even rigidbody2D as well.

So I need advice on what to do next. Is there a simpler way to do this that I’m not seeing? Or should I bite the bullet and create my own collider scripts?

Colliders live in Rigidbody2D space not world-space so we don’t store them rotated or anything like that so providing a function for you is just something you could do yourself and is pretty trivial to do and I don’t see why it would stop you moving forward.

What I really don’t understand is why you’re using raycast when you can use one of the many Cast queries or the generic Collider2D.Cast method? Maybe you have good reasons not to do this but this will give you the contact point which you can use to perform your own collision resolution.

Note that if you use useFullKinematicContacts then you’ll get callbacks or you can just ask for the contacts between two kinematic/static objects then perform your own collision resolution. You can also use the Distance methods like Physics2D.Distance to give you not only separation but also overlap.

1 Like

Thanks for the reply!

Sorry if this is a trivial problem, finding a (efficient) way to do this has not felt trivial to me! I’m new to unity and I don’t have much coding experience either, but I’m a physics major so I figured creating a physics engine would be a great place to start

So if I’m understanding you correctly, you’re suggesting that I find line equations of the edges relative to the RigidBody2D - then use the rigid body transform to find world space versions of these line equations for the raycasts? As a side note, is there a way to raycast from RigidBody2D space?

I have experimented with Collider2D.Cast back when I started, but I’ve had a bit of trouble wrapping my head around exactly how it works, so I’ve been avoiding them in favour of raycasts (I generally don’t like using a technique, even if it works, unless I understand exactly how it works). But if using Collider2D.Cast is the better method for this problem, then I will revisit it.

I’ve never heard of these, I will check them out.

Thanks for the help!!

I understand and sorry if I “sounded” demeaning. What I was trying to get across is that if you absolutely must be able to have world-space of a collider, you simply transform the geometry into world-space using the Transform component because Unity doesn’t store and update this geometry in world-space. Providing a method to do this doesn’t involve any magic or data that’s not available to you. The most complex one would be a PolygonCollider2D and that involves taking its points and doing a Transform.TransformPoint on it but as I go on to say, I don’t believe you need to do this.

No, I wasn’t suggesting anything like that. Just that if you absolutely must find the extremes of a collider in a direction so you can perform two raycasts then you can calculate that yourself and that, as I said above, this is data you already have and Unity providing a method for you wouldn’t make it any faster.

By Rigidbody2D space I refer to a space defined with no scaling with the origin at the RB position with its rotation around the Z axis. I’m not sure what raycasting in this space would mean apart from raycasting in the angle of the RB but that wouldn’t help as other colliders in the scene attached to other RB are not in that space. I think this is all redundant though.

Box, Circle, Capsule (etc) cast methods all work in exactly the same way i.e. define the respective shape and “cast” it through space and return the first contact encountered. All of them allow you to define the shape (circle is point and radius for instance, box is center and size etc) and then allow you to define a direction and distance you want to virtually sweep the shape through space. It’ll return you the first contact it encounters or nothing if no contact found. If you’re happy with raycast then know that this is effectively Point.Cast i.e. take a point and cast it through space. It returns you the exact same thing. Others just use different geometry than a point; circle, box, capsule, polygon etc.

For Collider2D.Cast, all this does is allow you to work with any Collider2D without having to check the type (Box, Circle, Capsule etc). It figures out the type for you as you call it on an instance of a Collider2D so you don’t need to define the geometry itself, only the direction and distance part. It then returns the same result as described above. The difference here is that you need an instance of a Collider2D whereas the other queries don’t as you define the geometry (circle, capsule, box etc) in the query method itself. There’s also a Rigidbody2D.Cast which will sweep all colliders attached to that Rigidbody2D instance through space returning the first contact point on all those colliders.

The thing is, if you use any of the above methods they all return the same thing as Raycast i.e. RaycastHit2D (unfortunate naming but that’s a historic thing from 3D physics) but in the end it’s the same thing. You can use this using your existing calculations.

1 Like