简体   繁体   中英

Unity3D: Find Raycasthit direction

I'm trying to make a Billiard game and I wanna calculate the direction on which the Cue Ball(white ball) will be moving after it hits another ball.

视觉效果

As you can see I wanna calculate the angle/direction in which the RAY hits the ball and the angle/direction on which the raycast will change its direction into. I need the angle to display as a Vector3 variable so I can use it on the linerenderer(3).

I already calculated the direction that the ball that gets hit will go.

If you could help me on this that would be great!

Current code:

RaycastHit hitz;
if (Physics.SphereCast(transform.position, 0.8f, location - transform.position, out hitz, Mathf.Infinity, lmm2))
{

    lineRenderer2 = hitz.collider.GetComponentInChildren<LineRenderer>();
    lineRenderer2.SetVertexCount(2);

    if (!Input.GetKey(KeyCode.Mouse0))
        lineRenderer2.SetPosition(0, hitz.point);

    if (!Input.GetKey(KeyCode.Mouse0))
       {
           Vector3 start = hitz.point;
           Vector3 end = start + (-hitz.normal * 4);

           if (lineRenderer2)
           {
               if (!Input.GetKey(KeyCode.Mouse0))
                   lineRenderer2.SetPosition(1, end);
           }

           if(lineRenderer3)
           {
               anglelel = Vector3.Angle(hitz.normal, hitz.point);
               Vector3 cross = Vector3.Cross(hitz.normal, hitz.point);
               if(cross.y > 0)
               {

                    tzt = Quaternion.AngleAxis(90f, hitz.normal) *realStick.transform.forward;
               }
              if (cross.y < 0)
               {
                  anglelel = -anglelel;
                  tzt = Quaternion.AngleAxis(270f, hitz.normal) * realStick.transform.forward;
               }
               Vector3 start2 = hitz.point;
               Vector3 end2 = start2 + ((tzt) * 5f);
               lineRenderer3.SetPosition(0, hitz.point);
               lineRenderer3.SetPosition(1, end2);
           }
        }
}

Thank you for your time.

Edit:

This part of the code has been changed to this one, currently makign some progress but still, it's not good enough. Before

if(lineRenderer3)
        {
            Vector3 start2 = hitz.point;
            //THIS IS WHERE I'M CURRENTLY STUCK AT
            Vector3 end2 = start2 + (hitz.point * 0.7f); 
            lineRenderer3.SetPosition(0, hitz.point);
            lineRenderer3.SetPosition(1, end2);
         }

After

if(lineRenderer3)
{
     anglelel = Vector3.Angle(hitz.normal, hitz.point);
     Vector3 cross = Vector3.Cross(hitz.normal, hitz.point);
     if(cross.y > 0)
     {

          tzt = Quaternion.AngleAxis(90f, hitz.normal) *realStick.transform.forward;
     }
      if (cross.y < 0)
      {
          anglelel = -anglelel;
          tzt = Quaternion.AngleAxis(270f, hitz.normal) * realStick.transform.forward;
       }
       Vector3 start2 = hitz.point;
       Vector3 end2 = start2 + ((tzt) * 5f);
       lineRenderer3.SetPosition(0, hitz.point);
       lineRenderer3.SetPosition(1, end2);
  }

Let's take this piece by piece. First off, this is a classic Physics 101 problem. The angle 2 billiard balls make on impact is a perfect 90 degree angle. Note how the green and blue vector in the following picture make a right angle:

池球的物理学

Now, you should also notice that from the point of contact to the center of both balls is normal to the surface of both balls. This means that in unity, we can use the hit.normal to get the direction of travel for the ball we hit. We just need to invert it by doing: -1 * hit.normal

Now, to get the direction the cue ball travels, we just need to rotate the previous vector 90 degrees. We can do this with a quaternion. We create a 90degree rotation about the up direction (or whatever direction is normal to the pool table) by doing: Quaternion.AngleAxis(-90, Vector3.up)

We can then calculate the angle between the original vector of travel and the angle the cue ball will travel at by doing Vector3.Angle(-1 * cue.up, rotate90 * hit.normal)

Let's look at this visual example from my test scene:

Unity池表

I color coded the vectors in unity to match the diagram above. The only difference you may notice is the black vector, which represents our hit.normal .

Here's the code:

public class Main : MonoBehaviour {
    public Transform cue,cueBallPostHit;
    public int dist = 10;
    public Color red,green,blue;

    RaycastHit hit;
    float scale,ballAngle;
    Quaternion rotate90;
    Vector3 cueBallHitPosition;

    void Start () {
        rotate90 = Quaternion.AngleAxis(-90, Vector3.up);
    }

    void FixedUpdate () {
        if(Physics.SphereCast(cue.position, .5f, cue.up, out hit, dist))
        {
            // Calculate variables
            cueBallHitPosition = hit.point + (.5f * hit.normal);
            scale = (cue.position - hit.point).magnitude;
            ballAngle = Vector3.Angle(-1 * cue.up, rotate90 * hit.normal);
            print(ballAngle);

            // Cue Ball Direction and normal
            Debug.DrawLine(cue.position, cueBallHitPosition, red);
            Debug.DrawRay(cueBallHitPosition, hit.normal, Color.black);
            // Ball direction
            Debug.DrawRay(hit.point + (-.5f * hit.normal), -1 * hit.normal * scale, blue);
            // Cue Ball Direction
            Debug.DrawRay(cueBallHitPosition, rotate90 * hit.normal * scale, green);

            // Visual for where the ball will hit
            cueBallPostHit.position = cueBallHitPosition;
        }
        else
        {
            Debug.DrawRay(cue.position, cue.up * dist, blue);
            cueBallPostHit.position = cue.position + (2 * cue.up);
        }
    }
}

Hopefully that should be enough to help you get started in the right direction, but if you have questions, let me know and I'll add some more explanations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM