2016-08-22 5 views
1

Я пытаюсь создать игру в бильярд, и я хочу рассчитать направление движения мяча (белого шара) после того, как он ударит по другому шару.Unity3D: Найти направление Raycasthit

Visuals

Как вы можете видеть, что я хочу вычислить угол/направление, в котором RAY ударяется мяч и угол/направление, на котором raycast изменит свое направление в. Мне нужен угол для отображения в виде переменной Vector3, поэтому я могу использовать его на linerenderer (3).

Я уже рассчитал направление, в которое попадет мяч.

Если бы вы могли помочь мне в этом, это было бы здорово!

Текущий код:

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); 
      } 
     } 
} 

Спасибо за ваше время.

Edit:

Эта часть кода была изменена на этом, в настоящее время makign некоторый прогресс, но все же, это не достаточно хорошо. Перед

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); 
     } 

После

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); 
    } 
+0

Это больше проблема физики, чем строго кодирование игры. Если вы пытаетесь визуализировать результат применения силы в этой точке бильярдного шара, вам нужно выполнить вычисления, используя его физические атрибуты, а не только такие, как лицевые нормали. Вот концепция, чтобы вы начали - вам нужно перевести ее в код: http://physics.stackexchange.com/questions/43232/force-applied-off-center-on-an-object – Serlite

+0

Не совсем то, что Я искал. Проблема, о которой они говорят, находится в 2D-пространстве, в то время как моя игра в 3D. – Ssiro

+0

Ваша игра отображается в 3D, но если ваша бильярдная таблица не плоская, вся физика может быть упрощена до 2D, так как все они останутся на плоскости XZ. – Serlite

ответ

3

Давайте возьмем этот кусок за куском. Во-первых, это классическая проблема физики 101. Угол 2 бильярдных шариков на ударе - идеальный угол 90 градусов. Обратите внимание, как зеленый и синий вектор на рисунке сделать правильный угол:

Physics of a pool ball

Теперь, вы должны также заметить, что с точки контакта к центру обоих шаров нормаль к поверхности и мячи. Это означает, что в единстве мы можем использовать hit.normal, чтобы получить направление путешествия за мяч, который мы попали. Нам просто нужно инвертировать его: -1 * hit.normal

Теперь, чтобы получить направление движения мяча, нам просто нужно повернуть предыдущий вектор на 90 градусов. Мы можем сделать это с помощью кватерниона. Мы создаем поворот на 90 градусов по направлению вверх (или независимо от направления, нормального к бильярдному столу): Quaternion.AngleAxis(-90, Vector3.up)

Затем мы можем рассчитать угол между исходным вектором движения и углом, по которому биток будет перемещаться на делает Vector3.Angle(-1 * cue.up, rotate90 * hit.normal)

Давайте посмотрим на этот визуальный пример из моей тестовой сцены:

Unity pool table

I цветом векторы в единстве, чтобы соответствовать диаграмме выше. Единственное отличие, которое вы можете заметить, это черный вектор, который представляет наш hit.normal.

Вот код:

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); 
     } 
    } 
} 

Надеется, что должно быть достаточно, чтобы помочь вам начать работу в правильном направлении, но если у вас есть вопросы, дайте мне знать, и я добавлю еще несколько объяснений.