Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Best Bullet Collision Method

Discussion in 'Physics' started by Michael_Waltham, Apr 6, 2017.

  1. Michael_Waltham

    Michael_Waltham

    Joined:
    Aug 20, 2014
    Posts:
    29
    Hi There,

    Our small team is currently working on a 3D shooter style game. Initially, all bullets used triggers as opposed to physical colliders. We then called the appropriate damage methods and such in the OnTriggerEnter function. The result of this was bullets exploding too far into objects as there is no physical collision to correct the bullet using Rigidbody continuous collision detection before the explosion occurs. Note that this even occurred with relatively slow moving bullets as seen in the image below.

    Our solution was then to use physical colliders on the bullets with continuous rigidbody collision detection, which seems to be what Unity did in the tanks demo. This is now causing many problems further down the line as bullets physically push enemies back on impact (due to mass) as well as many other related problems. It seems far more intuitive to make bullets use trigger colliders instead however this brings us back to square one as mentioned above.

    Any suggestions on this topic would be greatly appreciated.

    89682-collisions.jpg
     
  2. Svenberra

    Svenberra

    Joined:
    Nov 5, 2012
    Posts:
    4
    One method could be to raycast instead. Give the bullet object a rigid body but no collider. Add a script to the bullet that cast a ray between the bullet's previous position and current position. If your bullets must have a volume like in the picture you could use SphereCast instead of RayCast. Also this could be used for arrows. The current and previous position also gives you the movement direction so you could align the arrow(or bullet) model along the trajectory.
     
  3. Michael_Waltham

    Michael_Waltham

    Joined:
    Aug 20, 2014
    Posts:
    29
    Thanks for the feedback. We were just wondering that surely a raycast for every bullet every frame is a bit too expensive?
     
  4. Svenberra

    Svenberra

    Joined:
    Nov 5, 2012
    Posts:
    4
    Hmm, well i haven't really used raycasts in Unity so I don't know how efficient they are.
    When CCD is enabled for an object I've read that physx use an algorithm based on the velocity to determine if discrete collision detection can be used or not. Doing a spherecast every frame would probably be a bit slower since that would be like doing a CCD Sweeptest every frame.

    But perhaps a hybrid approach could be used.
    Use your first mentioned method, that is, flag the collider as a trigger and in OnTriggerEnter do a single raycast from the previous position to get the exact point of impact.
     
  5. Michael_Waltham

    Michael_Waltham

    Joined:
    Aug 20, 2014
    Posts:
    29
    I did try that hybrid approach. Here is a simplified bit of code describing how I went about it:

    Code (CSharp):
    1. Vector3 PreviousLocation;
    2.  
    3. void OnTriggerEnter(Collider Other)
    4. {
    5.     rb.isKinematic = true;
    6.     rb.velocity = Vector3.zero;
    7.     transform.position = PreviousLocation;
    8. }
    9.  
    10. void FixedUpdate()
    11. {
    12.    PreviousLocation = transform.position;
    13. }
    Ignoring any raycasting at this point, the above code moves the object to the previous location before the trigger happens. This previous location is still inside the colliding object which makes no sense. It seems as though the trigger was called a frame late.
     
  6. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,442
    I would just drop the bullet mass down until it didn't push anything.

    Before Unity fixed continuous detection one workaround was to do a raycast every frame from the last position to the goal position (after transform updates) and if the ray could reach the distance without hitting anything then nothing was in the way and the transform could occur. If it did hit something then it was stored and did the whole damage/despawn gig. This prevented the bullet-through-paper issue and bypassed rigidbody requirements on projectiles.

    Try not to overcomplicate it, give things a good try and adjust settings to truly see if something can work. If it does and performs well then there's really not a big demand to do something different.
     
  7. Michael_Waltham

    Michael_Waltham

    Joined:
    Aug 20, 2014
    Posts:
    29
    I have managed to find a preemptive solution which is keep bullets as physical colliders and to create 4+ layers including: EnemyHitbox, PlayerHitbox etc...

    Dropping the bullet mass was also a part of this solution.
     
  8. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    I have a shelved project for a FPS game that used projectiles. I found the Physics engine is not up to handling high speed objects.

    After a lot of trial and error and fine tuning I ended up using raycast's like Svenberra suggested above. I also calculated the projectiles trajectory and handled the projectile movement in code. I found the performance to be very good, but I did do a lot of optimising.

    If your game is going to be multiplayer, then you are going to have a lot more problems to solve with lag compensation.

    https://developer.valvesoftware.com/wiki/Lag_compensation