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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Why is this rotation not working?

Discussion in 'Scripting' started by Sporech, Oct 13, 2015.

  1. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Hi, here i have a projectile class. It will always travel along the x-axis (for now) and the projectiles will deviate. I made it so it will rotate the projectiles (which are long thin cylinders) so that they appear to go in a straight line, but they dont rotate. Can anyone see anything wrong?
    Code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Projectile : MonoBehaviour {
    5.     private int pathway;
    6.  
    7.     private int ydeviation;
    8.     private int zdeviation;
    9.  
    10.     void Start () {
    11.         int pathway = 10;
    12.         ydeviation = Random.Range (-1, 2);
    13.         zdeviation = Random.Range (-1, 2);
    14.         Vector3 deviatedvector = new Vector3 (0, ydeviation, zdeviation);
    15.         this.gameObject.transform.Rotate (deviatedvector);
    16.     }
    17.  
    18.     void Update () {
    19.         Vector3 location = new Vector3(this.gameObject.transform.position.x,this.gameObject.transform.position.y,this.gameObject.transform.position.z);
    20.         location.x += 5;
    21.         location.y += ydeviation;
    22.         location.z += zdeviation;
    23.         this.gameObject.transform.position = location;
    24.         pathway = pathway - 1;
    25.         if (pathway == 0) {
    26.             Destroy (this.gameObject);
    27.         }
    28.     }
    29. }
     
  2. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Just to add, they never despawn, the part which says
    Code (CSharp):
    1. pathway = pathway - 1;
    2.         if (pathway == 0) {
    3.             Destroy (this.gameObject);
    4.         }
    Should make it despawn after so many frames. I can't see the problem though.
     
  3. SomeGuy22

    SomeGuy22

    Joined:
    Jun 3, 2011
    Posts:
    722
    There's some redundant code there-- First off

    Code (CSharp):
    1.  Vector3 location = this.gameObject.transform.position;
    Is much simpler :p Also if pathway is 10, and you're decreasing by 1 every frame, the object will be gone in 10 frames... That's pretty extreme, not sure if you know that. Most time counters need to be frame-independent, which means you'll need to use Time.deltaTime instead of just decreasing an integer. Rethink that part~ But even if you were going for just 10 frames of existence, you need to keep an eye out for what variables you are changing. You have an int pathway already defined in the Projectile class, but you make a new one in Start()! So change int pathway to just pathway in the Start function. (The pathway in Projectile defaults to 0. 0 - 1 = -1. So your logic statement would never hit)

    The frame-independent thinking also applies for your location changes. You should take Time.deltaTime into account instead of just adding 5 to the x component each frame.

    The random deviation part looks correct, but keep in mind that when you feed it ints, you'll get 1 less/more than you enter. If you have Random.Range(-1, 2) than you'll only either get 0 or 1. (Something to do with rounding and the way arrays are handled) So there's a chance that rotations are 0. Also, 1 is a pretty small change. Try larger numbers, and try a Debug.Log to see what numbers are actually getting output to the system.
     
  4. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Okay, i fixed the fact it wasn't rotating at all, i used a quaternion.
    Here's the updated code:
    Code (CSharp):
    1. using System.Collections;
    2.  
    3. public class Projectile : MonoBehaviour {
    4.     private int pathway;
    5.  
    6.     private float ydeviation;
    7.     private float zdeviation;
    8.  
    9.     void Start () {
    10.         int pathway = 10;
    11.         ydeviation = Random.Range ((float)-0.5, (float)0.5);
    12.         zdeviation = Random.Range ((float)-0.5, (float)0.5);
    13.  
    14.         float yrot = this.gameObject.transform.rotation.y;
    15.         yrot += ydeviation;
    16.         float zrot = this.gameObject.transform.rotation.z;
    17.         zrot += zdeviation;
    18.         this.gameObject.transform.rotation = new Quaternion (0, yrot, zrot, 0);
    19.     }
    20.     void Update () {
    21.         Vector3 location = new Vector3(this.gameObject.transform.position.x,this.gameObject.transform.position.y,this.gameObject.transform.position.z);
    22.         location.x = (location.x + 5);
    23.         location.y += ydeviation;
    24.         location.z += zdeviation;
    25.         this.gameObject.transform.position = location;
    26.         pathway = pathway - 1;
    27.         if (pathway == 0) {
    28.             Destroy (this.gameObject);
    29.         }
    30.     }
    31. }
    I am having a few other problems though. It doesn't make the projectile straight, it just goes at a wierd angle, and im stuck on ideas of how to make it look straight. :/
    Any suggestions?
     
  5. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Also, could you give an example of how i could use delta-time in this way? Thanks ;)
     
  6. SomeGuy22

    SomeGuy22

    Joined:
    Jun 3, 2011
    Posts:
    722
    It's because your location is getting the deviations added. Rotation units are different than position units. Instead use transform.Translate(), and just add forwards movement. Translate takes into account object rotation, so you can add to the position locally.
    http://answers.unity3d.com/questions/296336/timedeltatime.html
     
  7. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Okay, i get that part, but how do i get my projectiles at the correct rotation in the first place?
     
  8. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Are you trying to access the Quaternion.y and z components as if they were angles of some sort? It doesn't work like that.
     
  9. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    I guess so, can you link me to a quaternion page
     
  10. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    I'm not sure what you're trying to accomplish with the deviations. But aside from that, modifying a Quaternion to represent a different rotation is quite simple. You just need to multiply the delta rotation (a Quaternion again) on top of it. For example, the following equation is true:

    Quaternion.Euler(0, 0, 50) = Quaternion.Euler(0, 0, 20) * Quaternion.Euler(0, 0, 30)
     
  11. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    I am trying to get bullet spread working, (notice the name of the class: Projectile). What does the euler bit mean? Could you explain your example, so i can apply it? That would help :)
     
    Last edited: Oct 14, 2015
  12. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Documentation: http://docs.unity3d.com/ScriptReference/Quaternion.Euler.html

    Quaternion.Euler() creates a Quaternion from Euler angles. So in my example, I create a Quaternion representing a rotation 20 degrees about the Z axis. To arrive at 50 degrees, I need to rotate another 30 degrees. To do so, I multiply a 30 degrees rotation on top of the 20 degrees.
     
  13. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Okay, thx that's great :D. I've managed to find a way to make quaternions work for it:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Projectile : MonoBehaviour {
    5.  
    6.     public float pathway;
    7.  
    8.     void Start () {
    9.         float ydeviation = Random.Range ((float)-0.06, (float)0.06);
    10.         float zdeviation = Random.Range ((float)-0.06, (float)0.06);
    11.         Quaternion currentrot = this.gameObject.transform.rotation;
    12.         currentrot.Set(currentrot.x,currentrot.y+ydeviation,currentrot.z+zdeviation,currentrot.w);
    13.         this.gameObject.transform.rotation = currentrot;
    14.     }
    15.     void Update () {
    16.         this.gameObject.transform.Translate (new Vector3 (0, 6, 0));
    17.         this.pathway = this.pathway - Time.deltaTime;
    18.         if (this.pathway < 0) {
    19.             Destroy (this.gameObject);
    20.         }
    21.     }
    22. }
     
  14. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Well, no. I think I wasn't clear enough previously. The components of the Quaternion (x, y, z, and w) are not the same as Euler angles. You can mess around with them, but you really should know how Quaternions work internally. If you do without knowing what you're doing, you will most certainly mess up your angles and get very weird rotations.
     
  15. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Okay, could you give a better example? I need to get into good habits, this one does work, but I guess if it will cause future trouble, it would be good if you can show me a good example.

    On the plus side, i managed to fix the despawn issue ^^.
     
  16. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    As I understood your issue, you will want to shoot projectiles in a cone rather than a straight line? So for this, it should be a matter of spawning a projectile looking straight forward, and then adjusting its rotation about the Y axis (left/right) and X axis (up/down.)

    So assuming you spawned the projectile and it is already looking straight forward, this should do the trick:

    Code (csharp):
    1. projectile.transform.rotation *= Quaternion.Euler(
    2.   Random.value * maxAngle * 2 - maxAngle,
    3.   Random.value * maxAngle * 2 - maxAngle,
    4.   0);
    With this you should be able to use a maxAngle of 5 for example, and the result would be a deviation of -5 to +5 degrees to the left/right and up/down.
     
  17. Sporech

    Sporech

    Joined:
    Sep 14, 2015
    Posts:
    26
    Okay, thx mate. The my previous code does work, but i can appreciate that it may not be great practise; thanks for the advice.