Search Unity

Unity 2D - Avoid Pushing between rigidbody

Discussion in '2D' started by cruzlutor, Feb 15, 2015.

  1. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    i have an issue with my 2D game in unity (pokemon style), i'm using transform.position to move the gameobjects

    I have a player and enemies that follow him, all is ok, but when the enemies make a collision then they begin to push each other, enemies and player has rigidbody and box collider 2D

    I need that nobody to be pushed when the enemies or player get a collision.

    • tryed to use kinematic in enemies but the player can push them.

    • tryed to add a big amount of mass to the player but he can push the enemies.

    • tryed to detect the collision in code with OnCollision* but when i cancel the enemy movement they dont return to move.
    Here is a video of my problem

     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    If you're bypassing movement controlled by the 2D physics system then you must set the Rigidbody2D component to be Kinematic. If you don't want the physics system to produce collisions then set the collider to be a trigger and use the OnTriggerXXX callbacks instead. Additionally, use the collision layers to control what can contact each other in the 2D physics settings.
     
    Fischchen123 likes this.
  3. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    I need the collision but without pushing between them

    When i try OnTriggerXXX callbacks both object stop but they dont move again because they are permanently collide
     
  4. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    Im really out of ideas, somebody has a similar problem?
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Really isn't enough information to help you, the failing logic must be in your scripts and/or where you having those scripts called.

    If you want collision response (presumably you're calling this 'pushing') then don't use triggers. If you don't want a collision response then use triggers. If you want to know when it first happens then use the 'enter' callbacks, if you want it continuously then use the 'stay' callbacks and if you want it when the contact ends use the 'end' callback.

    If you don't want things to contact each other at all then use the 2D physics settings to control the what layer(s) can contact other layer(s).

    Beyond that, not sure what else I can say without you providing more information.
     
  6. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    899
    First of all, you're probably better of using rigidbody2D.MovePosition, instead of transform.position.

    You should not be able to push things that are set to kinematic. I tried using several different movement techniques and I was not able to push anything kinematic. The only problematic situation I found was when two kinematic objects collide. In that case they pass through each other.

    Detecting collision with OnCollision* and then moving back to the previous position should work.

    You could always use something like Physics2D.OverlapCircle to see if the position you are about to enter is already occupied.
     
    cruzlutor likes this.
  7. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    As i can see Unity has not native way to prevent push between rigidbodies, I'll try improve more complex way to prevent push and detect collider at same time (Physics2D.OverlapCircle can be a good option)

    thanks for all guys
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Again, why not use triggers? These tell you what overlap and don't 'push' each other.
     
    Fab4 likes this.
  9. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    Finally I'll get the expected result,changing the rigidbody2D.isKinematic property to true when the target was close and stop it

    Here is a video


    And the enemy movement code

    Code (CSharp):
    1.  
    2. void FixedUpdate () {
    3.  
    4.     if(path == null)
    5.         return;
    6.  
    7.     if(currentWayPoint >= path.vectorPath.Count)
    8.         return;
    9.  
    10.     float distanceTarget = Vector3.Distance (transform.position, target.position);
    11.  
    12.     if (distanceTarget <= 1.5f) {
    13.         rigidbody2D.isKinematic = true;
    14.         return;
    15.     }else{
    16.         rigidbody2D.isKinematic = false;
    17.     }
    18.  
    19.     Vector3 wayPoint = path.vectorPath [currentWayPoint];
    20.     wayPoint.z = transform.position.z;
    21.  
    22.     transform.position = Vector3.MoveTowards (transform.position, wayPoint, Time.deltaTime * speed);
    23.  
    24.     float distance = Vector3.Distance (transform.position, wayPoint);
    25.  
    26.     if(distance == 0){
    27.         currentWayPoint++;
    28.     }
    29.  
    30. }
     
  10. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    @MelvMay , I'll try to test Physics2D.OverlapCircle and comment the result too

    Do you have any example to apply in my case? i check the documentation but not understant at all
     
  11. cruzlutor

    cruzlutor

    Joined:
    Jan 14, 2015
    Posts:
    13
    @MelvMay sorry, I thought you meant Physics2D.OverlapCircle. I tried triggers, but when 2 enemies collide both stop moving
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    If they stop moving then that's your logic in the callbacks, nothing to do with the physics system so you need to look there. Also, you should ALWAYS use kinematic rigid-bodies (never use dynamic ones) if you're setting the position yourself via the transform.
     
  13. hidden_at

    hidden_at

    Joined:
    Aug 16, 2016
    Posts:
    1
    Hi,
    first put your enemy in a layer ("EnemyLayer") and your Player in another layer ("PlayerLayer") then all you need to do is to create a new script and put the following code in Start method :
    Physics2D.IgnoreLayerCollision (LayerMask.NameToLayer ("PlayerLayer"), LayerMask.NameToLayer ("EnemyLayer"));

    after that put the script on camera and that's it . . .
     
    Last edited: Aug 16, 2016
    bblbex2001 likes this.