Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Why are my Boomerangs' vector calculations only working when I face forward?

Discussion in 'Scripting' started by PencilManners, Jul 6, 2020.

  1. PencilManners

    PencilManners

    Joined:
    May 7, 2016
    Posts:
    14
    I'm trying to create a Boomerang projectile that follows a curve I created with a line renderer. I've gotten to the point where it mostly works, as long as I'm facing forward. As I turn away, the boomerangs movement on the X-axis decreases until it's moving in the opposite direction when I've turned 180.



    This is the script for the boomerangs movement. The idea is that it's fed an array of vectors from the line renderer's script which provide the X and Y coordinates of the curve in relation to the center/Z-axis. Those X and Y coordinates are used to change the local position of a child object while it's parent handles moving back and forth on the Z-axis.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. //Moves like a boomerang that looslely follows the X and Y coordinates from the arc of the aim reticule while moving forwards on the Z axis.
    6. public class CrossMovement : MonoBehaviour
    7. {
    8.     [SerializeField]
    9.     private float ForwardSpeed = 1;
    10.     [SerializeField]
    11.     private float MaxTrackingDistance = 2;
    12.    
    13.     private ArcLine ArcReticule;
    14.     private Vector3[] TrackingList;
    15.  
    16.     private float ZDistance = 0;
    17.  
    18.     private int TrackIndex = 1;
    19.     private int IndexModifier = 1;
    20.  
    21.     private bool ReverseCourse = false;
    22.  
    23.     private GameObject Model;
    24.     private void Awake()
    25.     {
    26.         ArcReticule = GameObject.Find("AimPrefab Cross").GetComponent<ArcLine>();
    27.         Model = transform.GetChild(0).gameObject;
    28.         RefreshArray();
    29.     }
    30.  
    31.     private void RefreshArray()
    32.     {
    33.         TrackingList = null;
    34.         TrackingList = new Vector3[ArcReticule.TrackingArray.Length];
    35.         for (int i = 0; i < TrackingList.Length; i ++)
    36.         {
    37.             TrackingList[i] = ArcReticule.TrackingArray[i];
    38.         }
    39.     }
    40.  
    41.     // Update is called once per frame
    42.     private void Update()
    43.     {
    44.         //Find the vector inbetween the current tracked vector and the previous one
    45.         Vector3 TargetVector = new Vector3(TrackingList[TrackIndex].x, TrackingList[TrackIndex].y, 0);
    46.         Vector3 PreviousVector = new Vector3(TrackingList[TrackIndex - IndexModifier].x, TrackingList[TrackIndex - IndexModifier].y, 0);
    47.         float FractionBetween = (ZDistance - TrackingList[TrackIndex - IndexModifier].z) / (TrackingList[TrackIndex].z - TrackingList[TrackIndex - IndexModifier].z);
    48.         Vector3 TrackLocation = Vector3.Lerp(PreviousVector, TargetVector, FractionBetween);
    49.  
    50.         //Add the forward speed.
    51.         ZDistance += ForwardSpeed * Time.deltaTime * IndexModifier;
    52.  
    53.         //Apply X/Y movement to the model child object
    54.         Model.transform.localPosition = Vector3.MoveTowards(Model.transform.localPosition, TrackLocation, MaxTrackingDistance * Time.deltaTime);
    55.         //Model.transform.RotateAround(ArcReticule.LineStart, transform.up, transform.rotation.eulerAngles.y);
    56.  
    57.         transform.position += transform.forward * ForwardSpeed * Time.deltaTime * IndexModifier;
    58.  
    59.         //If the cross has moved past the current point of the arc, move up the array to track the next one.
    60.         if (ReverseCourse == false && ZDistance >= TrackingList[TrackIndex].z || ReverseCourse == true && ZDistance <= TrackingList[TrackIndex].z)
    61.         {
    62.             //If the cross has reached the end of the arc, move down the array and reverse speed instead.
    63.             if (TrackIndex >= TrackingList.Length - 1 && ReverseCourse == false)
    64.             {
    65.                 IndexModifier = -1;
    66.                 ReverseCourse = true;
    67.                 RefreshArray();
    68.             }
    69.  
    70.             TrackIndex += IndexModifier;
    71.  
    72.             //Debug.Log(TrackIndex);
    73.             //Debug.Log(TrackingList[TrackIndex]);
    74.         }
    75.  
    76.         if (TrackIndex <= 0 && ReverseCourse == true)
    77.         {
    78.             Destroy(gameObject);
    79.         }
    80.     }
    81. }
    And here's the portion of the line renderers script that calculates the arc.

    Code (CSharp):
    1. private Vector3 CalculateArcPoint(float t, bool ArcOrTrack)
    2.     {
    3.         //Find the position of the Vector if it was a straight line
    4.         Vector3 StraightPosition = Vector3.Lerp(LineStart, LineEnd, t);
    5.  
    6.         //Find the height of the arc at the current position
    7.         float RadianPoint = Mathf.Deg2Rad * (t * 180);
    8.         //Using the first half of a tilted sine wave so the beggining and ending height is zero while the third quarter is at max height.
    9.         float Y = Mathf.Sin(RadianPoint - (Mathf.Sin(RadianPoint) / 2)) * Height;
    10.         //account for rotation on the Z-axis
    11.         Vector3 RotationPoint = Quaternion.AngleAxis(Angle, transform.forward) * new Vector3(0, Y, 0);
    12.  
    13.         Vector3 ArcPoint = StraightPosition + RotationPoint;
    14.  
    15.         if(ArcOrTrack == true)
    16.         {
    17.             return ArcPoint;
    18.         }
    19.         else
    20.         {
    21.             float Z = Vector3.Distance(LineStart, LineEnd) * t;
    22.             return new Vector3(RotationPoint.x, RotationPoint.y, Z);
    23.         }
    24.        
    25.     }
    I'm sure it's a simple fix but I can't figure out which vector needs to be modified and whether I should be using transform.rotation, transform.up/right/forward or transform.rotatearound to fix it.
     
  2. PencilManners

    PencilManners

    Joined:
    May 7, 2016
    Posts:
    14
    I figured it out, it was because of this line of code in the ArcLine script.

    Code (CSharp):
    1. Vector3 RotationPoint = Quaternion.AngleAxis(Angle, transform.forward) * new Vector3(0, Y, 0);
    Because of transform.forward, the vectors would change based on the objects rotation. Vector3.forward fixes the boomerang but messes up the line renderer so I added an extra line in the function that redid Rotation point with Vector3.forward if it's creating a vector for the cross.

    Code (CSharp):
    1. private Vector3 CalculateArcPoint(float t, bool ArcOrTrack)
    2.     {
    3.         //Find the position of the Vector if it was a straight line
    4.         Vector3 StraightPosition = Vector3.Lerp(LineStart, LineEnd, t);
    5.  
    6.         //Find the height of the arc at the current position
    7.         float RadianPoint = Mathf.Deg2Rad * (t * 180);
    8.         //Using the first half of a tilted sine wave so the beggining and ending height is zero while the third quarter is at max height.
    9.         float Y = Mathf.Sin(RadianPoint - (Mathf.Sin(RadianPoint) / 2)) * Height;
    10.         //account for rotation on the Z-axis
    11.         Vector3 RotationPoint = Quaternion.AngleAxis(Angle, transform.forward) * new Vector3(0, Y, 0);
    12.  
    13.         Vector3 ArcPoint = StraightPosition + RotationPoint;
    14.  
    15.         if(ArcOrTrack == true)
    16.         {
    17.             return ArcPoint;
    18.         }
    19.         else
    20.         {
    21.             float Z = Vector3.Distance(LineStart, LineEnd) * t;
    22.             //Redo RotationPoint calculation using vector3.forward so that object rotation doesn't effect it
    23.             RotationPoint = Quaternion.AngleAxis(Angle, Vector3.forward) * new Vector3(0, Y, 0);
    24.             return new Vector3(RotationPoint.x, RotationPoint.y, Z);
    25.         }
    26.        
    27.     }