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. Dismiss Notice

C# movement relative to direction

Discussion in 'Scripting' started by Decroded, Aug 14, 2014.

  1. Decroded

    Decroded

    Joined:
    Aug 14, 2014
    Posts:
    9
    Sorry I'm really new to Unity, trying to understand how Vector3 and Eulers can interact.
    Right now attempting old school RPG style grid movement (Legend of Grimrock) in 1 metre blocks on X & Z, with only 90 degree turns on Y.
    First keeping simple by instant move/rotate instead of over time (so no timedelta yet).

    Below works fine except when I press forward (W), it always moves in same direction (moveVector) regardless of which way the Hero is facing (faceDir).

    Questions:
    1) Can someone please help with the particular calculation highlighted in red?
    2) I intentionally store faceDir independently of camera angle though I would also like to know how to read the GameController's direction without needing to use this var.

    Much appreciated!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class HeroC2 : MonoBehaviour {
    5.     Vector3 faceDir = new Vector3(0,0,0);
    6.     Vector3 moveVector = new Vector3(0,0,0);
    7.     // Use this for initialization
    8.     void Start () {
    9.         Screen.lockCursor=true;
    10.         transform.rotation = Quaternion.Euler(faceDir);
    11.     }
    12.  
    13.     // Update is called once per frame
    14.     void Update () {
    15.  
    16.         CharacterController cc = GetComponent<CharacterController>();
    17.  
    18.         //Rotation
    19.         if (Input.GetKeyDown(KeyCode.Q)) {
    20. //            faceDir = faceDir + new Vector3(0,-90,0);
    21.             faceDir[1] -= 90;
    22.             transform.rotation = Quaternion.Euler(faceDir);  
    23.         }      
    24.         if (Input.GetKeyDown(KeyCode.E)) {
    25. //            faceDir = faceDir + new Vector3(0,90,0);
    26.             faceDir[1] += 90;
    27.             transform.rotation = Quaternion.Euler(faceDir);  
    28.         }
    29.      
    30.      
    31.         //Translation
    32.         if (Input.GetKeyDown(KeyCode.W)) {
    33. //            moveVector = new Vector3(0,0,1);
    34.             moveVector = Vector3.forward;
    35.         }
    36.         if (Input.GetKeyDown(KeyCode.S)) {
    37.             moveVector = Vector3.back;
    38.         }
    39.         if (Input.GetKeyDown(KeyCode.A)) {
    40.             moveVector = Vector3.left;
    41.         }
    42.         if (Input.GetKeyDown(KeyCode.D)) {
    43.             moveVector = Vector3.right;
    44.         }
    45. //        moveVector=moveVector+faceDir;    //<--THIS IS WHERE I NEED HELP
    46.         if (Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.S)
    47.                 || Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.D)){
    48.             cc.Move(moveVector);
    49.         }
    50.     }
    51. }
     
  2. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    This is better in my opinion. I can do that vector math if you want but I'd rather avoid it. =)

    EDIT: Well I'm pretty sure, not 100% confident, that specific line would be moveVector = transform.rotation * moveVector; Don't do both this line and the code below. It's one or the other.
    Code (csharp):
    1.         if (Input.GetKeyDown(KeyCode.W)) {
    2.             moveVector = transform.forward;
    3.         }
    4.         if (Input.GetKeyDown(KeyCode.S)) {
    5.             moveVector = -transform.forward;
    6.         }
    7.         if (Input.GetKeyDown(KeyCode.A)) {
    8.             moveVector = -transform.right;
    9.         }
    10.         if (Input.GetKeyDown(KeyCode.D)) {
    11.             moveVector = transform.right;
    12.         }
     
    Decroded likes this.
  3. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Question 2:
    Code (csharp):
    1. if (Input.GetKeyDown(KeyCode.Q)) {
    2.   transform.Rotate(new Vector3(0f, -90f, 0f));
    3. }    
    4. if (Input.GetKeyDown(KeyCode.E)) {
    5.   transform.Rotate(new Vector3(0f, 90f, 0f));
    6. }
    7. // if you need it:
    8. // faceDir = transform.eulerAngles;
    http://docs.unity3d.com/ScriptReference/Transform.html
    http://docs.unity3d.com/ScriptReference/Quaternion.html
     
    Last edited: Aug 14, 2014
    Decroded likes this.
  4. Decroded

    Decroded

    Joined:
    Aug 14, 2014
    Posts:
    9
    Hey thanks, transform.forward works but the other directions throw an error.


    I don't want to bite off too much but I do need to start understanding the basics of vector math.
    I've been watching videos and doing tutorials I haven't figured out how to create a vector that is relative to a direction.

    Your other line of code worked though thanks alot!
    Code (CSharp):
    1. moveVector = transform.rotation * moveVector;
     
  5. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Yeah man, for some reason Vector3.right and Vector3.left exist, but only transform.right.

    transform.left does not exist. transform.back does not exist. transform.down does not exist. It's tricky, but if you check the documentation you'll see the same thing.

    That's okay though because negative transform.right is the same as transform.left. (-transform.right == transform.left if it existed.)
    Vector3.left == new Vector3(-1, 0, 0) == -1 * new Vector3(1, 0, 0) == -1 * Vector3.right

    That's why you see in my code I use -transform.forward, -transform.right, and -transform.up.
     
    Last edited: Aug 14, 2014
    Decroded likes this.
  6. Decroded

    Decroded

    Joined:
    Aug 14, 2014
    Posts:
    9
    Sorry yes both those ways work.
    Thanks alot :)

    And thanks for answering Q2 also.
    Its still pretty hazy but hopefully it becomes clearer as I gain more XP ;)
     
    Last edited: Aug 15, 2014
    GarthSmith likes this.
  7. Decroded

    Decroded

    Joined:
    Aug 14, 2014
    Posts:
    9
    Back with more nooby questions.
    Everything working perfectly for moving/rotating instantly, now I'm struggling making smooth transition between grid blocks.

    Below code works OK except it seems I'm doing something wrong when I set destPos.
    First I tried destPos = transform.forward, but that vector seemed relative to world (still confused why).
    So I'm trying to make it relative to transform.position but its giving weird results, can't get it to move in the right direction.

    Thankyou!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Translate1M_01 : MonoBehaviour {
    5.     Vector3 startPos;
    6.     Vector3 destPos;
    7.  
    8.     void Start () {
    9.         startPos = transform.position;
    10.         destPos = transform.position;
    11.     }
    12.  
    13.     // Update is called once per frame
    14.     void Update () {
    15.         if (Input.GetKeyDown(KeyCode.W)) {
    16.             startPos = transform.position;
    17.             destPos = transform.position + transform.forward;
    18.             print("FROM:" +transform.position +" TO:" +destPos +" DISTANCE:" +Vector3.Distance(transform.position,destPos));
    19.         }
    20.         if (Input.GetKeyDown(KeyCode.S)) {
    21.             startPos = transform.position;
    22.             destPos = transform.position - transform.forward ;
    23.             print("FROM:" +transform.position +" TO:" +destPos +" DISTANCE:" +Vector3.Distance(transform.position,destPos));
    24.         }
    25.         if (Input.GetKeyDown(KeyCode.A)) {
    26.             startPos = transform.position;
    27.             destPos = transform.position - transform.right;
    28.             print("FROM:" +transform.position +" TO:" +destPos +" DISTANCE:" +Vector3.Distance(transform.position,destPos));
    29.         }
    30.         if (Input.GetKeyDown(KeyCode.D)) {
    31.             startPos = transform.position;
    32.             destPos = transform.position + transform.right ;
    33.             print("FROM:" +transform.position +" TO:" +destPos +" DISTANCE:" +Vector3.Distance(transform.position,destPos));
    34.         }
    35.         if (startPos != destPos) {
    36.             if (Vector3.Distance(transform.position,destPos) < 0.05f || Vector3.Distance(transform.position,startPos)>= 1f)
    37.             {
    38.                 transform.position = destPos;
    39.                 startPos = transform.position;
    40.                 print("FINISHED:" +transform.position);
    41.             } else {
    42.                 print("FROM:" +transform.position +" TO:" +destPos +" DISTANCE:" +Vector3.Distance(transform.position,destPos));
    43.                 transform.Translate(destPos * Time.deltaTime);
    44.             }
    45.         }
    46.     }
    47. }
    48.  
     
    Last edited: Aug 17, 2014
  8. Joxno

    Joxno

    Joined:
    Aug 20, 2013
    Posts:
    6
    It seems as though you are using transform.Translate incorrectly, the translation is done in relation to the current position, if supplied with default 2nd parameter.

    An easier way to go about it is to use a Linear interpolation.

    Code (CSharp):
    1. Stuff...
    2. ......
    3. if (Vector3.Distance(transform.position,destPos) > 0.05f)
    4. {
    5. transform.position = Vector3.Lerp(transform.position,destPos,Time.deltaTime);
    6. }
     
    Decroded likes this.
  9. Decroded

    Decroded

    Joined:
    Aug 14, 2014
    Posts:
    9
    Thanks Joxno, that effect is nice but Lerp causes it to slow down as it approaches the destination and I need it to move at a constant rate.

    Anyway I've managed to hack together following code which works perfectly for what I need.
    I hope to flesh out my understanding to do be able to do this multiple ways but time to move on for now.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Translate1M_03 : MonoBehaviour {
    5.     //Translation:
    6.     float movSpeed = 4.0f;
    7.     Vector3 pos;
    8.     Transform tr ;
    9.     bool moving = false;
    10.    
    11.     //Rotation:
    12.     bool rotating = false;
    13.     public float rotSpeed = 360f;
    14.     float rotDegrees = 0f;
    15.     Quaternion rotToAngle ;
    16.  
    17.     void Start () {  
    18.         pos = transform.position;
    19.         tr = transform;
    20.     }
    21.    
    22.     // Update is called once per frame
    23.     void Update () {
    24.         Debug.DrawRay(transform.position, transform.forward, Color.red);
    25.         //Input:
    26.         if (!moving && !rotating) {
    27.             if (Input.GetKey(KeyCode.D) && tr.position == pos) {
    28.                 //pos += Vector3.right;
    29.                 pos += transform.right;
    30.                 moving=true;
    31.                 print ("MOVE LEFT");
    32.             } else if (Input.GetKey(KeyCode.A) && tr.position == pos) {
    33.                 pos += -transform.right;
    34.                 moving=true;
    35.                 print ("MOVE RIGHT");
    36.             } else if (Input.GetKey(KeyCode.W) && tr.position == pos) {
    37.                 pos += transform.forward;
    38.                 moving=true;
    39.                 print ("MOVE FORWARD");
    40.             } else if (Input.GetKey(KeyCode.S) && tr.position == pos) {
    41.                 pos += -transform.forward;
    42.                 moving=true;
    43.                 print ("MOVE BACK");
    44.             } else if (Input.GetKey(KeyCode.Q) && tr.position == pos) {
    45.                 rotDegrees -= 90f;
    46.                 //rotToAngle = Quaternion.Euler(0, rotDegrees, 0);
    47.                 rotToAngle = Quaternion.Euler(0, rotDegrees, 0);
    48.                 rotating = true;
    49.                 print ("TURN LEFT");
    50.             } else if (Input.GetKey(KeyCode.E) && tr.position == pos) {
    51.                 rotDegrees += 90f;
    52.                 //rotToAngle = Quaternion.Euler(0, rotDegrees, 0);
    53.                 rotToAngle = Quaternion.Euler(0, rotDegrees, 0);
    54.                 rotating = true;
    55.                 print ("TURN RIGHT");
    56.             }
    57.         }
    58.  
    59.         //Translation:
    60.         if (moving) {
    61.             if (Vector3.Distance(transform.position,pos) <0.05f){
    62.                 transform.position = pos;
    63.                 moving=false;
    64.                 print ("FINISHED MOVE");
    65.             } else {
    66.                 transform.position = Vector3.MoveTowards(transform.position, pos, Time.deltaTime * movSpeed);
    67.             }
    68.         }
    69.  
    70.         //Rotation:
    71.         if (rotating) {
    72.             if (Quaternion.Angle(transform.rotation,rotToAngle) <10f) {
    73.                 transform.rotation = rotToAngle;
    74.                 rotating=false;
    75.                 print ("FINISHED TURN");
    76.             } else {
    77.                 transform.rotation = Quaternion.RotateTowards(transform.rotation, rotToAngle, rotSpeed * Time.deltaTime);
    78.             }
    79.         }
    80.     }
    81. }
     
    Last edited: Aug 18, 2014