So I’ve added a Point Effector to a certain enemy type (lets call him enemy pusher) with the idea that when the collider it’s tied to hits another enemy, it adds some force to repel the other enemy away. I’ve tested it - as seen in the video - with a circle object with a circle collider + RB being pushed by the enemy pusher, so I know that works. However it doesn’t seem to push the other enemies away, so what ends up happening is the enemy pusher type ends up staying behind other enemies, and slowing his overall speed in relation to their max speed towards the player. I’m wondering if these aren’t being pushed because it’s conflicting with the logic that’s adding force to the RB to get the enemies moving towards the player at all times this code being:
I swapped it out for a Area Effector instead, pushing enemies at a 90 angle (which I may need to tweak). I assigned this enemy type a new Layer of Enemy Push, updated my collision matrix where appropriate and also added a Collider Mask to the Effector so that only other non-pusher types of enemies get pushed (pushers don’t start pushing themselves)
Here’s the result if anyone is interested, not perfect yet, but heading in right direction.
Effectors add forces to the Rigidbody2D. Using explicit movement on the Rigidbody2D isn’t something that is compatible with explicit movement because you’re actively trying to move it to a specific position. It’s like saying move to A but also, effector, move to B. Yes, it’ll “sort of” work just like gravity will “sort of” work but it’s a conflicting request. A MovePosition calculates the velocity needed to move to the position during a single simulation step. When it has completed, the original velocity is restored. Forces don’t affect it. Only when you stop issuing a MovePosition it does. MovePosition is really mean for Kinematic body motion although with careful use it can be used on Dynamic bodies but you cannot just treat it as business as usual with Dynamic bodies because it’s an exclusive operation.
Using “Time.deltaTime” would suggest you’re doing this per-frame. Physics doesn’t run per-frame (by default) so this will only happen when the simulation runs. Also, “transform.position” is NOT where the Rigidbody2D is if you’re using interpolation. The Rigidbody2D is the authority on the pose, refer to “rb.position”. The transform should never be part of physics calculations; you’ll let subtle movement issues creep in if you do. If you’re running physics per-frame then this above is fine though.
All those PolygonCollider2D are scary. Are you changing them per-frame? Physics isn’t going to like that kind of thing either; it’ll also be costly.
this function then gets called in fixedUpdate, I assume this is okay?
And yes, I’ve tied a polygon collider to each frame, they are all set to disabled, a function is then added per frame to let the script know which index collider to make activate per frame. The reason for this is so that as the character is animating, it is correctly keeping an accurate representation of it’s shape. I’m not sure how else to do this, because with other types of colliders you can change them in the animation tab, so essentially you only need to add one collider and then just drag it to different spots when the sprite changes, however with polygon colliders you can’t do this, so this was the only solution I found. I obviously want a true representation of the sprite, not just a box or circle collider around them, as that would be unfair to the player if they took damage, even though technically then didn’t touch the enemy sprite. Will this have heavy implications (enabling and disabling colliders on each enemy)?
Disabling a collider destroys all the physics shapes it contains along with any contacts and asks the body to recalculate its details. Enabling a PolygonCollider2D converts the outline into multiple physics shapes (convex polygons), adds them to the broadphase and flags them to have contacts created when the simulation runs next. The profiler will show you if this is a performance problem for you but it’s not a trivial thing that you want to scale. Also, changing this per-frame is additional waste unless you’re running physics per-frame because you might change it many times before physics runs so it becomes pointless.
Physics colliders are immutable for the most part with the physics system optimized for that case.
Okay how? Changing the Transform? No. Referring to the Transform.position as the authority on position? No. Constantly changing the Transform rotation to flip the character rather than only when you change direction or using negative local-scale? No.
Does it “sort of work”? Maybe but it’s far from optimal. The main thing to understand is that physics isn’t simply a render system where you can mess with the Transform and expect good performance. Physics has to decompose colliders into real physics shapes, those shapes get added to a spatial database so finding contacts and performing queries is fast. Changing colliders involves this work. Colliders don’t even move, Rigidbody2D do, colliders are simply attached and don’t need changing. Modifying the Transform doing stuff like rotation means they all have to be recreated.
If you’re finding this all works for you then then that’s fine but I’d check the profiler too. Sometimes working isn’t enough and we have to jump through a lot of hoops to support things that are not the way you should be doing them such as changing the Transform and expecting it to “just work”.
What then would you suggest to get an accurate representation of the sprite as each frame is changing the sprite? If Unity had the ability to re-modify an existing PolygonCollider2D per frame, then I wouldn’t need all these PolygonCollider2Ds.
Hmm, perhaps I need to go back over the code that moves the enemies towards the player’s position and that flips the enemies when the player is on the other side of the enemy, I’ll look into optimising this.
I don’t suggest anything. Main response was related to asking what’s the point of doing it per-frame? Physics isn’t rendering and isn’t running per-frame so it’s wasted work. Are you running physics per-frame? Then I raised the issue of potential performance issues which you can check with the profiler. Maybe it’s good enough for you.
It does, you can set the outline paths for it as you did for each of them if you want to use the same collider but this won’t save you much. Constantly adding/removing shapes can be costly at scale and as I said, you’ll need to determine if this is the case for you via the profiler. It seems you’re asking for some kind of “animated collider” but that goes against what physics systems (not just 2D) want to do and how they work.
We did add a CustomCollider2D in 2021.2 that gives you low-level access to drive physics shapes (and read physics shapes from existing colliders) but depending on your knowledge, this might not be what you want. It certainly can be used to make your own high performance colliders that can be changed without a lot of the overhead.
I think when a ton of enemies are on screen at once, it’ll start getting costly, so I may need to research a better way to get the enemies moving towards the player, if there is a more optimal way.
yeah perhaps, I may need to have a look at the custom collider.
You probably already know my issue but this video below just demonstrates it and why I’ve added the multiple colliders.
largefaroffbarnswallow
Also just wanted to say you’ve been a star, taking your time to answer my questions, I really do appreciate it a lot, thank you
I understand that you feel you need to accurately track the exact area of the sprite and only you can determine if that’s needed or not but in a majority of cases, it’s not required as the player just wouldn’t notice and/or it makes little difference to the players experience/fun. For instance, a capsule for the player and a capsule for the axe might suffice. In the end, trying to create a sort-of near pixel-perfect detection and animating it is going to be costly unfortunately.
A chunk of the cost here is the PolygonCollider2D. You are not specifying physics shapes but instead a (potentially) concave outline which has to be decomposed into convex polygon shapes which the physics system (Box2D) understands. Look at the inspector, look at how many shapes each creates (Info > Shape Count). Potentially lots.
The new “custom collider” stuff would allow you to read the polygoncollider2d shapes (during authoring) and these are stored in a PhysicsShapeGroup2D. With lots of these, you can fire them at a single CustomCollider2D.
All I’m really saying though is that there’s a performance penalty to brute-forcing it like this. It’s difficult because it sounds like we could “support” animation by providing features but the problem is there’s a huge difference between making certain things easier to squeeze performance out of it and actively encouraging animating physics stuff which is never going to scale well.
You’re more than welcome. I hope my direct style of answering is helpful, it’s not meant as a criticism. You’re operating here is an “awkward” place between animation and physics. It’s always been an awkward relationship.
Yeah it’s just that, for example, that axe on the guard dude, it pulls back and forth as he animates, his legs move, his arms move, I didn’t want to just stick a collider on it and call it done, I feel like if I don’t track the whereabouts of the axe or feet etc as they are moving around, it’ll be a cheap hit on the player, like they could come into contact with the collider even though the axe is no longer there as it’s animated and been pulled back. Tbh, I hate the way I’ve set so many colliders on each enemy prefab, but it was the only way I thought of doing it that would accurately represent the enemy.
If I do end up looking at the Custom Collider stuff, will need to update my unity which will be fun lol
Certainly! I prefer this style as it’s providing results haha I see criticism as a good thing
Note that animation is normally done in a ragdoll set-up. You have a root Rigidbody2D (dynamic or whatever) that controls the core movement. Then you have child GameObject that have a Rigidbody2D (Kinematic) that will automatically move with the parent or you can modify its local position relative to the parent body. None of this causes the colliders themselves to be deformed or recreated.
Limbs and torso can be capsules, a head can be a circle/capsule, weapons can be boxes/capsules etc. The important part is that each of these sub-colliders are attached to a Kinematic Rigidbody2D.
In physics, Rigidbody2D move and colliders are along for the ride. The main thing to understand is that it’s advanced to want to “deform” or “modulate” individual colliders. Moving them relative to some root position via a Rigidbody2D is the way to go.
With flipbook-style sprites this doesn’t exactly map but with simple animation you can obviously reposition these fixed colliders or I should say, the Rigidbody2D they are attached to. The trick being modifying their local position (relative to the parent) in the animation.
I wanted to avoid that ragdoll ‘skeleton rig’ approach at all costs, I just personally think it looks very stiff/robotic. I wanted to take the time to animate each of my sprites using frame by frame animation, so it almost gives it that CupHead style of animation, (I’m no where near the level of that good lol, but still…) and not that mobile game looking animation you always see. I mean, that style is completely fine, just not what I’m after.
So I guess the take away here is:
Have a look at updating the way my enemies more towards the player and how they rotate the way they are facing, see if this can be optimised.
Remove the Polygon Collider2D’s from each sprite and either look into Custom Colliders or just use 1-2 Capsule Collider 2Ds on each sprite and move then in the animator as the sprite moves.
Oh yes, you can still use this flipbook style of rendering. What I was suggesting above was that in your current animation, instead of turning on/off lots of different colliders, you stick to moving the relative position of primitive colliders. So for example, as your axe moves, have a child GameObject and move a CapsuleCollider2D or PolygonCollider2D that’s attached to a Kinematic Rigidbody2D on that child GameObject. Move the Transform local-position. This doesn’t deform the collider nor does it mean it needs to be recreated. It’s better for performance as well as having a specific collider that can be used to detect collisions (assuming you need that) so you know when the axe has hit something.
There’s another optimization you could do without changing the multiple PolygonCollider2D. Put each of them on their own child GameObject with their own Rigidbody2D set to be Kinematic. Then in the animator, simply enable/disable Rigidbody2D.simulated. This removes that PolygonCollider2Ds shapes (actually any attached 2D Collider) from the simulation but it doesn’t destroy them. It means turning them on/off bypasses all the decomposition, shape creation/destruction and is much, much faster!
In short, replace enable/disable PolygonCollider2D in your animator with enable/disable Rigidbody2D.simulated. You’ll need a separate child GameObject for each.
So essentially, if the Enemy has 24 frames, you’d stick 24 child GameObjects on the Enemy, each having a PolygonCollider2D that is associated with that frame + a Rigidbody2D. By default the Rigidbody2D.simulated is set to disabled. I then modify the function that is tied to the animation in the animator to instead turn on the appropriate child GameObject’s Rigidbody2D.simulated to enabled? Does that sound about right?
Just curious, if you have a 100 of those enemies on screen at once, each having 24 children but only one active RB at a time, would that effect performance at all, the fact of having that many objects on screen?
Yes, make sure the Rigidbody2D is set to be Kinematic body-type so it follows the parent Rigidbody2D.
It’s not clear what “objects on screen” means. A GameObject is passive, it doesn’t do anything and is completely passive; it cannot be “on screen”. Only things that render are “on screen”.
A Rigidbody2D doesn’t relate to “on screen” either. It’s only active when it’s set to be simulated. Despite what devs often get wrong, a Rigidbody2D for the most part does nothing. A Rigidbody2D set to be Static does nothing at all. A Rigidbody2D set to be Kinematic has no collision response so does very little either. Only Dynamic Rigidbody2D have collision response, create contacts etc and these are pretty cheap. What isn’t cheap is solving contacts and it’s this that devs often attribute to Rigidbody2D themselves. This is why you often see devs not adding Rigidbody2D at all and moving Static colliders via the Transform which is a form of instanity or in the very least, reversed logic.
I can only guess you’re asking about a Kinematic Rigidbody2D? If you’re worried about GameObjects then it makes no difference. Do a test, add 100 empty children GameObject to your enemies, it’ll make no difference. Only active components do work and often they only do something when you change them i.e. a 2D Collider you’re modifying, enabling/disabling.
In short, no, you’re avoiding the very expensive cost of regenerating colliders constantly. Adding a single Kinematic Rigidbody2D on a child costs next to nothing.
Ah yes, so add the children with a Kinematic RB but have the parent have the Dynamic RB.
This thread has been so informative, thank you so very much!!
I wish I could change the title of this thread now to include this topic of PolygonColldier2D’s and animation, as I think this would really help someone who is also in a similar position to me where they want their enemies to have almost pixel perfect colliders. Your solution for this is awesome, looking forward to refactoring tonight lol.
Yes, spot on. The child will automatically track the parent. It won’t move relative to the parent and always stay at the same relative position/rotation. The body being there means you can turn on/off the simulated which will add/remove any physics shapes. The physics shapes come from any colliders attached to that child body which, in your case, will be a single PolygonCollider2D. The PolygonCollider2D itself won’t see this on/off, it’ll keep all the shapes in the physics engine, it just flags whether they’ll be used or not.
You’re most welcome, sorry if it’s been a journey but hopefully informative.