Search Unity

Calculate trajectory of bouncing ball issue

Discussion in 'Physics' started by lo-94, Oct 25, 2015.

  1. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    Hey all,

    So I'm sort of stumped here, I thought I accounted for everything but there still seems to be something going wrong. Essentially what I'm doing is allowing the player to throw a ball, and I'm just trying to get some basic trajectory simulation going for the ball. For some reason, it seems that at certain points the raycasting isn't returning a hit, and the ball is sometimes passing through the floor. This is the code I have for the simulate path function that stores all the points in the trajectory. Perhaps somebody can spot an obvious mistake, as my physics programming is a bit rusty. It seems what is happening is that perhaps the segments are too large and the ray is being casted from inside the floor? Thus not registering the hit. Am I correct in thinking this or could something else be going wrong?

    Code (csharp):
    1.  
    2.     // Reference to the LineRenderer we will use to display the simulated path
    3.     public LineRenderer sightLine;
    4.  
    5.     public float ballSpeed;
    6.     public float maxDistanceToGoal = 0.1f;
    7.  
    8.     // Reference to a Component that holds information about fire strength, location of cannon, etc.
    9.     public PlayerFire playerFire; //just contains the speed and such
    10.  
    11.     private float skinWidth = 0.02f;
    12.  
    13.     // Number of segments to calculate - more gives a smoother line
    14.     public int segmentCount = 20;
    15.  
    16.     // Length scale for each segment
    17.     public float segmentScale = 0.1f;
    18.     private float radius;
    19.     private Vector3[] path;  //object to store the returned path in
    20.  
    21.     public int curPathSegment = 0;
    22.     // gameobject we're actually pointing at (may be useful for highlighting a target, etc.)
    23.     private Collider _hitObject;
    24.     public Collider hitObject { get { return _hitObject; } }
    25.  
    26.     public Vector3[] simulatePath()
    27.     {
    28.         Debug.Log ("simulate path");
    29.         Vector3[] segments = new Vector3[segmentCount];
    30.         // The first line point is wherever the player's cannon, etc is
    31.         segments[0] = transform.position;
    32.        
    33.         // The initial velocity
    34.         Vector3 segVelocity = playerFire.transform.up * playerFire.fireStrength * Time.deltaTime;
    35.        
    36.         // reset our hit object
    37.         _hitObject = null;
    38.        
    39.         for (int i = 1; i < segmentCount; i++)
    40.         {
    41.             // Time it takes to traverse one segment of length segScale (careful if velocity is zero)
    42.             float segTime = (segVelocity.sqrMagnitude != 0) ? segmentScale / segVelocity.magnitude : 0;
    43.            
    44.             // Add velocity from gravity for this segment's timestep
    45.             segVelocity = segVelocity + Physics.gravity * segTime;
    46.            
    47.             // Check to see if we're going to hit a physics object
    48.             RaycastHit hit;
    49.  
    50.                 if (Physics.Raycast(segments[i - 1], segVelocity, out hit, segmentScale))
    51.                 {
    52.                     Debug.DrawRay (segments[i - 1], segVelocity);
    53.                     // remember who we hit
    54.                     _hitObject = hit.collider;
    55.  
    56.                     if(hit.distance <= skinWidth){
    57.                         segments[i] = hit.point + (Vector3.up * (skinWidth + 0.001f));
    58.                         segVelocity = segVelocity - Physics.gravity * (segmentScale - hit.distance + skinWidth) / segVelocity.magnitude;
    59.                         segVelocity = Vector3.Reflect(segVelocity, hit.normal);
    60.                     }
    61.  
    62.                     //need to check if next point.y + segVelocity.y <= hit.point.y, if so correct
    63.                    
    64.                     else{
    65.                         // set next position to the position where we hit the physics object
    66.                         segments[i] = segments[i - 1] + segVelocity.normalized * hit.distance;
    67.                         // correct ending velocity, since we didn't actually travel an entire segment
    68.                         segVelocity = segVelocity - Physics.gravity * (segmentScale - hit.distance) / segVelocity.magnitude;
    69.                         // flip the velocity to simulate a bounce
    70.                         segVelocity = Vector3.Reflect(segVelocity, hit.normal);
    71.                     }
    72.                    
    73.                     /*
    74.                 * Here you could check if the object hit by the Raycast had some property - was
    75.                 * sticky, would cause the ball to explode, or was another ball in the air for
    76.                 * instance. You could then end the simulation by setting all further points to
    77.                 * this last point and then breaking this for loop.
    78.                 */
    79.                 }
    80.                
    81.                 // If our raycast hit no objects, then set the next position to the last one plus v*t
    82.                 else
    83.                 {
    84.                     segments[i] = segments[i - 1] + segVelocity * segTime;
    85.                 }
    86.  
    87.         }
    88.        
    89.         // At the end, apply our simulations to the LineRenderer
    90.        
    91.         // Set the colour of our path to the colour of the next ball
    92.         //Color startColor = playerFire.nextColor;
    93.         //Color endColor = startColor;
    94.         //startColor.a = 1;
    95.         //endColor.a = 0;
    96.         //sightLine.SetColors(startColor, endColor);
    97.        
    98.         sightLine.SetVertexCount(segmentCount);
    99.         for (int i = 0; i < segmentCount; i++)
    100.         {
    101.             sightLine.SetPosition(i, segments[i]);
    102.         }
    103.         return segments;
    104.  
    105.     }
    106.  
     
    Last edited: Oct 25, 2015