Search Unity

Moving character relative to Camera

Discussion in 'Editor & General Support' started by kk99, Jan 31, 2016.

  1. kk99

    kk99

    Joined:
    Nov 5, 2013
    Posts:
    77
    Hi Guys,

    I need little help since I am not making any progress here.
    I am using the Unity Third Person Character Controller presets which is working perfectly for Root Motion Animations.

    In case my animation dont have root Motion I need to add the movement with my script.
    I made this working already for going Forward and Backward relative to the Camera. The camera can be moved freely up and down and rotate around the character.

    What I need is now how to add going RIGHT and LEFT relative to the camera.
    I am not getting it done. Doing Vector3.right or Vector3.left is not working hmmm

    // Fixed update is called in sync with physics
    private void FixedUpdate()
    {
    // read inputs
    float h = CrossPlatformInputManager.GetAxis("Horizontal");
    float v = CrossPlatformInputManager.GetAxis("Vertical");

    if (v > 0)
    {
    transform.Translate(Vector3.forward * v * 1 * speedMeUp * Time.deltaTime);
    }

    if (v < 0)
    {
    transform.Translate(Vector3.back * v * 1 * speedMeUp * Time.deltaTime);
    }

    }


    Oh boy I dont think this is so difficult, but I guess I simply doing it wrong.
    thanks for any help :)
     
  2. AndreiKubyshkin

    AndreiKubyshkin

    Joined:
    Nov 14, 2013
    Posts:
    198
    Ok, this is simple. But not as simple as you're doing it:)

    Vector3.forward is just a constant vector (0f,0f,1f), it is not relative to camera in any way.

    To make your movement relative to the camera you actually need to get the camera transform.

    Code (csharp):
    1.  
    2. void FixedUpdate()
    3. {
    4.         //reading the input:
    5.         float horizontalAxis = CrossPlatformInputManager.GetAxis("Horizontal");
    6.         float verticalAxis = CrossPlatformInputManager.GetAxis("Vertical");
    7.          
    8.         //assuming we only using the single camera:
    9.         var camera = Camera.main;
    10.  
    11.         //camera forward and right vectors:
    12.         var forward = camera.transform.forward;
    13.         var right = camera.transform.right;
    14.  
    15.         //project forward and right vectors on the horizontal plane (y = 0)
    16.         forward.y = 0f;
    17.         right.y = 0f;
    18.         forward.Normalize();
    19.         right.Normalize();
    20.  
    21.         //this is the direction in the world space we want to move:
    22.         var desiredMoveDirection = forward * verticalAxis + right * horizontalAxis;
    23.  
    24.         //now we can apply the movement:
    25.         transform.Translate(desiredMoveDirection * speedMeUp * Time.deltaTime);
    26. }
    27.  
     
    Last edited: Jan 31, 2016
  3. someguywithamouse

    someguywithamouse

    Joined:
    Mar 25, 2018
    Posts:
    9
    I tried, and your code is a bit flawed. It does solve the issue though, but because of the way it was put together it doesnt move towards where (exactly) the camera faces, but rather just relative to the world with the up/down/left/right direction changing depending on an estimate of where the camera is facing. This doesn't make for very accurate control and also to make matters worse it will very easily jump from one direction to another even if you just get a centimeter close to facing left of where you *actually* are facing...

    EDIT: Solved, it wasn't the code causing the issue. It was mostly my setup. Fixed as shown later.
     
    Last edited: Jul 9, 2018
  4. AndreiKubyshkin

    AndreiKubyshkin

    Joined:
    Nov 14, 2013
    Posts:
    198
    I'm sorry you have issues with this tiny piece of code. I only showed the concept and didn't claim you can just simply copy paste and it will work in all cases.

    It works, however. It's just too simple not to work. If you have some "inaccurate" controls, the problem is somewhere else. My guess it's in your InputManager. Check gravity and sensitivity values of Horizontal and Vertical axis.

    Also I'd move the translation from FixedUpdate to usual Update. There's nothing happening there about physics, so there's no need for FixedUpdate.

    P.S. The video isn't helpful
     
  5. AndreiKubyshkin

    AndreiKubyshkin

    Joined:
    Nov 14, 2013
    Posts:
    198
    Oh.. lol. It has nothing to do with InputManager. Obviously the problem is your camera is the child of the player.

    The player tries to move relatevely to camera, but the camera rotates with him. Rethink your player/camera setup.
     
  6. someguywithamouse

    someguywithamouse

    Joined:
    Mar 25, 2018
    Posts:
    9
    [Edited June 28th]
    And also I tried your code again and it seems to behave fine now, except I am still having the same issues with my modified code where the movement direction is incorrect. I am currently fixing that but it's nice to see your code working a bit more like it was expected. The directions aren't solely 4-way or inaccurate in the same way they were before, so clearly what you're doing is working. I just need to figure out how to reverse the incorrect movement directions in my case (which after I've tweaked some settings should be pretty easy).

    Thanks for pointing that out though, I'm starting to get somewhere.
     
    Last edited: Jun 28, 2018
    AndreiKubyshkin likes this.
  7. someguywithamouse

    someguywithamouse

    Joined:
    Mar 25, 2018
    Posts:
    9
    Hello! I've spent a little bit of time improving upon AndreiKubyshkin's code and managed to create a script of my own, and it is working perfectly.

    Also thanks to him for pointing out that I made a mistake with the camera.



    My new code:
    Code (CSharp):
    1. void FixedUpdate(){
    2.             //assuming we're only using the single camera:
    3.                 var camera = Camera.main;
    4.            
    5.                 //Data recieved from CrossPlatformInput Handler:
    6.                   float horizontalAxis = CrossPlatformInputManager.GetAxis("Horizontal");
    7.                   float verticalAxis = CrossPlatformInputManager.GetAxis("Vertical");
    8.                
    9.             float facing = camera.transform.rotation.y;
    10.             float DistanceFromNeutral = 0;
    11.             float transformZ = 0;
    12.             float transformX = 0;
    13.             float finalZ = 0;
    14.             float finalX = 0;
    15.            
    16.             if (facing > -90 && facing <= 90){ //facing forward
    17.                 if(facing >= 0){
    18.                     DistanceFromNeutral = (90 - facing);
    19.                 }else{
    20.                     if(facing < 0){
    21.                         DistanceFromNeutral = (90 + facing);
    22.                     };
    23.                 };
    24.                
    25.                
    26.                 transformX = (1 / 90) * (DistanceFromNeutral);
    27.                 transformZ = 90 - transformX;
    28.             };
    29.            
    30.             //for monitoring and debugging:
    31.             Debug.Log("Main Camera's <color=red>Y rotation</color> is <color=red>" + facing + "</color>, and the <color=blue>Distance from Neutral rotation</color> <color=purple>(0/90/180/270)</color> is <color=blue>" + DistanceFromNeutral + "</color>.");
    32.            
    33.             // continue
    34.            
    35.             finalX = (transformX * verticalAxis) + (transformZ * horizontalAxis);
    36.            
    37.             //if(finalX > 1){
    38.             //    finalX = 1;
    39.             //    };
    40.             // ^^^^ dont use, causes vector3 slowdowns or something ^^^^
    41.            
    42.             finalZ = (transformZ * verticalAxis) + (transformX * horizontalAxis);
    43.            
    44.             //if(finalZ > 1){
    45.             //    finalZ = 1;
    46.             //    };
    47.             // ^^^^ dont use, causes vector3 slowdowns or something ^^^^
    48.            
    49.             transform.Translate((new Vector3( finalX * 0.01f , 0f , finalZ * 0.01f ))* moveSpeed * Time.deltaTime);
    50. }
     
  8. Okaymymy

    Okaymymy

    Joined:
    Dec 18, 2018
    Posts:
    1
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class PlayerMovement : MonoBehaviour
    {
    public float playerSpeed;
    public Transform cam;
    Quaternion rotation;
    Vector3 movementSpeed, rot;
    float fwd, side, camY;
    void Start()
    {

    }

    void FixedUpdate()
    {
    CalculatePlayerSpeed();
    Move();
    camY = cam.eulerAngles.y;
    rot = new Vector3(0, camY, 0);
    rotation = Quaternion.Euler(rot);
    transform.rotation = Quaternion.RotateTowards(transform.rotation, rotation, 180);
    }

    void LateUpdate()
    {
    movementSpeed = new Vector3(side*playerSpeed, 0, fwd*playerSpeed);
    }

    void CalculatePlayerSpeed()
    {
    side = Input.GetAxis("HorizontalK")+Input.GetAxis("HorizontalJ");
    fwd = Input.GetAxis("VerticalK")+Input.GetAxis("VerticalJ");
    }

    void Move()
    {

    transform.position += transform.TransformDirection(movementSpeed);
    }
    }


    //this is how i solved it. just used transform.TransformDirection to make the forward direction of my player local instead of world
     
  9. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    4,509
    Thank you for sharing, could you please put your code in code tags? After hitting the edit link at the bottom of your post you can find the appropriate button in the toolbar. Thanks!
     
  10. ErwinJB

    ErwinJB

    Joined:
    Mar 21, 2015
    Posts:
    3
    I put my own solution.
    This work with capsule collider, rigidbody and animator controller:
    Code (CSharp):
    1.  
    2.     private float speed = 100f;
    3.     private float walkSpeed = 0.5f;
    4.     private float runSpeed = 1f;
    5.    
    6.    
    7.     private float gravity = 8;
    8.  
    9.     private Rigidbody body;
    10.     private Animator anim;
    11.  
    12.     private Vector3 direction;
    13.     float percent;
    14.  
    15.     private void Awake()
    16.     {
    17.         body = GetComponent<Rigidbody>();
    18.         anim = GetComponent<Animator>();
    19.     }
    20.  
    21.     private void FixedUpdate()
    22.     {
    23.  
    24.  
    25.  
    26.         Move();
    27.  
    28.         if (direction != Vector3.zero)
    29.         {
    30.            HandleRotation();
    31.         }
    32.  
    33.         HandleAnimations();
    34.     }
    35.  
    36.     public void Move()
    37.     {
    38.         float h = Input.GetAxisRaw("Horizontal");
    39.         float v = Input.GetAxisRaw("Vertical");
    40.  
    41.         direction = new Vector3(h, 0, v);
    42.  
    43.         direction = direction.normalized;
    44.      
    45.         if (Input.GetButton("Fire1"))
    46.         {
    47.             percent = runSpeed * direction.magnitude;
    48.             speed = 200f;
    49.         }
    50.         else
    51.         {
    52.             percent = walkSpeed * direction.magnitude;
    53.             speed = 100f;
    54.         }
    55.  
    56.         //CONVERT direction from local to world relative to camera
    57.         body.velocity = Camera.main.transform.TransformDirection(direction) * speed * Time.deltaTime;
    58.     }
    59.  
    60.     public void HandleRotation()
    61.     {
    62.         float targetRotation = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + Camera.main.transform.eulerAngles.y;
    63.         Quaternion lookAt = Quaternion.Slerp(transform.rotation,
    64.                                       Quaternion.Euler(0,targetRotation,0),
    65.                                       0.5f);
    66.         body.rotation = lookAt;
    67.  
    68.     }
    69.  
    70.  
    71.     public void HandleAnimations()
    72.     {
    73.         anim.SetFloat("speed", percent, 0.1f,Time.deltaTime);
    74.     }
    75.  
     
    BlackDragonBE likes this.
  11. alex98_

    alex98_

    Joined:
    Jan 30, 2019
    Posts:
    1
    While the rotation looks great...the movement gets the Camera Y so if you look up it turns your character into a space ship.Also it seems to ignore other AddForce usage (adding extra gravity downwards for example)

     
  12. chaseholton

    chaseholton

    Joined:
    Dec 17, 2012
    Posts:
    55
    Yeah this script is so close to being perfect, but the flying player issue is a problem. I can't seem to find a way to stop it from happening haha. Any luck?