Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Script rotates around local z-axis but not around local x-axis?

Discussion in 'Scripting' started by kaysteinhoff2003, Jun 1, 2020.

  1. kaysteinhoff2003

    kaysteinhoff2003

    Joined:
    Mar 22, 2020
    Posts:
    19
    Hi so I'm making here a flying behavior for my plane to be controlled by the player. My problem here is that I try to rotate around the localRotation and it works fine on the z-axis. But somehow it won't work on the x-axis. I can't find my error in the script I bet it is something complitly rediculous.

    Anyway here is my code:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class FlyingBehavior : MonoBehaviour
    4. {
    5.     public float finalVelocity = 1000;
    6.     public float turnSpeed = 20;
    7.     public float accelerationRate = 100;
    8.     public float decelerationRate = 250;
    9.    
    10.     float initialVelocity = 0;
    11.     float currentVelocity = 0;
    12.     float xRotation;
    13.     float zRotation;
    14.  
    15.     void Update()
    16.     {
    17.         float planeX = Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime;
    18.         float planeZ = Input.GetAxis("Vertical") * turnSpeed * Time.deltaTime;
    19.        
    20.         xRotation -= planeZ;
    21.         zRotation -= planeX;
    22.        
    23.         transform.localRotation = Quaternion.Euler(xRotation, 0f, zRotation);
    24.        
    25.         if(Input.GetButton("Fire1"))
    26.         {
    27.             currentVelocity = currentVelocity + (accelerationRate * Time.deltaTime);
    28.             transform.Translate(Vector3.forward * Time.deltaTime * currentVelocity);
    29.         }else{
    30.             if(currentVelocity > 0)
    31.             {
    32.                 currentVelocity = currentVelocity - (decelerationRate * Time.deltaTime);
    33.                 transform.Translate(Vector3.forward * Time.deltaTime * currentVelocity);
    34.             }
    35.         }
    36.        
    37.         currentVelocity = Mathf.Clamp(currentVelocity, initialVelocity, finalVelocity);
    38.     }
    39. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Hmm, this certainly all seems extremely reasonable to me. Perhaps use Debug.Log() to output the values of
    xRotation
    and
    zRotation
    to see if they are both changing how you expect them to?
     
  3. kaysteinhoff2003

    kaysteinhoff2003

    Joined:
    Mar 22, 2020
    Posts:
    19
    It's all as expected but the problem here is that the plane is rotated around the global x-axis instead of the local, which makes no sense to me
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Oh I see, you're hitting .localRotation... if you don't rotate the whole plane, it will always be from that reference datum, the unrotated parent object, i.e, world space.

    Let me dig up my flight controller and post it in a few minutes here...
     
  5. kaysteinhoff2003

    kaysteinhoff2003

    Joined:
    Mar 22, 2020
    Posts:
    19
    Alright I'll wait
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Here's the relevant code, part of a much larger project. It uses a loop in Start() with Start defined as a coroutine (totally legal under Unity), although if I wrote it today I probably would not use that construct and just put it in Update().

    The FlightModelOriginalParameters stuff is just constants related to how the controls feel.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. // part of Pilot Kurt app by Kurt Dekker (@kurtdekker)
    5.  
    6. public class FlightModelOriginal : FlightModel000
    7. {
    8.     FlightModelOriginalParameters fmop;
    9.  
    10.     public FlightControlInputs fci { get; private set; }
    11.  
    12.     float MaxAltitude = 100.0f;
    13.  
    14.     public static FlightModelOriginal AttachToStatePlayer ( FlightModelOriginalParameters fmop)
    15.     {
    16.         FlightModelOriginal fmo = STATE.pf.gameObject.AddComponent<FlightModelOriginal> ();
    17.         fmo.fmop = fmop;
    18.         return fmo;
    19.     }
    20.  
    21.     void Awake()
    22.     {
    23.         fci = FlightControlInputs.Attach (gameObject);
    24.  
    25.         TimeFilteredOutput = Vector3.zero;
    26.      
    27.         STATE.PlayerFlightSpeed = 10.0f;
    28.     }
    29.  
    30.     public void DestroyThyself()
    31.     {
    32.         fci.DestroyThyself ();
    33.         Destroy (this);
    34.     }
    35.  
    36.     Vector3 TimeFilteredOutput;
    37.  
    38.     IEnumerator NoseOverAndDown( GameObject player)
    39.     {
    40.         Quaternion q1 = player.transform.rotation;
    41.         Quaternion q2 = Quaternion.Euler (70, 0, 0);
    42.         float NoseOverTime = 1.0f;
    43.         for (float t = 0; t < NoseOverTime; t += Time.deltaTime)
    44.         {
    45.             float fr = t / NoseOverTime;
    46.             player.transform.rotation = Quaternion.Lerp ( q1, q2, fr);
    47.          
    48.             player.transform.position += player.transform.forward *
    49.                 STATE.PlayerFlightSpeed * Time.deltaTime;
    50.          
    51.             yield return null;
    52.         }
    53.     }
    54.  
    55.     IEnumerator Start()
    56.     {
    57.         GameObject player = STATE.pf.gameObject;
    58.  
    59.         ServiceCeiling sc = FindObjectOfType<ServiceCeiling> ();
    60.         if (sc)
    61.         {
    62.             MaxAltitude = sc.transform.position.y;
    63.         }
    64.  
    65.         while(true)
    66.         {
    67.             STATE.UpdateCountersAndTimers ();
    68.          
    69.             if (GameModeManager.NeedSpeedIncreasing())
    70.             {
    71.                 STATE.PlayerFlightSpeed += Time.deltaTime * 0.1f;
    72.             }
    73.          
    74.             Vector3 rawOutput = fci.GetOutputRaw();
    75.  
    76.             rawOutput += new Vector3( Input.GetAxis( "Horizontal"), Input.GetAxis ( "Vertical"));
    77.          
    78.             if (SETTINGS.InvertXControls)
    79.             {
    80.                 rawOutput.x = -rawOutput.x;
    81.             }
    82.             if (SETTINGS.InvertYControls)
    83.             {
    84.                 rawOutput.y = -rawOutput.y;
    85.             }
    86.          
    87.             TimeFilteredOutput = Vector3.Lerp(
    88.                 TimeFilteredOutput, rawOutput,
    89.                 fmop.ControlSnappiness * Time.deltaTime);
    90.          
    91.             float Roll = -TimeFilteredOutput.x;
    92.          
    93.             if (player.transform.position.y > MaxAltitude)
    94.             {
    95.                 yield return StartCoroutine( NoseOverAndDown( player));
    96.             }
    97.          
    98.             Roll *= fmop.RollMultiplier;
    99.             Roll *= Time.deltaTime;
    100.             player.transform.Rotate ( new Vector3( 0, 0, Roll));
    101.          
    102.             float Turn = -player.transform.eulerAngles.z;
    103.             if (Turn < 180) Turn += 360;
    104.             if (Turn > 180) Turn -= 360;
    105.             Turn *= fmop.RollToTurnCoupling;
    106.             Turn *= Time.deltaTime;
    107.             player.transform.Rotate( new Vector3( 0, Turn, 0));
    108.          
    109.             float Pitch = TimeFilteredOutput.y;
    110.          
    111.             Pitch *= fmop.PitchMultiplier;
    112.             Pitch *= Time.deltaTime;
    113.  
    114.             if (fmop.LimitPitchEnabled)
    115.             {
    116.                 float xangle = player.transform.eulerAngles.x;
    117.                 if (xangle > 180) xangle -= 360.0f;
    118.                 if ((xangle < -fmop.LimitPitchAngle) &&
    119.                     (Pitch < 0))
    120.                 {
    121.                     Pitch = 0;
    122.                 }
    123.                 if ((xangle >  fmop.LimitPitchAngle) &&
    124.                     (Pitch > 0))
    125.                 {
    126.                     Pitch = 0;
    127.                 }
    128.             }
    129.  
    130.             player.transform.Rotate ( new Vector3( Pitch, 0, 0));
    131.          
    132.             player.transform.position += player.transform.forward *
    133.                 STATE.PlayerFlightSpeed * Time.deltaTime;
    134.  
    135.             yield return null;
    136.         }
    137.     }
    138. }
    This is the FlightModelOriginalParameters config object:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. // part of Pilot Kurt app by Kurt Dekker (@kurtdekker)
    5.  
    6. public class FlightModelOriginalParameters
    7. {
    8.     public float ControlSnappiness;
    9.  
    10.     public float RollMultiplier;
    11.  
    12.     public float RollToTurnCoupling;
    13.  
    14.     public float PitchMultiplier;
    15.  
    16.     public bool LimitPitchEnabled;
    17.     public float LimitPitchAngle;
    18.  
    19.     // <WIP> New stuff to implement:
    20.     // Roll limit
    21.     // Pitch limit
    22.  
    23.     public void ConfigureOriginal()
    24.     {
    25.         ControlSnappiness = 4.0f;
    26.         RollMultiplier = 70.0f;
    27.         RollToTurnCoupling = 0.5f;
    28.         PitchMultiplier = 50.0f;
    29.     }
    30.  
    31.     public void ConfigureFTUECanyon()
    32.     {
    33.         ConfigureOriginal ();
    34.  
    35.         RollMultiplier = 0.0f;
    36.         RollToTurnCoupling = 0.0f;
    37.         LimitPitchEnabled = true;
    38.         LimitPitchAngle = 15.0f;
    39.     }
    40. }
    You can try the app out on the appstore (iOS or Android... search for Pilot Kurt) and see what kind of controls that gives you.
     
  7. TheOtherUserName

    TheOtherUserName

    Joined:
    May 30, 2020
    Posts:
    136
    I've tried it out and it is not quit what I need but it gets in that direction. Do you know the flight controls of GTA 5? You can rotate the plane and also seperatly control the velocity. That's kinda what I'm trying to do. My problem really is that it doesn't rotate around the local axis
     
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Your line 23 generates world Euler rotations.

    Note how my code applies rotations to whatever is present in the orientation right now, first along the roll axis (line 100), then along the turn axis according to roll-to-turn coupling (line 107), and finally along local pitch axis (line 130).

    It is applying them to the actual base object in the player hierarchy, then finally it moves it (line 132), so everything is relative to where you are at any given moment.
     
  9. TheOtherUserName

    TheOtherUserName

    Joined:
    May 30, 2020
    Posts:
    136
    Thanks I haven't noticed how the rotation is apllied in line 100. There is just so much to read :) but I think that will solve my problem thanks :)
     
  10. kaysteinhoff2003

    kaysteinhoff2003

    Joined:
    Mar 22, 2020
    Posts:
    19
    Edit I debugged my script and now everything works fine! Here is my code if anyone is interested:

    Code (CSharp):
    1. sing UnityEngine;
    2.  
    3. public class FlyingBehavior : MonoBehaviour
    4. {
    5.     public float finalVelocity = 1000;
    6.     [Range(0.01f, 1f)]
    7.     public float turnSpeed = 0.5f;
    8.     public float accelerationRate = 100;
    9.     public float decelerationRate = 250;
    10.     public float flyingSpeed = 200;
    11.    
    12.     float initialVelocity = 0;
    13.     float currentVelocity = 0;
    14.     float xRotation;
    15.     float zRotation;
    16.  
    17.     void Start()
    18.     {
    19.        
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.        
    25.         if(currentVelocity >= flyingSpeed)
    26.         {
    27.             float planeX = Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime;
    28.             float planeZ = Input.GetAxis("Vertical") * turnSpeed * Time.deltaTime;
    29.        
    30.             xRotation += planeZ;
    31.             zRotation -= planeX;
    32.        
    33.             transform.Rotate(xRotation, 0f, zRotation);
    34.         }
    35.        
    36.         if(Input.GetButton("Fire1"))
    37.         {
    38.             currentVelocity = currentVelocity + (accelerationRate * Time.deltaTime);
    39.             transform.Translate(Vector3.forward * Time.deltaTime * currentVelocity);
    40.         }else{
    41.             if(currentVelocity > 0)
    42.             {
    43.                 currentVelocity = currentVelocity - (decelerationRate * Time.deltaTime);
    44.                 transform.Translate(Vector3.forward * Time.deltaTime * currentVelocity);
    45.             }
    46.         }
    47.        
    48.         currentVelocity = Mathf.Clamp(currentVelocity, initialVelocity, finalVelocity);
    49.     }
    50. }
    Thanks for the help Kurt-Dekker!​
     
    Kurt-Dekker likes this.