Search Unity

Move Relative to Camera but Rotate towards Move Direction

Discussion in 'Scripting' started by dragonice501, Feb 13, 2016.

  1. dragonice501

    dragonice501

    Joined:
    Dec 2, 2015
    Posts:
    146
    I'm having a hard time figuring or finding this out. I want my character to move on the ground relative to the camera but still rotate in the direction they're moving. Like in the 3D Legend of Zelda games.

    So far my system just has the character stay aligned to with the camera, always facing forward but able to move relative towards it. How can i keep that control while still being able to rotate them?

    This code is from the main script that calls to the others that process the input, like the brain calling out to the limbs.

    TP_ stands for Third Person

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TP_Controller : MonoBehaviour {
    5.  
    6.     public static CharacterController CharacterController;
    7.     public static TP_Controller Instance;
    8.  
    9.     void Awake ()
    10.     {
    11.         CharacterController = GetComponent<CharacterController>() as CharacterController;
    12.         Instance = this;
    13.         TP_Camera.UseExistingOrCreateNewMainCamera ();
    14.     }
    15.  
    16.     void Update ()
    17.     {
    18.         if (Camera.main == null)
    19.             return;
    20.      
    21.         GetLocomotionInput ();
    22.         HandleActionInput ();
    23.  
    24.         TP_Motor.Instance.UpdateMotor ();
    25.     }
    26.  
    27.     void GetLocomotionInput()
    28.     {
    29.         var deadZone = 0.1f;
    30.  
    31.         TP_Motor.Instance.VerticalVelocity = TP_Motor.Instance.MoveVector.y;
    32.         TP_Motor.Instance.MoveVector = Vector3.zero;
    33.  
    34.         if (Input.GetAxis ("Vertical") > deadZone || Input.GetAxis ("Vertical") < -deadZone)
    35.             TP_Motor.Instance.MoveVector += new Vector3 (0, 0, Input.GetAxis ("Vertical"));
    36.  
    37.         if (Input.GetAxis ("Horizontal") > deadZone || Input.GetAxis ("Horizontal") < -deadZone)
    38.             TP_Motor.Instance.MoveVector += new Vector3 (Input.GetAxis("Horizontal"), 0 ,0);
    39.  
    40.         TP_Animator.Instance.DetermineCurrentMoveDirection ();
    41.     }
    42.  
    This is the code that actually moves the player, the TP_Motor script. SnapAlignWithCamera () and ProcessMotion () are the only functions you need to see it think.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TP_Motor : MonoBehaviour {
    5.  
    6.     public static TP_Motor Instance;
    7.  
    8.     public bool Locked = false;
    9.  
    10.     public float ForwardSpeed = 10;
    11.     public float BackwardSpeed = 2;
    12.     public float StrafingSpeed = 5;
    13.  
    14.     public float SlideSpeed = 10;
    15.  
    16.     public float Gravity = 21;
    17.     public float TerminalVelocity = 20;
    18.     public float JumpSpeed = 6;
    19.  
    20.     public float SlideThreshold = 0.6f;
    21.     public float MaxControllableSlideMagnitude = 0.4f;
    22.  
    23.     private Vector3 slideDirection;
    24.  
    25.     public float VerticalVelocity { get; set; }
    26.     public Vector3 MoveVector { get; set; }
    27.  
    28.     // Use this for initialization
    29.     void Awake ()
    30.     {
    31.         Instance = this;
    32.     }
    33.  
    34.     void Start()
    35.     {
    36.         Locked = false;
    37.     }
    38.  
    39.     // Update is called once per frame
    40.     public void UpdateMotor ()
    41.     {
    42.         if (Locked)
    43.         {
    44.             AlignCharacterWithEnemy ();
    45.         }
    46.         else
    47.         {
    48.             SnapAlignWithCamera ();
    49.         }
    50.  
    51.         ProcessMotion ();
    52.     }
    53.  
    54. void SnapAlignWithCamera()
    55.     {
    56.         if (MoveVector.x != 0 || MoveVector.z != 0)
    57.         {
    58.             transform.rotation = Quaternion.Euler (transform.eulerAngles.x, Camera.main.transform.eulerAngles.y, transform.eulerAngles.z);
    59.         }
    60.     }
    61.  
    62.     void ProcessMotion()
    63.     {
    64.         //Transform MoveVector into World Space
    65.         MoveVector = transform.TransformDirection(MoveVector);
    66.  
    67.         //Normalize MoveVector if Magnitude > 1
    68.         if (MoveVector.magnitude > 1)
    69.             MoveVector = Vector3.Normalize (MoveVector);
    70.  
    71.         //Apply sliding if applicaple
    72.         ApplySlide();
    73.  
    74.         //Multiply MoveVector by Movespeed
    75.         MoveVector *= MoveSpeed();
    76.  
    77.         //Reapply Vertical Velocity to MoveVector.y
    78.         MoveVector = new Vector3 (MoveVector.x, VerticalVelocity, MoveVector.z);
    79.  
    80.         //Apply Gravity
    81.         ApplyGravity();
    82.  
    83.         //Move the Character in World Space
    84.         TP_Controller.CharacterController.Move(MoveVector * Time.deltaTime);
    85.     }
    86.  
    87.     void ApplyGravity()
    88.     {
    89.         if (MoveVector.y > -TerminalVelocity)
    90.             MoveVector = new Vector3 (MoveVector.x, MoveVector.y - Gravity * Time.deltaTime, MoveVector.z);
    91.  
    92.         if (TP_Controller.CharacterController.isGrounded && MoveVector.y < -1)
    93.             MoveVector = new Vector3 (MoveVector.x, -1, MoveVector.z);
    94.      
    95.     }
    96.  
    97.     void ApplySlide()
    98.     {
    99.         if (!TP_Controller.CharacterController.isGrounded)
    100.             return;
    101.  
    102.         slideDirection = Vector3.zero;
    103.  
    104.         RaycastHit hitInfo;
    105.  
    106.         if (Physics.Raycast (transform.position + Vector3.up, Vector3.down, out hitInfo))
    107.         {
    108.             if (hitInfo.normal.y < SlideThreshold)
    109.                 slideDirection = new Vector3 (hitInfo.normal.x, -hitInfo.normal.y, hitInfo.normal.z);
    110.         }
    111.  
    112.         if (slideDirection.magnitude < MaxControllableSlideMagnitude)
    113.             MoveVector += slideDirection;
    114.         else
    115.         {
    116.             MoveVector = slideDirection;
    117.         }
    118.     }
    119. }
     
  2. frilanski

    frilanski

    Joined:
    Oct 19, 2013
    Posts:
    11
    Personally have no idea how to tackle this but i would perhaps use a separate approach to moving the character and move an empty around him. then you can use the "Look at" function to rotate your player towards this empty. Then check to see if the empty is getting too far away and move your player towards it at = speed if it is.

    Sorry that I don't have an actual solution to your problem but just wanted to chip in Good Luck;)