Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Rocket Collision Detection Using Raycast Is Faulty

Discussion in 'Scripting' started by Scissors, Jun 28, 2014.

  1. Scissors

    Scissors

    Joined:
    Jun 13, 2013
    Posts:
    22
    Hey, Im busy working on weapon systems, making unguided rockets which move along a bezier curve. Each rocket ray casts ahead of itself towards the next intended position along the curve BEFORE executing any form of translation. If no collision has occurred (ignoring objects in layer 9), then movement may be executed. The CollisionHandler() function contains all the necessary statements to be executed upon collision.

    The problem lies at the point of collision detection (rayCast), a successful collision is never determined, unless the rocket's position is absolutely against a collider's surface before casting the ray, an unlikely event.

    I cant seem to find my fault, any assistance would be greatly appreciated. The code is as follows:

    Code (JavaScript):
    1. function Update()
    2. {
    3.     //Check for collision [*CollisionHandler returns inverse operation]
    4.     if(!hit && CollisionHandler())
    5.     {
    6.         Move();
    7.     }
    8.     else if(shockwave.radius < shockwaveRadius)
    9.     {
    10.         shockwave.radius += shockwaveDelta * Time.fixedDeltaTime;
    11.     }
    12. }
    13.  
    14.  
    15. //Execute collision side-effects
    16. function CollisionHandler(): boolean
    17. {
    18.     //Update next position
    19.     UpdatePos();
    20.     //Draw ray for debugging purposes
    21.     Debug.DrawRay(transform.position, (Vector3(nextPos.x, nextPos.y, transform.position.z) - transform.position), Color.red, 1);
    22.     //Extrapolative raycast collision check
    23.     if(Physics.Raycast(transform.position, (Vector3(nextPos.x, nextPos.y, transform.position.z) - transform.position), hitInfo, moveDelta * Time.fixedDeltaTime, 9))
    24.     {
    25.         print("Hit");
    26.         hitInfo.transform.BroadcastMessage("Hit", primaryDamage, SendMessageOptions.DontRequireReceiver);
    27.         transform.position = hitInfo.point;
    28.         emitter.Emit();
    29.         hit = true;
    30.         return false;
    31.      
    32.     }
    33.     else
    34.     {
    35.         print("noHit");
    36.         return true;
    37.     }
    38. }
    39.  
    40.  
    41. //Execute translation
    42. function Move()
    43. {
    44.     transform.position = Vector3(nextPos.x,  nextPos.y, transform.position.z);
    45. }
    46.  
    47.  
    48. //Calculate next position on bezier curve
    49. function UpdatePos()
    50. {
    51.  
    52.     bezierIndex += (moveDelta * Time.fixedDeltaTime);
    53.     nextPos.x = (((1-bezierIndex)*(1-bezierIndex)) * startPos.x) + (2 * bezierIndex * (1 - bezierIndex) * handle.x) + ((bezierIndex * bezierIndex) * endPos.x);
    54.     nextPos.y = (((1-bezierIndex)*(1-bezierIndex)) * startPos.y) + (2 * bezierIndex * (1 - bezierIndex) * handle.y) + ((bezierIndex * bezierIndex) * endPos.y);
    55. }
    56.  
     

    Attached Files:

    Last edited: Jun 29, 2014
  2. Fluzing

    Fluzing

    Joined:
    Apr 5, 2013
    Posts:
    815
    Have you tried using linecast? Raycasts behave differntly than you expect maybe.

    http://docs.unity3d.com/ScriptReference/Physics.Linecast.html

    In my experience, this is better for determining collisions between two points.

    Edit: Time.fixedDeltaTime is a very small number I believe, causing the length of your ray to be very short.

    Edit 2: that is also no the right way to LayerMask.
     
    Last edited: Jun 28, 2014
  3. Scissors

    Scissors

    Joined:
    Jun 13, 2013
    Posts:
    22
    Hey, thanks for the quick reply... yeah, im aware of lineCast, but I dont need to detect collision from within an object and lineCast is more process intensive... I really dont get what im doing wrong here, the debug ray even draws correctly... I multiply the length of the ray by time.fixedDeltaTime to make the ray the same length as the object will translate in a frame... the way the script is balanced, that is about 1.1m in-game. That is done to check if its safe to translate to the new position, and it works for another bullet script iv made, perfectly. just since iv added the bezier its been a problem
     
  4. Fluzing

    Fluzing

    Joined:
    Apr 5, 2013
    Posts:
    815
    Why don't you use a collider on the missile to determine collision?
     
  5. Scissors

    Scissors

    Joined:
    Jun 13, 2013
    Posts:
    22
    Its just too expensive. Basic colliders require a rigidBody to get anything above discrete collision detection and even using a rigidBody on continuous dynamic is not as fail-safe as a ray-cast. it just increases the collision sample rate, and on objects which move more than extremely fast, its still possible to end up intersecting a collider or jumping it completely. At the same time, a rayCast or lineCast will provide the exact point of collision in world space which is extremely useful for effect deployment... :'(
     
  6. Scissors

    Scissors

    Joined:
    Jun 13, 2013
    Posts:
    22
    Edit 2: that is also no the right way to LayerMask.[/QUOTE]

    huh? what do you mean? how should the layer mask be provided? i was under the impression it was an integer value representing the Layer array position?
     
  7. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    836
    Hey, could you provide the entire script to make it easier for us to test? To try a simple debug, I'd replace your distance in your raycast with the magnitude of:

    Code (csharp):
    1. (Vector3(nextPos.x, nextPos.y, transform.position.z)- transform.position)
    This will ensure your raycast is just from the start of the debug ray to the end.

    LayerMasks are integers read as a bitmask to represent which layers are "masked." To construct a layermask masking a single layer you typically just bitshift 1 left the layer's index, so, 1 << 8 would mask layer 8. I wouldn't bother masking while debugging this though, just makes it more complex.
     
    Scissors likes this.
  8. Scissors

    Scissors

    Joined:
    Jun 13, 2013
    Posts:
    22
    O M F dude... i just need some serious sleep... it was the length of the ray, i wasnt thinking clearly ;P thanks so much, magnitude's the one :)
     
  9. Scissors

    Scissors

    Joined:
    Jun 13, 2013
    Posts:
    22
    could i ask one more question? how do i accept your answer as most correct? iv never had to post an issue on the forums here before ;P
     
  10. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    836
    I don't think you can. The forum just got updated, so I'm not super up to date on it, but since this is more for discussion it's not to just focus on a "best answer."

    Unity Answers does have the Stack Overflow format where you select a best answer, though.
     
    Scissors likes this.