Search Unity

Hitscan (raycasting hits) vs Projectile simulation

Discussion in 'Scripting' started by Korno, Jun 18, 2015.

  1. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    Hey guys, I am working on a simple little FPS project - mainly to teach myself how an FPS is structured and I was wondering what your opinions are on simulating weapon hits.

    I have done a bit of googling around this and it seems there are two approaches -

    Hitscan
    Basically raycasting hits which is much easier performance wise. However you lose the ability to simulate bullet drop over distance, wind effecting bullets and even (over long ranges) the player being able to move before the bullet hits. This means the player wont have to lead the target and turns it into a point and kill game.

    Actual Projectile
    Actually generating a bullet and giving it some force and direction. Physics will take care of everything else. As far as I can see in Unity I am going to have to turn on continuous collision detection to stop the bullet passing through objects. If I started adding machine guns and other rapid fire guns to the game I guess this is going to cause the physics engine to choke up. The benifits of this is that I could even simulating bullet bounce, pentration of walls etc and I get bullet drop added for free - due to the physics engine.

    Now again I can see things that I have to consider:

    1. The scale of maps - If we are playing indoor then hitscan will be the preferred choice as there will basically be no difference at short distances.
    2. The type of weapons - If each bullet really counts and does a lot of damage and are slow firing weapons then I guess making projectiles will be better for realism. Laser weapons should of course be instant.
    3. Skill/Realism - Hitscanning means the player will not have to lead (shoot ahead of) fast moving targets and can just point and click, meaning a more arcade experience?
    4. Number of bullets/firing - If there are twenty charaters firing machines guns at each other - with 10 rounds per second I guess stuff will start to slow down quit quickly.
    So, if you have written or are writing a FPS what approaches are you taking with your weapons?

    P.S I know missiles, grenades etc will have to be projectiles.
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    It all depends on what kind of weapon you're simulating and what the distances are. I'm no gun expert, but I'm pretty sure that with modern assault weapons of the sort most FPSes love, the bullets move so fast that the effects of gravity, wind, and human-scale target movement are negligible, except over extreme distances.
     
    Korno likes this.
  3. ElectroMantis

    ElectroMantis

    Joined:
    Sep 15, 2013
    Posts:
    78
    I usually fire a raycast from the gun and then spawn a visual bullet that simply moves forward but doesn't do anything functionally. It bothers me a little though because with enough distance the enemy would react before the bullet even hit.

    When I tried collision detection, I had a problem if the bullets moved fast enough the collision wouldn't register and would go through the target.

    So here's something I thought about but never tried. What if one could place the raycast detection on the bullet itself? I'm not sure it would work unless you made your ray long enough, otherwise you'd run into the same problem regular collision detection had. I'm pretty sure it wouldn't be very efficient to have raycasting code on every bullet either. Actually this might be a terrible idea. o_O

    But then you'd have complete control of the bullet's movement anyway...
     
    dahiyabunty1 and Korno like this.
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Did you set the collision detection on the bullet to "bullet"? If you do, then (as I understand it) this is basically what the physics engine does already — it casts a ray along the path that the object moves on each frame.

    Actually, it has to do quite a bit more than that, since its collider has some extended volume. So you could probably do it more efficiently yourself. Just cast a ray the length of which is equal to how far the bullet will travel in one frame, and Bob's your uncle.

    (It's a shame Unity doesn't include a "PointCollider" class... it could very be very efficiently checked against any of the standard volume colliders, and would be perfect for stuff like this.)
     
    Alverik and ElectroMantis like this.
  5. ElectroMantis

    ElectroMantis

    Joined:
    Sep 15, 2013
    Posts:
    78
    I didn't even know about that bullet option! Is that something that's been here the whole time, or was it introduced with the Physx upgrage in Unity5?

    I feel rather silly for not seeing that. :oops:

    I'm gonna try that out as soon as I can!
     
  6. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    For an even easier implementation, cast a line that covers how far the bullet just traveled since the previous fixed update. Record the bullet's position in Start(), for example in a variable named previousPosition. In each FixedUpdate(), run a linecast from previousPosition to the current position. Then store the current position in previousPosition. You don't even need to set it to continuous mode for this.
     
    Alverik and luigi7 like this.
  7. ElectroMantis

    ElectroMantis

    Joined:
    Sep 15, 2013
    Posts:
    78
    You set the collision detection on the rigidbody component no? If so, I couldn't find a "bullet" option. Only Discrete, Continuous and Continuous Dynamic.

    The Linecast from previousPosition seems simple enough too. I'll try that as well.
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yikes, I must have been thinking of a different engine. You're right, there's no such option, though this page explains how to set things up so that it ought to work.

    So sorry for the confusion!
     
  9. tedthebug

    tedthebug

    Joined:
    May 6, 2015
    Posts:
    2,570
    Sorry for reviving this older post but I'm interested in what you came up with. I was also wondering if setting the bullets collider to just be a trigger & firing the effect when it hits something would make a difference.

    Thansk
     
  10. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    This is a good thought, but if the bullet travels too fast it might not register a collision/trigger, even with detection mode set to Continuous. It could be in front of the target in one physics update and behind the target in the next physics update without ever actually making contact in either update. The newer PhysX in Unity 5 is supposed to be better than Unity 4 in this regard, but the issue is still present for very fast-moving objects.
     
  11. tedthebug

    tedthebug

    Joined:
    May 6, 2015
    Posts:
    2,570
    I didn't think about that, the speed if the item & the tick of the check. Thanks
     
  12. Gigiwoo

    Gigiwoo

    Joined:
    Mar 16, 2011
    Posts:
    2,981
    Moving this great discussion to Scripting.
    Gigi
     
  13. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    @superpig sent out a tweet the other day asking if people were still experiencing fast bodies moving through objects which lead me to believe that Unity had addressed this internally.
     
  14. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,659
    If you have a repro for fast-moving objects skipping through colliders in Unity 5 or not producing collision messages, the physics team would LOVE to take a look at it.
     
  15. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,532
    For which version?

    I just code in an extra raycast behind the bullet from the last known position to the most recent known position and if it hits anything on the layermask then the bullet has passed through something and so I use the hit data and pop the impact manually. Works fine, runs awesome.
     
  16. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,532
    Erm, I haven't noticed any behavior change from 4.x to 5.x in this regard. Can we get the specifics of the changes to address the bullet-through-paper issue?
     
  17. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,659
    Well, the whole of PhysX got upgraded to incorporate several years' worth of changes, so I don't think we can give specifics.

    We know that continuous collision detection had issues in PhysX 2.8 / Unity 4, but physics team are under the impression that PhysX 3.3 fixed this and there are no more problems with continuous collision detection. People still talk about the issue and about needing to raycast step-to-step, so I'm just trying to establish whether this is a) still a genuine problem, b) people actually thinking of Unity 4 and assuming the problem still exists in 5, or c) people not setting it up correctly.
     
  18. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    Sorry, I was just working on hearsay for Unity 5. My linecast code works fine for me in Unity 4 & 5, so I haven't had a need to change it and test fast-moving collisions.
     
  19. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,532
    Ahh I figured out what the deal was. Took a few minutes to experiment with it this morning.

    You must use AddForce or move the rb with a physics driven method. It looks like Continuous actually makes zero difference if you use Transform to move something. Is this intentional? Certainly seems like an optimization choice but I'm not sure if it was intended for Transform changes on rb's to be captured with Continous the same way the AddForce movement is captured.
     
  20. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    I'm pretty sure it's intentional that manually changing the transform bypasses PhysX. Rigidbody.MovePosition() (that physics-driven method you mentioned) teleports a physics object to a specific point while respecting its interpolation setting.
     
  21. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,532
    It does make sense, but its curious because the Rigidbody is still moving positions when you're using Translate and collisions are still being considered... It just seems to be not handling as Continuous unless a physics method like MovePosition or AddForce has been invoked, probably dirtying the state by doing so?
     
  22. novashot

    novashot

    Joined:
    Dec 12, 2009
    Posts:
    373
    Just to throw in a small test since we are seeing new stuff in unity 5...

    Bbuilt on Unity 5.1.1f1 Personal...
    My bullet setup:
    upload_2015-7-3_15-13-17.png

    Rigid script looks like:
    Code (csharp):
    1.  
    2. public class rigid : Projectile {
    3.  
    4.     private Rigidbody myRigid;
    5.  
    6.     public override void SetUp(ProjectileInfo info)
    7.     {
    8.         base.SetUp(info);
    9.         myRigid = GetComponent<Rigidbody>();
    10.         myRigid.velocity = velocity;
    11.     }
    12. }
    13.  
    and it's base setup function is:
    Code (csharp):
    1.  
    2. // This is bullet initialization, It gets called by the weapon that fired this projectile
    3.     public virtual void SetUp(ProjectileInfo info)
    4.     {
    5.         myInfo = info;    
    6.         hitCount = 0;
    7.         velocity = myInfo.speed * transform.forward + transform.TransformDirection(Random.Range(-myInfo.maxSpread, myInfo.maxSpread) * myInfo.spread, Random.Range(-myInfo.maxSpread, myInfo.maxSpread) * myInfo.spread, 1);
    8.         collidersToIgnore.Add (myInfo.owner.GetComponent<Collider>());
    9.         backCollidersToIgnore.Add (myInfo.owner.GetComponent<Collider>());
    10.         Invoke("Recycle", myInfo.projectileLifeTime); // set a life time for this projectile
    11.     }
    12.  
    So basically just gives the rigid bullet some velocity and direction

    (edit) Forgot to mention the projectile speed is set to 1000 for the webplayer test... (end Edit)

    and here is the test webplayer:

    https://dl.dropboxusercontent.com/u/1475775/UnityForumsStuff/RigidTest/RigidTest.html

    Results to me look like it does stop the bullets pretty well using just physics..
     
    Last edited: Jul 3, 2015
    theANMATOR2b and TonyLi like this.
  23. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,659
    What do you mean by 'still being considered?' If you move the transform such that it is colliding with some other object, then on the next frame it will detect that collision and act accordingly, but it won't e.g. knock objects out of the way as it moves from its old position to its new position.

    If you're moving your object by changing the transform, then the physics system will not stop that from happening, even if you move it "through" a wall.
     
  24. Dalfamurni

    Dalfamurni

    Joined:
    Apr 24, 2015
    Posts:
    4
    I know this is old, and maybe I shouldn't revive it a second time, but it's been 5 years of development since then. This is probably still the best option, but I wanted to know if there have been any other major updates that revolutionize the way bullets are done. Someone mentioned a "bullet" collision detection option that turned out to not be in Unity, but that's a possible example of what I mean. Any major updates?
     
  25. dahiyabunty1

    dahiyabunty1

    Joined:
    Jan 22, 2020
    Posts:
    68
    first ray cast... check distance and then use formula to find time... like t = d/v;

    then after time t check where is player...

    i have seen this in pro developer coding