Home > Software engineering >  Camera relative moment
Camera relative moment

Time:12-24

I'm new to Unity 3D and I've started to study and learn player and camera mechanics these past few weeks.Although, I have a simple character controller system with a Cinemachine free look cam following the player, I need help incorporating a camera relative player movement mechanic into my project. I therefore need help incorporating such a mechanism into my system. I've added my PlayerController Code below

`

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] public float _playerSpeed;
    [SerializeField] public Rigidbody rb;

    [SerializeField] private float _jumpforce = 100 ;
    [SerializeField] private float fallMultiplier;
    [SerializeField] private float lowJumpMultiplier;
    public bool isGrounded;

    public bool jumpReady;
    public float jumpcoolDownTimer = 1.5f;
    public float jumpcoolDownCurrent = 0.0f;

    [SerializeField] private float sensi;
    private float rotX;
    private float rotY;
    private Vector3 rotate;

    
    int isJumpingHash;
    int isFallingHash; 
    int isLandingHash;

    public Animator animator;
    Vector3 vel;

    // Start is called before the first frame update
    void Start()
    {
        jumpcoolDownCurrent = jumpcoolDownTimer;

        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;

        animator = GetComponent<Animator>();

        //Converting string values to hash values to save memory
        isJumpingHash = Animator.StringToHash("isJumping");
        isFallingHash = Animator.StringToHash("isFalling");
        isLandingHash = Animator.StringToHash("isGrounded");

        var cam = Camera.main;
    }

    // Update is called once per frame
    void Update()
    {
        Move();
        Jump();
    }


    private void OnCollisionEnter(Collision collision){
        if(collision.gameObject.tag == "Surface"){
            isGrounded = true;
        }
    }

    private void Move()
    {
        vel = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")) * _playerSpeed;

        if(Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.W)){
            transform.position  = transform.forward * Time.deltaTime * _playerSpeed;
        }
    }

    private void Jump(){
        vel.y = rb.velocity.y;
        rb.velocity = vel;

        //Jump Cooldown timer
        if(jumpcoolDownCurrent >= jumpcoolDownTimer){
            jumpReady = true;
        }
        else{
            jumpcoolDownCurrent  = Time.deltaTime;
            jumpReady = false;
        }
        bool jump = animator.GetBool(isJumpingHash);
        bool fall = animator.GetBool(isFallingHash);
        bool land = animator.GetBool(isLandingHash);

        //Jump
         if(Input.GetKeyDown(KeyCode.Space) && isGrounded && jumpReady){
            rb.AddForce(Vector3.up * _jumpforce, ForceMode.Impulse);
            isGrounded = false;
            jumpcoolDownCurrent = 0.0f;
            animator.SetBool(isJumpingHash, true);
            jump = true;
        }
        //Fall
        if((rb.velocity.y <= 0 && !isGrounded)){
            rb.velocity  = Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
            animator.SetBool(isFallingHash, true);
            fall = true;
        }
        //Land
        if(isGrounded && fall){
            fall = false;
            animator.SetBool(isFallingHash, false);
            animator.SetBool(isLandingHash, true);

        }
        //Back to 2d movement
        if(isGrounded && rb.velocity.y <= 0){
            animator.SetBool(isLandingHash, false);
            land = false;
            animator.SetBool(isJumpingHash, false);
            jump = false;
            animator.SetBool(isFallingHash, false);
            fall = false;
        }
    }
}

`

I've referred to several different Youtube tutorials and and also surfed different forums to find a solution, but to no avail. But I did notice that all these users were using the Quaternion Rotation mechanics and cam transforms. Upon attempting to incorporate these codes into my project, the camera continuously rotates as I try to rotate the camera in one particular direction, or the A and D (strafe left and right) animations weren't fucntioning properly. I'd appreciate any sort of help, thanks.

P.S -> For those of you who don't know, camera relative moment is the mechanic that most third person games use now, where the player while in movement, turns along the rotation and the camera and runs in the direction the camera is facing. Good examples of that would be God of War (2018), Batman Arkham Series etc.

CodePudding user response:

I highly recommend that you don't use CineMachine, I have never seen anyone able to use it successfully and it is very simple to make your own camera controller after you study for a few days (or pay for someone to make one for you).

To make Camera Relative Movement in a platformer game similar to God of War, you should look into transform.Rotation, EulerAngles and Quaternions (Penny De Byl has good online classes and books on dealing with Quaternions, they're Vector4 and very difficult to wrap your head around) Then, throughout your game, add a bunch of walls with a trigger collider attached that rotate the camera to 1 angle or another when the player crosses them.

You might even want to make the camera a child of the player object then it will always have the perfect angle and move when the player rotates.

If you ask a more specific question later, then a more specific answer can be given.

CodePudding user response:

Using Camera.main.transform.forward you can get the forward direction relative to the camera. You can use Camera.main.transform.right to get the right direction. If you set the y coordinate of these to zero, you can use these to define the direction you travel in. You would then need to normalize it, and multiply it by your input.

So, here is what I would do:

  • get forward direction for camera
  • scale it so that the vertical component is zero
  • normalize it so that you get a normalized directional vector
  • multiply by your vertical movement to get your vector for movement forward and back
  • do the same for right and left movement
  • add the 2 parts together
  • multiply by speed to get your velocity

Like this:

vel = (Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized * Input.GetAxis("Vertical"))
  (Vector3.Scale(Camera.main.transform.right, new Vector3(1, 0, 1)).normalized * Input.GetAxis("Horizontal")))
* playerSpeed;

Also, while it is not relevant to your issue at the moment, it is best to normalize your input vector. So do something like: Vector3 inputDirection = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0f).normalized. Otherwise, diagonal movement ends up being much faster than movement in one direction.

  • Related