Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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

Discussion in 'Physics' started by Bujakowski, Jun 16, 2017.

  1. Bujakowski

    Bujakowski

    Joined:
    Nov 22, 2016
    Posts:
    6
    I've got a similar problem to the one described over here:
    https://forum.unity3d.com/threads/unity-2d-avoid-pushing-between-rigidbody.298183/
    Though it's kind of unsolved.

    *** The problem ***
    How do I make player 1 stop at player 2 (and vice versa) without pushing one another? I still want them to collide with other objects with 2d box colliders.

    *** DEMO ***
    I'll demonstrate the problem:


    Now some code:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Player : MonoBehaviour {
    6.     private Rigidbody2D body;
    7.     private float horizontalInput;
    8.     private float verticalInput;
    9.     private float speed = 10;
    10.  
    11.     void Start () {
    12.         body = GetComponent<Rigidbody2D>();
    13.     }
    14.    
    15.     void FixedUpdate () {
    16.         horizontalInput = Input.GetAxisRaw(gameObject.name + "_Horizontal");
    17.         verticalInput = Input.GetAxisRaw(gameObject.name + "_Vertical");
    18.         MoveCharacter(horizontalInput, verticalInput);
    19.     }
    20.  
    21.     private void MoveCharacter(float horizontalInput, float verticalInput)
    22.     {
    23.         Vector2 direction = new Vector2(horizontalInput, verticalInput);
    24.  
    25.         if (direction.x != 0 || direction.y != 0)
    26.         {
    27.             body.MovePosition((Vector2) gameObject.transform.position + direction * speed * Time.deltaTime);
    28.         }
    29.     }
    30. }
    31.  
    Finally the prefabs config:


    *** What I've tried / what won't work ***
    - Changing body type to Kinematic - they don't push each other but they don't collide at all,
    - Tried CharacterController - no difference obviously =)
    - Changing mass - this only works one way

    This is such a common problem I think that maybe in unity 5.6 there is finally a sollution =)?

    Thanks for all advice,
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Terminology is important here. You're saying "collide" but it's not obvious if you mean "come into contact" or the "collision response to coming into contact". The "pushing" you're talking about is a collision response so it seems you're saying you don't want a collision response and only want to know if two things come in contact, presumably by getting a physics callback or using the GetContacts calls?

    If you don't want a collision response then you must use a Kinematic body as this is what this is for as it doesn't respond to forces. If you want two Kinematic bodies to produce a contact i.e. "collide" and get OnCollisionXXX2D calls then set Rigidbody2D.useFullKinematicContacts to true.

    This option appears when you set the Body Type to Kinematic.
     
    ilicstefan0307, Fabii555 and vexe like this.
  3. Bujakowski

    Bujakowski

    Joined:
    Nov 22, 2016
    Posts:
    6
    I've tried setting Rigidbody2D.useFullKinematicContacts to true and I've read some docs and some other forum questions, but still no luck. I have, however encountered this bug topic:
    https://issuetracker.unity3d.com/is...nematic-contacts-on-rigidbody2d-has-no-effect
    Could this bug be my problem?

    So far the only possible solution I found is to detect collison with another object and manually set flags cannotMoveRight, cannotMoveLeft, cannotMoveTop, cannotMoveBottom depending on the collison's direction. However, I'm not sure what's the best to implement this.

    Thanks for your reply anyway =)
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    That issue you refer to is just plain wrong. As I've said, Full kinematic contacts allows contacts to be created between kinematic bodies so you'll get callbacks and you can retrieve contacts using GetContacts. Without that you won't get either.

    If you expect the bodies to produce a collision response then you're fundamentally misunderstanding as that is what a dynamic body type is!

    Could you ellaborate? What were you expecting?
     
  5. Bujakowski

    Bujakowski

    Joined:
    Nov 22, 2016
    Posts:
    6
    When setting type to kinematic the characters move through each other. Well I wasn't expecting too much

    I want Player 1 (red knight) not to be able to move to Player 2's (blue knight) position and not to push him. Just to stop.

    I'm not sure whether you understand what I'm trying to achieve? I'm really just poking around with unity, any (non-hacky) solution will work for me if you just point me in the right direction. Am I correct to assume that I need to implement this manually by collision detection?

    #2 How Do I use GetContacts? I've got something like this, though obviously the argument(s) is wrong.

    Code (CSharp):
    1. void OnCollisionEnter2D(Collision2D coll) {
    2.     Collider2D.GetContacts(coll.contacts);
    3. }
     
  6. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    Try just setting both knights velocity to 0 in OnCollisionEnter.

    I also wonder what happens if you make a gameobject with kinematic rigidbody move along with the non-kinematic rigidbody, but set its layer to only interact with the other Knight.
     
    Last edited: Jun 18, 2017
  7. Bujakowski

    Bujakowski

    Joined:
    Nov 22, 2016
    Posts:
    6
    Already tried that through:
    Code (CSharp):
    1. void OnCollisionEnter2D(Collision2D coll) {
    2.     body.velocity = Vector2.zero;
    3. }
    But nothing changes :/

    This may work but only for 2 players, what if I want to add more players? I need a more general approach but still, thanks for you suggestions.
     
  8. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Have the same issue, but in 3D. I simply want the same behaviour From Software have been doing for almost a decade in the Dark Souls/Bloodborne games.

    Characters never push each other, but still collide with each other.

    The environment may push characters (traps, walls, door). Characters can push debris or breakable objects.

    Unknown number of character, unknown velocity, animation driven motion.

    It should be super simple, but it appears totally impossible in Unity.
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    It's not impossible, you're asking for kinematic motion and it's used all the time. You want a body that doesn't response to forces and with kinematics you need to determine collision yourself and move appropriately. I do not know your movement requirements but here's a simple example I just put together.

    - Add two GameObject, each with a Rigidbody2D (set to be Kinematic) and a CircleCollider2D. Add the following script to one of them so that it moves. It uses Rigidbody2D.MovePosition to move but it doesn't just move there, it first checks if it can move there. It does this with a single "Cast" call and then checks the returned hits to see if they are a valid move. In my code a valid move is if the move is non-zero distance. We also finish and don't move at all if a tiny or zero distance is moving into the contact. This is just one of many movement models you can adopt but it's all centered around the same thing; using Kinematic bodies, checking for collision then using MovePosition/MoveRotation to move if appropriate (determined by your game).

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Move : MonoBehaviour {
    4.  
    5.     public float Speed = 1;
    6.     private Rigidbody2D m_Rigidbody;
    7.     private RaycastHit2D[] m_Contacts = new RaycastHit2D[100];
    8.  
    9.    // Use this for initialization
    10.    void Start ()
    11.     {
    12.         m_Rigidbody = GetComponent<Rigidbody2D>();
    13.    }
    14.  
    15.    // Update is called once per frame
    16.    void FixedUpdate ()
    17.     {
    18.         // Set initial velocity as zero.
    19.        var velocity = Vector2.zero;
    20.  
    21.         // Do some crude movement.
    22.         if (Input.GetKey(KeyCode.LeftArrow))
    23.         {
    24.             velocity.x = -Speed;
    25.         }
    26.         if (Input.GetKey(KeyCode.RightArrow))
    27.         {
    28.             velocity.x = Speed;
    29.         }    
    30.         if (Input.GetKey(KeyCode.UpArrow))
    31.         {
    32.             velocity.y = Speed;
    33.         }    
    34.         if (Input.GetKey(KeyCode.DownArrow))
    35.         {
    36.             velocity.y = -Speed;
    37.         }
    38.  
    39.         velocity *= Time.deltaTime;
    40.         var direction = velocity.normalized;
    41.  
    42.         // Find contacts along our movement direction.
    43.         var resultCount = m_Rigidbody.Cast(direction.normalized, m_Contacts, velocity.magnitude);
    44.  
    45.         // We need to find a hit where we're actually moving.
    46.         for(var i = 0; i < resultCount; ++i)
    47.         {
    48.             var contact = m_Contacts[i];
    49.             var distance = contact.distance;
    50.  
    51.             // Are we actually moving?
    52.             if (distance > Mathf.Epsilon)
    53.             {
    54.                 // Yes, so schedule the move.
    55.                 m_Rigidbody.MovePosition(m_Rigidbody.position + (direction * distance));
    56.                 return;
    57.             }
    58.             // If we're moving into a contact then finish as we cannot move.
    59.             else if (Vector2.Dot(contact.normal, direction) < 0)
    60.                 return;
    61.         }
    62.  
    63.         // No contact was found so move the full velocity.
    64.         m_Rigidbody.MovePosition(m_Rigidbody.position + velocity);
    65.    }
    66. }
    67.  
    68.  
    https://gyazo.com/dbdd885b304854f3799713b04830a094
     
    asfdfdfd and Gaven-jr like this.
  10. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    We want it to respond to forces, just not forces applied by a specific physic layer.

    We want a character that works like any other character, moving around, pushing object, colliding with walls, pushed by movers, explosion, attacks... Except it cannot push or by pushed by other characters.
     
    buzzing_jelly likes this.
  11. Bujakowski

    Bujakowski

    Joined:
    Nov 22, 2016
    Posts:
    6
    @MelvMay - Nice, this looks like it may actually work, still a pity we can't do it out of the box. Will try it in a couple of days when I find some free time and give feedback whether it works for my situation.
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    So to stay with Dynamic bodies, it'd need deep integration into the solver for 2D (Box2D) and I can only presume the same for 3D (PhysX). I would consider it as an option for 2D but I'm not even sure it's possible via PhysX, I'd need to ask one of the 3D physics guys. You're saying be Dynamic on a certainly layer but act Kinematic on another although still solve overlaps as per a Dynamic body.

    I had a look but couldn't see this as a request in the feedback on the site, maybe it's there but I can't see it so it doesn't seem to be a commonly requested thing. Maybe there's lots of posts asking for it though but I'm not aware of them.
     
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Another issue to consider is that if continuous col-det isn't used for such a feature then things will get overlapped with discrete col-det. The physics system will solve that overlap by repositioning the body. If something continues to move into overlap then it'll look like it's "pushing" because both will move out of overlap. You cannot stop this otherwise it'll just act like a Kinematic body allowing overlap. The only way to get around this is to always use continuous collision detection for the dynamic body which is much more expensive so this feature won't scale well.
     
  14. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    If you search for "Rigidbody not pushing" or "Character not pushing", it's a topic that comes back quite often in one wording or another. Usually Dark Souls is listed as an example. In 2D, the problem is most likely immensely easier then in 3D.

    I'm kinda surprised PhysX doesn't offer any way to affect the energy transferred on a collision. Like... energy transfer between Layer A and B is 0%.

    I see where you're going with the repositionning issue. If you had to perfectly duplicate the Dark Souls character collision system in Unity, how would you do it?
     
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    I know nothing about "Dark Souls" nor do I see how that is relevant. What you want is clear however you're going to struggle doing that with Unity as is. I'm NOT the 3d physics guy and do not know what might help you achieve that in the future. Maybe some other users have had more success with various techniques, I'm not sure. It's certainly the first time I've seen the feature request.
     
  16. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Well, I said Dark Souls, simply because it's probably the most well-known third person RPG where a character cannot push another.

    Thanks for your help. Hopefully someone had or will have more luck.
     
  17. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    You can also try increasing mass and drag of objects.
     
  18. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Only works one way. Character A cannot push B, but then B can very easily push A.

    As for friction, only works if the contact is maintained with the floor.
     
    Last edited: Jun 20, 2017
  19. Bujakowski

    Bujakowski

    Joined:
    Nov 22, 2016
    Posts:
    6
    @MelvMay your code works as expected, many thanks! It probably needs to be polished to ensure smooth gameplay but it's a good start.
     
    MelvMay likes this.
  20. J0hn4n

    J0hn4n

    Joined:
    May 11, 2015
    Posts:
    24
    maybe a simpe raycast when its about to move to get the normal.
     
  21. bernardo_reis

    bernardo_reis

    Joined:
    Dec 27, 2019
    Posts:
    5
    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.
     
    Last edited: Jan 20, 2020
    4-bit likes this.
  22. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    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. :)

    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.
     
    Last edited: Jan 20, 2020
  23. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    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.
     
    4-bit likes this.
  24. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    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. ;) 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.
     
    Last edited: Jan 20, 2020
  25. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    https://web.archive.org/web/2015092....com/suggestions/physics-contact-modification

    Had to track back an old 2015 feedback.

    https://docs.nvidia.com/gameworks/c...dCollisionDetection.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.
     
  26. bernardo_reis

    bernardo_reis

    Joined:
    Dec 27, 2019
    Posts:
    5
    @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 has a very interesting point above
     
  27. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    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.
     
  28. bernardo_reis

    bernardo_reis

    Joined:
    Dec 27, 2019
    Posts:
    5
    @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?
     
  29. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    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. ;)

    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
     
    Last edited: Jan 21, 2020
    bernardo_reis likes this.
  30. bernardo_reis

    bernardo_reis

    Joined:
    Dec 27, 2019
    Posts:
    5
    @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?
     
  31. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Last edited: Jan 24, 2020
  32. bernardo_reis

    bernardo_reis

    Joined:
    Dec 27, 2019
    Posts:
    5
    Thanks @MelvMay, your example above was really helpful. I believe

    Code (CSharp):
    1. // NOTE: This is effectively how we iterate and change direction for the queries.
    2. movementDirection -=  hit.normal * Vector2.Dot(movementDirection, hit.normal);
    is exactly what I was looking for!
     
    MelvMay likes this.
  33. MrExillion

    MrExillion

    Joined:
    Mar 24, 2018
    Posts:
    10
    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.
     
  34. MrExillion

    MrExillion

    Joined:
    Mar 24, 2018
    Posts:
    10
    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.
     
  35. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    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.
     
    Last edited: Jan 21, 2021
  36. MrExillion

    MrExillion

    Joined:
    Mar 24, 2018
    Posts:
    10
    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 :)
     
    MelvMay likes this.
  37. fontinixxl

    fontinixxl

    Joined:
    Nov 13, 2019
    Posts:
    4
    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.
     
    MelvMay likes this.