Search Unity

Question Collisions in high speed without unity physic / rigidbody

Discussion in 'Scripting' started by Saw9yer, Dec 26, 2021.

  1. Saw9yer

    Saw9yer

    Joined:
    Sep 19, 2020
    Posts:
    72
    Hello everyone,

    These days i experimented to works without unity physic / rigidbody in order to create a responsive 2D platformer, with importants velocities.
    I use transform.Translate(velocity * Time.deltaTime) to apply my movements.

    During my first test I managed collisions with :
    - Raycasts (i fire 12 raycast, 3 by side, size 1by 1)
    - If i collide (my player is inside a collider) i use transform.position to set the correct position of my player

    For exemple, to detect the groud :
    Code (CSharp):
    1. Collider2D colMiddleSouth = FireRay(new Vector3(collider.bounds.min.x + halfWidthSprite, collider.bounds.min.y, 0), Vector3.down, 1);
    2. Vector3 col_v3 = colMiddleSouth.bounds.max;
    3. transform.position = new Vector3(transform.position.x, col_v3.y + halfHeightSprite, 0);
    I was not satisfied because it becomes hard to manage complex collisions

    So i did a second try, and i managed collisions with :
    - Raycast, all the trick is to set the good length of the raycast according to player's velocity
    - then if i collide at the length of my raycast i set velocity.x or .y to 0

    For exemple :
    Code (CSharp):
    1.         float directionY = Mathf.Sign(velocity.y);
    2.         rayLength = Mathf.Abs(velocity.y) * Time.deltaTime ;
    3.  
    4.         RaycastHit2D hit = Physics2D.Raycast(new Vector2(transform.position.x, transform.position.y-halfHeightSprite), Vector2.down, rayLength, collisionMask);
    5.         Debug.DrawRay(new Vector2(transform.position.x, transform.position.y - 25), Vector2.down * rayLength, Color.red);
    6.  
    7.         if (hit)
    8.         {
    9.             velocity.y = 0;
    10.         }
    This time again i am not satisfied of the result.

    Did you know others ways to manage collisions without rigidbody/unity physics?
     
  2. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
  3. Saw9yer

    Saw9yer

    Joined:
    Sep 19, 2020
    Posts:
    72
    Yes i did come tests with overlap.
    But my real problem here is how to manage pixel perfects collisions at high speed.
    I wonder there are betters ways to manages collisions.
     
  4. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    How high a speed are we talking max velocity? 4000?

    because I notice raycast misses from certain angles even with draw ray on objects particular objects which are moving. Why don’t you see if it’s possible to for one frame only set your fixed update speed to be faster than your update speed, or your update speed to be switched off and to try and get two rapid collision checks in row before reverting update cycle.
    So hopefully when the first check misses, the second check doesn’t.

    The answer might be in time
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    You say you're not using 2D physics but you're using queries therefore obviously colliders. This IS using 2D physics therefore you need to use it correctly so here are some basic rules:
    1. Don't ever modify the Transform if using 2D physics components
    2. If you want a 2D Collider to move then add a Rigidbody2D and use its API to move it; many ways to do this.
    3. Rigidbody2D don't make it "unresponsive". If you want explicit control then set the body-type to Kinematic; it's what it's for.
    4. When you query, don't use the Transform position as a reference, it's not the authority on the pose, that's the Rigidbody2D so use its position/rotation properties.
    If you don't use a Rigidbody2D but 2D colliders then you're implicitly saying Static (non-moving) colliders but then go and change the Transform going against that. Changing the Transform on a GameObject with only a Collider2D is relatively expensive as it requires the Collider2D to be recreated from scratch. Even worse, you're likely doing so per-frame when physics doesn't even run per-frame by default unless you've selected that. Also, changing a Transform doesn't even update anything other than the Transform. Renderers only know this when they render. Likewise physics only knows this when it runs which is again, by default, during the fixed-update.

    If you change the Transform, nothing in the physics (or any other system) will follow this change. This means that if you then also run a query, it'll be querying colliders as they were the last simulation step and won't be related to the change of Transform.

    So from above, adding a Rigidbody2D and setting it to be Kinematic means it's entirely under your control. Use its API to cause it to move. Use the Rigidbody2D.position/rotation properties to refer to the position. If you want smooth motion then either set the physics to update per-frame or leave it at default and set the Rigidbody2D to use interpolation.

    There are loads of queries such as casting a Rigidbody2D or an individual collider. You can even ask the distance which also shows overlap so you can resolve overlap collisions yourself. You can control all this detection and movement.

    You just need to stop driving the Transform system as if you're driving a per-frame renderer.