Search Unity

projectile facing the trajectory it's being shot in (2D)

Discussion in 'Scripting' started by egg_citizen, Aug 1, 2019.

  1. egg_citizen

    egg_citizen

    Joined:
    Jan 3, 2019
    Posts:
    19
    I know this topic has come up more often, but the answers I found, didn't work with me somehow, so I'll just have to post this (as it's driving me crazy)

    I'm trying to create a projectile that faces the direction it's moving in.
    As the projectile is shot in an arc, the projectyle facing will change during flight.
    For this, I used the calculation of triangular corner calculation.
    When searching for Arccos (used within mathematics to calculate the corner) and Unity, the correct function should be Mathf.Acos.
    Yet, this seems to work much differently then Arccos would. (even after applying "* 180/Mathf.PI" or " * Mathf.Rad2Deg").
    I have read about it within docs.unity3d.com/ScriptReference/Mathf.Acos.html, but don't understand what it means.

    Please, can somebody help me, this should be so simple and took me so long already.

    The code I'm using so far:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Bullet : MonoBehaviour
    6. {
    7.     private float timeInBetweenCalc = 0.1f;
    8.     private Vector3 previousPos;
    9.     private Vector3 moveDirection;
    10.  
    11.     private void Start()
    12.     {
    13.         previousPos = transform.position;
    14.     }
    15.  
    16.     void Update()
    17.     {
    18.         timeInBetweenCalc -= Time.deltaTime;
    19.  
    20.         // the time in between calculations is here to be sure that the projectile has enough time to move
    21.         if (timeInBetweenCalc < 0)
    22.         {
    23.             moveDirection = transform.position - previousPos;
    24.             LookForward();
    25.             timeInBetweenCalc = 0.1f;
    26.         }
    27.  
    28.     }
    29.  
    30.     public void LookForward()
    31.     {    
    32.         previousPos = transform.position;
    33.  
    34.         float sideC = Mathf.Sqrt(moveDirection.y * moveDirection.y + moveDirection.x * moveDirection.x);
    35.         float arcCos = Mathf.Acos((moveDirection.y * moveDirection.y + sideC * sideC - moveDirection.x * moveDirection.x) / (2 * moveDirection.y * sideC)) * 180/Mathf.PI;
    36.  
    37.         transform.eulerAngles = Vector3.forward * arcCos;
    38.  
    39.  
    40.    
    41.     }
    42. }
    Edit: The calculation for the corner, I took from a website about corner calculations. So it's possible there are flaws there as well I guess?

    Expected calculation:
    x/Sin(cornerA) = y/Sin(cornerB) = sideC/Win(cornerC)
    I want the corner across x, so the calcultation to get there should be:
    cornerA = arccos(
     
    Last edited: Aug 1, 2019
  2. egg_citizen

    egg_citizen

    Joined:
    Jan 3, 2019
    Posts:
    19
    And suddenly I got it right... ok. :s. Problem solved I guess.

    Might others struggle as well, the final code has become as follows:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Bullet : MonoBehaviour
    6. {
    7.     private float timeInBetweenCalc = 0.03f;
    8.     private Vector3 previousPos;
    9.     private Vector3 moveDirection;
    10.  
    11.     private void Start()
    12.     {
    13.         previousPos = transform.position;
    14.     }
    15.  
    16.     void Update()
    17.     {
    18.         timeInBetweenCalc -= Time.deltaTime;
    19.  
    20.         if (timeInBetweenCalc < 0)
    21.         {
    22.             moveDirection = transform.position - previousPos;
    23.             LookForward();
    24.             timeInBetweenCalc = 0.03f;
    25.         }
    26.  
    27.     }
    28.  
    29.     public void LookForward()
    30.     {
    31.         previousPos = transform.position;
    32.         float sideC = Mathf.Sqrt(moveDirection.y * moveDirection.y + moveDirection.x * moveDirection.x);
    33.         float arcCos = Mathf.Acos((moveDirection.x * moveDirection.x + sideC * sideC - moveDirection.y * moveDirection.y) / (2 * moveDirection.x * sideC)) * 180/Mathf.PI;
    34.         if (moveDirection.y <= 0 || moveDirection.x <= 0)
    35.         {
    36.             transform.eulerAngles = Vector3.forward * (360 - arcCos);
    37.         }
    38.         else
    39.         {
    40.             transform.eulerAngles = Vector3.forward * arcCos;
    41.         }
    42.     }
    43. }
    44.  
     
    Last edited: Aug 1, 2019
  3. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    I don't know what it means, but you may just copy normalized velocity vector from rigidbody to transform forward vector every frame and that's it.
     
  4. egg_citizen

    egg_citizen

    Joined:
    Jan 3, 2019
    Posts:
    19
    What is means is, the way an object is moving, can always be concidered a corner in a triangle. You have upward movement (y), you have sideways movement (x), and you have the target point (somewhere between x and y).
    You also know that the starting corner is 90 degrees (well, it doesn't have to be, but makes the calculation easier).
    So then all you need is the corner that best describes the facing of the movement. That's basicly what this formula does right now.

    I did try something with the forward vector and normalized velocity, but couldn't get it working. Probably because I know too little about the working of those functions. If you wish, you can add it as one of the possible solutions by creating the code that would have helped in this situation.
     
  5. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    You need something like

    Code (CSharp):
    1. projectile.rotation = Quaternion.LookRotation(rigidbody.veloctiy);
    and that's it.