Search Unity

Bullets go through object without Collision

Discussion in 'Scripting' started by XZ001, Dec 1, 2011.

  1. XZ001

    XZ001

    Joined:
    May 21, 2011
    Posts:
    166
    Im having an interesting problem. I have script to make a bullet move, destroy itself on collision and destroy itself after a certain time period if it doesn't hit anything. Here's the script:

    Code (csharp):
    1. var lifetime = 1.0;
    2. var speed = 10.0;
    3. var xrot : float;
    4. var yrot : float;
    5. var zrot : float;
    6.  
    7. function Awake()
    8.     {
    9.     xrot = Random.Range(-0.05, 0.05);
    10.     yrot = Random.Range(-0.05, 0.05);
    11.     zrot = Random.Range(-0.05, 0.05);
    12.     transform.rotation.x += xrot;
    13.     transform.rotation.y += yrot;
    14.     transform.rotation.z += zrot;
    15.     }
    16.  
    17. function Update ()
    18.     {
    19.     var forward = transform.TransformDirection(Vector3.forward);
    20.     lifetime -= 1.0 * Time.deltaTime;
    21.     transform.position += forward * speed * Time.deltaTime;
    22.     if(lifetime <= 0.0)
    23.         {
    24.         Destroy(gameObject);
    25.         }
    26.     }
    27. function OnTriggerEnter()
    28.     {
    29.     Destroy(gameObject);
    30.     }
    (The xrot, yrot, etc is just for lowering accuracy so it can just be ignored). All of this works well except for one problem. If the bullets go too fast they will go right through an object without registering a collision. I understand why this happens, but my question is: Is there a way to fix it so they will register a collision no matter what the speed is?
     
  2. TheSpaceMan

    TheSpaceMan

    Joined:
    Nov 6, 2011
    Posts:
    153
    This is a common problem with physics, I haven't done this in unity, but there should be some settings for continious collision detection. Since collision is often only handled at the objects position the bullet is in theory not colliding with the plane. ;)

    If there is no continious collision detection or simular, you could store the old position in the bullet and shoot a ray between your old and new position and see if it hits something, in theory the same idea, except the ray is smaller and migt require more/less juice.
     
  3. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    What speed are we talking? 10? Thats slow. My projectiles fly at around 500

    Are you using rigidbodies?

    Do you have the trigger boxes ticked?


    Side note: Rather than counting how long the projectile has been alive, why dont you just put Destroy(gameObject, 5) in awake so it destroys after 5 seconds (or whatever you want your lifespan to be)


    Rather than moving the bullet manually, you should just use rigidbody.AddForce
     
    Last edited: Dec 1, 2011
  4. TheSpaceMan

    TheSpaceMan

    Joined:
    Nov 6, 2011
    Posts:
    153
    The speed of the object is irrelevant if you don't know the size, you will still have the same issues.
     
  5. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    If you say so...I have a bullet prefab that works perfectly, but I guess you know better.
     
  6. TheSpaceMan

    TheSpaceMan

    Joined:
    Nov 6, 2011
    Posts:
    153
    A bullet of size 1 that travels 500 units will travel 500 times it own distance per second.
    A bullet of size 0.001 that travels 500 units will travel 500000 it's own size in distance.

    Let's say a constant frame rate of 60 fps.

    0.016666666666666666666666666666667 seconds per frame.
    The distance travelled is thus 8.333333333333333333333333333 units per update.

    if an object is less then 8.333 units - bulletsize*2 thick, You risk missing it if one update the bullet is just before the geomatry and the other update just after, if there is no continious collision detection active. Since when the checks are done, the bullet doesn't actually intersect anything. This is nothing I make up, this is how a physics engine work. It's possible that unity have this activate by default. In most physics engines it's not.
    If your prefab work, good for you.
     
  7. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    what makes you think there is not continuous collision detection..

    there are additional interpolation/extrapolation options if its missing, but in most cases this shouldnt be required.
     
  8. handsomePATT

    handsomePATT

    Joined:
    Nov 30, 2010
    Posts:
    574
    I just had this problem and the best way i found was to shoot a short raycast in front to see if you hit anything and handle it yourself
     
  9. TheSpaceMan

    TheSpaceMan

    Joined:
    Nov 6, 2011
    Posts:
    153
    In most physics engine it's deactivated because its not needed for every object, rather you activate it for the relevent fast moving objects since it drains a lot more CPU per update.
     
  10. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    And you know for sure this is how the unity engine works because....
     
  11. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    More specifically - do a RayCast in front of the object equal to the distance it will travel in that frame. If it returns a hit, move the projectile to that position and do whatever collision magic you need to do, if not then allow it to move normally. This is generally the most reliable way to handle it.
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Because there's a drop-down for rigidbodies with Discrete, Continuous, and ContinuousDynamic options, which are explained in the docs. Discrete is default, because it uses less CPU time. Interpolation has no effect on collisions, since it's a purely visual function and doesn't affect physics.

    What you should do is this:

    Code (csharp):
    1. var force = 500.0;
    2. var lifeTime = 1.0;
    3.  
    4. function Start () {
    5.     rigidbody.AddForce(Vector3.forward * force);
    6.     Destroy(gameObject, lifeTime);
    7. }
    Plus whatever else you need for the "lowering accuracy" stuff. Make the object have a rigidbody, set to ContinuousDynamic. Make static objects that it must collide with have kinematic rigidbodies set to Continuous. In another topic recently I said that raycasting is still the only 100% effective method, but I think I take that back. It's been a while since I've used continuous dynamic, and testing just now it seems completely effective, so if it had issues before, they seem to have been fixed. The downside is more CPU time, plus you can't get away with just using colliders for static objects, they must be kinematic rigidbodies set to Continuous.

    --Eric
     
  13. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    yes but there must be some sort of continuous collision detection otherwise it would never detect one... anyways, who cares, its going above what this thread needed, which is the code you have posted, which is the same as the code I use, which works perfectly well.

    Worth noting, I didnt have to set my rigidbodies to anything other than discrete to get the collisions working fine.
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I don't think you actually read my post. There's continuous collision detection only if you explicitly use ContinuousDynamic for the object in motion in combination with Continuous for static objects. Otherwise it's discrete.

    It doesn't work perfectly well, or else the OP wouldn't have started this topic and stated: "If the bullets go too fast they will go right through an object without registering a collision."

    You *will* have objects going through colliders if you're using only discrete collision, if the object is going fast enough and the colliders are thin enough. It's a mathematical fact, which can be demonstrated with trivial ease.

    --Eric
     
  15. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I did read what you said and understood. My point was that there must always be some form of detection even for discrete, otherwise there would never be any collision/trigger event fired... Maybe my interpretation of how it works is wrong, but its still detecting a collision.

    Yes, but the OP is using a completely different method of moving the object, which is why I stated that the addforce/rigidbody approach works perfectly well... sure there are misses, but it gets most of them from what I have seen. I havnt done a test to see how many are missing, but it wasnt enough to concern me when im firing approximately 200/s @ 500 m/s and the majority are hitting the mark

    I could appreciate using continuous detection if the object was moving really fast, but in this case it seems the speed multiplier is only around 10 * Time.deltaTime, which isnt a super fast movement.
     
  16. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    I have kind of the same setup- when I put my speed above 600 my projectile passes through with no collision. I haven't tried adding the force yet to see if I can go higher.
     
  17. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    try erics suggestion and change the collision type
     
  18. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    What's the lifetime var for?? I have my projectile to die on collision with the enemy or terrian.....;)
     
  19. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    That assumes it is always going to hit one of those two things...

    there is a high possibility it may never! ie. Near edge of terrain fire at angle so that the trajectory means its going to go off terrain
     
  20. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    I also have it so it destroys itself after 5000m incase.

    Whats that lifetime var for???
     
  21. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    yes... you may also want the bullet to be ineffective after a shorter period of time.. ie if it hasnt hit an object within 2 seconds, its going to lose all effectiveness and do no damage... like say a shotguns buckshot rather than sniple rifle projectile
     
  22. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    Rgr, I take that back its 2000m when it dies not 5k-

    Its working out pretty good, although I would like it to go faster. I will try the addforce deal and see if it helps-
     
  23. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    It depends what your doing, you see I have a minigun turret that spits out 1000 bullets in a few seconds. I dont want 1000 projectiles lingering too much longer than required, so they have a reasonably small lifespan. They travel really fast, and there are lots, so they die in about 0.5 second to make sure im not going above whats really required
     
    roloriley2 likes this.
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Well, yes, clearly discrete collision detects collisions, that's what it's for. It can only do so if the objects overlap at some point, however. If the object is moving fast enough, it will go "through" the collider, because it's being moved (teleported, really) in discrete (hence the name) intervals. So it can be in front of a collider one frame, then behind it the next, with no overlap, hence no collision detected. If you want to prevent this, you'd need to use continuous collision, which actually takes into account colliders that may be between the two positions.

    Typically with things like miniguns you don't bother with actual projectiles at all, you just fake it with raycasting, unless for some reason you need 100% ultra realism at the expense of performance.

    --Eric
     
  25. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    That was my point. You get what I meant, and I understood what you meant, so that's great, lets move on :_)

    The reason I still fire bullets is I have tracers. If it turns out the performance is a problem, I'll replace it with ray casting. At this point I dont want to use rays, because that is a definite hit regardless of how fast the target is moving. I want the player to have a chance at not being shot to bits as soon as they get in range. I may change my mind on this later, but for now its how it is and works nice enough.
     
  26. XZ001

    XZ001

    Joined:
    May 21, 2011
    Posts:
    166
    Sorry for being so late to reply. I didn't have much of an opportunity to use the computer until now. And 10 is just the speed it was at there because that was where it could still detect the collisions. I checked the rigidbody and it's set to descrete collision detection so I will try changing it to continuous and if that doesn't work I will try the RayCast solution. Thanks a lot for the advice guys!
     
    DDeathlonger likes this.