[2d] [Isometric] - How to disable pushing between two characters

I’m struggling with the same problem for quite some time. I’m writing a 2D top down RPG and given my background playing games since I was a kid, the behavior I want to achieve is quite common. @MelvMay to your point. maybe Dark Souls is not a good example (although is a very famous game), but there are plenty of others. For example, Pokemon or the Zeldas for SNES. On those games, entities still collide to each other (in the sense they stop moving when they touch), but they not apply forces to each other. They simply stop moving. So one can say there is collision detection (they touch, they stop moving and they apply damage to each other), but no forces act.
I’ve tried all the “hacky” approaches suggested everywhere, like forcing the velocity to zero, temporarily converting bodies to kinematic, etc etc, but they always have some small issue that is perceptible at run time, like tiny movements until velocity becomes zero, kinematic bodies moving over each other, kinematic bodies walking through walls or something on those lines.
Maybe the reason why me and so many other (this topic is extremely common in Unity/game dev forums), struggle with this problem is that on our minds this is something extremely simple (conceptually speaking), but perhaps it’s just not how Unity physics system was designed to work).
Perhaps there is no simple solution and everyone trying to achieve this behavior will have to add code to do Raycasts or things of the sort like @MelvMay exemplified above - which I’ve tested and seems to work for my use case with some minor adjustments - although I’d love to have a feature request for this.

1 Like

Sorry but I just don’t follow what’s difficult to achieve here and saying it might be because how Unity physics system was designed is kind of misdirecting the issue, especially if you consider it’s not “Unity physics”, you’re implying PhysX or Box2D not designed for something so simple.

2D physics offers a lot of queries to allow you to determine collisions and it’s then not difficult to create your own responses. I also don’t understand why something that is a perfectly valid thing to do such as zeroing velocity is considered hacky unless hacky is anything that isn’t done automatically by Unity. What would be hacky would be using a dynamic body when you don’t want a dynamic-body collision response. :slight_smile:

For instance, if I create a Kinematic body, when it moves I perform a Rigidbody2D.Cast to cast its colliders through space I have all I need to determine how to move. If I find I’m overlapped, I can use Physics2D.Distance which not only tells me distance but also nearest points and if it’s overlapped. Using these calls I can easily determine where I can move and how to respond in a top-down set-up.

Heck, if you don’t want to use queries to determine contacts but still want to use callbacks for them but don’t want a collision response then use a Kinematuc body with Rigidbody2D.useFullKinematicContacts check. This means you get contacts exactly the same as Dynamic bodies but no collision response. YOu can then use Physics2D.Distance to determine how to respond i.e. if you’re overlapped you can easily move out of overlap with the ColliderDistance2D results via (distance * normal).

I think what you’re describing is to have a non-dynamic response using a Dynamic body which is like asking for a green light to be red. If you use a Dynamic body and get a callback, the callback is after the collision response has happened which isn’t what you want. If you don’t want a collision response then you use a Kinematic body.

In the end, I’m not trying to trivialise any issue you’re having with setting this up just that I don’t see how anything is a blocker for you. I’m more than happy to help you get this working.

I honestly believe you have no idea what we are talking about.

Zeroing velocity is not the answer as both character would simply stop on contact. What they want, is for both characters to act as if the other one is a unmoving wall. No energy transfer, but you can slide around it.

There’s another thread around, where I mention that PhysX actually have specific calls for this kind of behaviour, but they are not exposed by Unity.

1 Like

I fully understand and to note that the person I was replying to isn’t using physx (3D) so I was addressing how to achieve this in 2D.

It’s a good job I never said it was a solution here either. :wink: I said it wasn’t hacky to use such calls.

Anyway, the calls I highlighted allow you to do what is required in 2D, contacting objects, not overlapping and not “transferring energy” because you’re just dealing with the contacts. You can slide along other objects etc.

You cannot get a dynamic body to do this without being able to intercept the contacts before they are passed to the solver and doing something like modifying the contact mass; something which simply cannot be exposed for reasons that have been stated many times on the forums. You certainly can’t do it after the solver and callbacks have run unless you reverse the collision response already applied to the dynamic bodies.

Had to track back an old 2015 feedback.

https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/3.3.4/Manual/AdvancedCollisionDetection.html#contact-modification

In addition to modifying contact properties, it is possible to:

  • Set target velocities for each contact
  • Limit the maximum impulse applied at each contact
  • Adjust inverse mass and inverse inertia scales separately for each body

This was never exposed.

Now, I know. 2D != 3D. However, it’s frustrating as hell when needed to do something very simple, and having “no good solution”. I must have missed the reasons for not exposing some functions.

@MelvMay thanks for the response.
So, to address your comment:

Ok, ok, it’s not Unity Physics, it’s PhysX. But that’s not my point, nor I said it’s difficult.

What I said is that I believe that there’s a great misalignment between what devs expect and what the out-of-the-box-whatever-physics-lib-offers. On our minds - or at least in mine - it should be simple to simply zero all forces on a collision or completely ignore it while still using other things offered by the library - for example the collision detection of dynamics bodies. Maybe it’s not, like I said maybe it’s not what it was designed to do because like you said, what we want to achieve is not real physics, we know that. Once again, I’m simply stating that we were - or again, at least I was - expecting some sort of checkbox or setting that would ignore forces on collision or whatever.

Also, like I said, I’ve tried all sort of hacky approaches, like manually zeroing velocity. They all have some sort of side effect and deliver bad user experience - or at least that’s what I’ve experienced with all the suggestions I’ve seen in forums.

Finally, like I mentioned on my previous post, I’ve tested your snippet above and it works and I’m quite happy with the result. It’s not complex by any means and to your last point

it’s not. I was just not expecting to have to add code to fix movement like the snippet above or your other suggestion to use Rigidbody2D.useFullKinematicContacts - which is interesting by the way. But adding code is not really a problem for me, I do have a lot of experience with this type of issues (although not a lot of experience in Unity, I confess).

Once again, thanks for the help, and one final question: which one do you think it’s better, performance wise: using a rigidbody cast like you have on your snippet above, or using kinematic bodies, full kinematic contacts and move back from overlaps - although this approach sounds a bit worse in my mind, at least conceptually.

PS: @LightStriker_1 has a very interesting point above

What you’re describing is manipulating contacts before they go to the solver which is still going to be code. For native physics, that’s never going to happen as it’s fraught with integration issues. You make it sound like there could be a check box for “Don’t respond to forces” but that’s just a Kinematic body. What you want is logic to control whether this should happen or not dependant upon the collision details and that’s where contact manipulation comes in.

In DOTS 3D physics you can already do this and DOTS 2D physics will be the same.

@MelvMay yup, I guess what I wanted was a way to manipulate the contacts after all. It’s a bummer Unity doesn’t expose that. And yes, I know it’s still code and it’s not as simple as a checkbox, but at least I wouldn’t have to detect collisions myself. And yes, you keep bringing up kinematic bodies, I already I got it, I know what kinematic bodies are. But like I said all I wanted was to re-use some of the behaviors dynamic bodies have.

Anyway, I left you a question on my previous post:

What do you think?

Yeah, sorry. I don’t mean for what I’m saying to sound like I’m preaching. I probably shouldn’t be on the forums in the middle of night. :wink:

Unfortunately it’s very hard to say what’s the difference would be without profiling as there are just too many variables at play. Casts via Rigidbody2D which cast all colliders can become relatively expensive but it depends on the types of colliders, how many, how often and against what. I think however the biggest cost would be your own scripts if they had to manipulate a lot of characters.

Casts are similar to using continuous col-det but you don’t need to use these, you can always just move then solve overlaps (discrete col-det). The Distance method isn’t that expensive, certainly less than doing the same via the solver which performs iterations.

I’d have to look around for the example I wrote for something similar which is a basic solver using the Rigidbody2D.Cast/Rigidbody2D.MovePosition (integration) and Physics2D.Distance (overlap solver) which worked really well using Kinematic bodies and useFullKinematicContacts and did it with a fair number of characters.

I don’t enjoy it when I have to say stuff like contact modification isn’t going to happen but given the current situation I realistically cannot see that being implemented given the issues involved. I understand how useful it is and how frustrating it can be to not have access to it and I originally wanted to implement this prior to me implementing effectors as some of them are based upon contact modification such as the PlatformEffector2D one-way and SurfaceEffector2D features and I would’ve rather exposed contact-mods in the engine and then effectors on GitHub rather than them being another black-box feature but it wasn’t to be.

Unfortunately exposing PreSolve callbacks in 2D means we’re making very expensive callbacks per contact which is terrible for performance. Gathering them isn’t so easy either as in 2D they’re called at various stages and not just one (at least for continuous contacts) although in 3D that situation isn’t the same AFAIK. We have zero control over what the end-user does when we perform a script callback. They can modify or destroy GameObject, even change scenes and this causes serious problem and the side-effects are hard and costly to detect and worst case, cause crashes. This is okay when you’re using a library directly yourself but integrated into an engine, it cannot be allowed to happen. A while back we were looking at the possiblities of having a sandboxed callback so you had very limited script support during it but that never happened either. The hardest part was finding a way to do this that didn’t have a performance impact for the majority who don’t use it. Other callbacks happen after the simulation has completed.

It’s not to say the above is impossible but given the hurdles, it becomes a serious time sink getting that working in a way that doesn’t cause crashes. Unity is complex under the hood and this complexity can make features like this difficult to implement as there are many things to consider. It certainly isn’t a case of this not being done because we don’t understand how valuable it is. In the end, 2D and 3D physics was implemented by devs who love this stuff and use it themselves; not some faceless company who doesn’t understand your needs which sometimes it can seem like.

EDIT: A final thought was that contact modification modification using PhysX plugin by Nvidia offering would help and found the thread here but the status is unknown (I’m not a 3D physics guy): https://forum.unity.com/threads/nvidia-physx-plugin-preview.645004/#post-4684595

1 Like

@MelvMay thanks for the response. Since I’m not on a deadline or anything (I code games as a hobby), I can actually try to implement it both ways and check performance for each.

I do have another question for you regarding your code snippet above. I was playing around with that and I realized I will need to change it slightly to achieve the movement behavior I want: I’m trying to achieve a movement very similar to the one seen in Zelda games.

On those games, if you’re moving diagonally and hit a wall in one of those directions, you can still move in the other direction. With the cast approach above, that doesn’t happen, so I was trying to change it and break the movement down into two movements, one for each axis (keeping in mind I’m dealing with a top down 2D game). However, doing that will effectively double the amount of casts I’m doing on each small movement my entities do.

I’m thinking if there is a more efficient way of doing that, perhaps using a single cast and then applying some vector math to break down the movement after I do the cast (I will confess I’m a bit rusty when it comes to physics). Would you have any ideas there?

So I decided to spend 30 mins and put together an example project and shown here:

2D examples repo: https://github.com/MelvMay-Unity/UnityPhysics2D/tree/2019.3

Example scene: https://github.com/MelvMay-Unity/UnityPhysics2D/blob/2019.3/Assets/Scenes/Miscellaneous/KinematicTopDownController.unity

Note: The above is on the 2019.3 branch but it’s also on “master” which is 2020.1 (currently).

You can go to the example controller and change the speed, how you control the character etc.

3 Likes

Thanks @MelvMay , your example above was really helpful. I believe

// NOTE: This is effectively how we iterate and change direction for the queries.
movementDirection -=  hit.normal * Vector2.Dot(movementDirection, hit.normal);

is exactly what I was looking for!

1 Like

A bit peculiar how i ended here. But really i need to break newtons laws. Essentially a mixed dynamic physics system would help, but i will break down my thoughts anyway.

I have the need to pull and push an object in the x z plane all as normal no problem.
I also need the same two objects to have gravity ok so far so good. Now the games core mechanic is scale by translation, so the local position within a volume determines the size of object A, suppose the other object B is the player, who can push and pull this object it seems fair. Now the problem is i want two players, but unlike the dark souls example, it is not the players i care about here. I simply want player 1 to climb object A when its small, and then as it gets bigger get elevated. And now things turn bad real fast. Firstly in order to scale by translate for all objects with a specific class attatached i managed to this through collections and then per object set kinematic scale and re position the height to be 1/2 scale of y. Then resume as non-kinematic. The issue is if i dont freeze axes on Player 1, he will get ejected with tremendous force. Suppose i want to Player 1 to drop by gravity to the object, newtons laws pretty much state that the collision is elastic and the player will keep bouncing. Setting velocity as zero has no effect as the force is still applied on collision. But suppose you could get a force absorp attribute and compare with anything, and let it be conditional, that would grant all the requests. The problem with locking y is the same as setting velocity 0. It could look something like:

Rb.Absorbforce(vector3 forcetoabsorb, other.rb, Vector3 incdirection, layermask or tag, collisionmode);

As with the realworld sometimes energy is conveted to heat, but in games we could just make it dissapear.

I’ll probably figure out to accomplish the absorb somehow, maybe by using raycast and then do some spaghetti references. But it still remains to figure out how to lift up the player without adding linear momentum as i scale object A. Im glad this thread is so thorough. There is a posibility i could use physics materials, and then jusy change the material based on the collision direction, but that would leave problems on muliple collision interactions at the same time. In any case its a rather stupid niche need in my case, and its actually a fun challenge. If i ebentually figure out to do a rigidbody with force absorp as a derived class ill share it here. Sorry for the rushed post, but its 3am in the morning and i really need some sleep, hope its readable.

So small update, the math is correct but it doesn’t work in practice, the force applied just by the scale is too unpredictable with a precision of 0,001. The issue essentially is that the object stops but the unstable natuee of the floating point precision of the scaling code, means that the item i need to scale quite drastically apply a ridiculous ammount of force nearly 10times that of the impact itself. So the only proper way for me to do it is to create state based system that will determine if its physics based or not, and then have an active state where standing on the objects is being set through transform.position = vector3. Which then has to be precise. I also need to simulate center of mass this way as well as gravity and torque outside the rigidbodey system, its going to be a bit of a challenge. So while i yesterday thought absorb force might be the solution, today i think a statebased rigidbody system is better and also better than the layer request, as it will also allow you to have different rigidbodies react based on an input state in combination with the new input system. You might have certain physics for player based on whether or not youre driving a car. Or walking, just by soecifying which state the player is in. In at which point if you collide with a player or is about to your impact will be calculated by a different inelastic collision v1 = m1-m2/m2 = v2, formula might be slightly wrong actually. Or p/-deltaTime*m_k = -F_impactforce_k. In either case the force pushing back at you should nullify by addition. Anyway, this doesnt actually work in my case, it does work though just not when you scale an object underneath you in an imprecise manner over transform. In either case its possible to make, but impractical.

This thread is about 2D physics and a specific issue and your posts are not adding to that issue from what I can follow. I would suggest you create your own thread and not hijack this one. You can obviously refer to this thread directly in your new post should you feel it’s of relevance.

Thanks.

Well thanks for the heads up, I didn’t view it in this manner. All it was is that I didn’t want to spam the forums for existing thread duplicates. And I don’t see the issue being restricted to 2D based on your answers. While my need is indeed in 3D, the issue i was trying to solve is caused by the same thing, and could appear in a similar 2D game context as well. In which i didn’t think it would be an issue if my solution would indeed solve this very issue for 2D which this thread is about. Regardless as i described in the update, i found no usefull solution of that which i tried so far, so the udate was as much to state that I wouldn’t post a solution or code relevant anytime soon, which would indeed help with the layer issue. And thus i commented on a change to the engine that would benefit both 2D and 3D physics alike, hard to argue with a stone that hits two birds. Firstly because its a stone and cant talk back, jokes a side, i was not trying to hijack the thread in anyway as much as to follow up on a failed attempt that would have helped all parties. My mistake for not just creating my own topic ofc. and leaving a link here if i got it to work. There was no mischief intended. If I indeed do solve the issue i will create a different thread, and post link to each other and vice versa. I wont repeat my suggestions, but essentially in the update i listed a few ways the physics environment could be changed, while implemented differently for 2d and 3d would benefit both. Thanks for your hard work servicing the fora :slight_smile:

1 Like

Thanks for that, it is amazing and very usefull to have those examples in a repo. I am developing a Zelda-like game, and I was struggling with the phisics2D to get the desired look and feel without having to using Dinamic Rb and tricks. Think those examples, specially the KinematicTopDownController are gonna be very usefull.

Again, thank you very much and good work on this thread.

1 Like