ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유니티 움직임 구현 - 플레이어 이동 및 점프, 1인칭 시점
    Unity 2024. 1. 25. 11:06
    반응형

    안녕하세요

    오늘은 유니티 1인칭 시점 플레이어 이동 및 점프를 구현해봤습니다.


    [하이어라키]

    • PlayerModel은 캡슐 오브젝트를 사용했습니다
    • CameraPos는 PlayerModel의 머리 부분에 위치했습니다 Position (0, 0.74, 0)
    • Orientation은 Position (0, 0 ,0) 입니다.
    • CameraHolder는 Position (0, 1.5, 0) 입니다.

    [MoveCamera.cs]

    #region 변수
    [SerializeField] private Transform cameraPosition;
    #endregion // 변수
    
    #region 함수
    /** 초기화 => 상태를 갱신한다 */
    private void Update()
    {
        transform.position = cameraPosition.position;
    }
    #endregion // 함수
    • cameraPosition 변수에 MainCamera를 넣어줍니다.
    • MoveCamera.cs는 CameraHolder에 넣어줍니다.

    [PlayerCamera.cs]

    #region 변수
    [Header("=====> 감도 설정 <=====")]
    [SerializeField] private float mouseSensitivityX;
    [SerializeField] private float mouseSensitivityY;
    
    [Header("=====> 방향 <=====")]
    public Transform orientation;
    
    private float xRotation;
    private float yRotation;
    #endregion // 변수
    
    #region 함수
    /** 초기화 => 상태를 갱신한다 */
    private void Update()
    {
        // 마우스 수평/수직
        float mouseX = Input.GetAxisRaw("Mouse X") * mouseSensitivityX;
        float mouseY = Input.GetAxisRaw("Mouse Y") * mouseSensitivityY;
    
        // 마우스가 위로 올라갈 때 X가 바뀜
        yRotation += mouseX;
        xRotation -= mouseY;
    
        // 수직회전 고정
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    
        // 회전 적용
        transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);
        orientation.rotation = Quaternion.Euler(0, yRotation, 0);
    }
    #endregion // 함수
    • mouseSensitivity는 직접 테스트해보면서 조절하시면 됩니다.
    • orientation은 Player객체 하위에 있는 Orientation 객체를 넣어주면 됩니다.
    • PlayerCamera.cs는 MainCamera에 넣어줍니다.

    [PlayerMovemenet.cs]

    #region 변수
    [Header("=====> 이동 <=====")]
    [SerializeField] private float moveSpeed;
    [SerializeField] private float correctMoveSpeed;
    [SerializeField] private float baseDrag;
    [SerializeField] private Transform orientation; 
    
    [Header("=====> 점프 설정 <=====")]
    [SerializeField] private float jumpPower;
    [SerializeField] private float jumpCooldown;
    [SerializeField] private float playerHeight;
    [SerializeField] private float correctPlayerHeight;
    [SerializeField] private LayerMask groundLayer;
    
    [Header("=====> 키 입력 <=====")]
    [SerializeField] private KeyCode jumpKey = KeyCode.Space;
    
    [Header("=====> 인스펙터 값 확인 <=====")]
    [SerializeField] private float airMultiplier;
    
    private bool isJump;
    private bool isGround;
    
    private float horizontalInput;
    private float verticalInput;
    
    private Vector3 moveDirection;
    
    private Rigidbody rigid;
    #endregion // 변수
    
    #region 함수
    /** 초기화 */
    private void Awake()
    {
        rigid = GetComponent<Rigidbody>();
        rigid.freezeRotation = true;
    
        // 점프 초기화
        PlayerResetJump();
    }
    
    /** 초기화 => 상태를 갱신한다 */
    private void Update()
    {
        // 오브젝트의 높이 절반 + 보정값
        isGround = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + correctPlayerHeight, groundLayer);
    
        // 플레이어 입력처리
        PlayerInput();
        // 플레이어 속도제어
        PlayerSpeedControl();
        // 저항 값 제어
        DragAirControl();
    }
    
    /** 초기화 => 상태를 갱신한다 */
    private void FixedUpdate()
    {
        // 플레이어 이동
        PlayerMove();
    }
    
    /** 입력처리 */
    private void PlayerInput()
    {
        // 움직임
        horizontalInput = Input.GetAxisRaw("Horizontal");
        verticalInput = Input.GetAxisRaw("Vertical");
        
        // 점프
        if(Input.GetKey(jumpKey) && isJump && isGround)
        {
            isJump = false;
    
            // 점프
            PlayerJump();
    
            // 점프 쿨타임
            Invoke(nameof(PlayerResetJump), jumpCooldown);
        }
    }
    
    /** 플레이어 이동 */
    private void PlayerMove()
    {
        // 이동방향 계산
        moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
    
        // 이동
        rigid.AddForce(moveDirection.normalized * moveSpeed * correctMoveSpeed * airMultiplier, ForceMode.Force);
    }
    
    /** 플레이어 속도제어 */
    private void PlayerSpeedControl()
    {
        // 속도
        Vector3 currentVelocity = new Vector3(rigid.velocity.x, 0f, rigid.velocity.z);
    
        // 현재 속도가 이동속도보다 클 경우
        if(currentVelocity.magnitude > moveSpeed)
        {
            // 같은 방향 moveSpeed로 크기 제한
            Vector3 limitVelocity = currentVelocity.normalized * moveSpeed;
            rigid.velocity = new Vector3(limitVelocity.x, rigid.velocity.y, limitVelocity.z);
        }
    }
    
    /** 플레이어 점프 */
    private void PlayerJump()
    {
        rigid.velocity = new Vector3(rigid.velocity.x, 0f, rigid.velocity.z);
    
        rigid.AddForce(transform.up * jumpPower, ForceMode.Impulse);
    }
    
    /** 점프 초기화 */
    private void PlayerResetJump()
    {
        isJump = true;
    }
    
    /** 저항 값 제어 */
    private void DragAirControl()
    {
        // 공기저항
        rigid.drag = isGround ? baseDrag : 1;
    
        // 점프했을때 안했을때 움직이는 속도 조정
        airMultiplier = isGround ? 1 : (1 / (baseDrag + 1));
    }
    #endregion  // 함수
    • playerHeight는 오브젝의 높이를 구하여 설정해주시면 됩니다. 캡슐 오브젝트의 높이는 2 입니다.
    • correct 변수는 보정값입니다.
    • PlayerMovement.cs는 Player에 넣어줍니다.

    [인스펙터]

     

    [추가 설정]

    • Layer에 Ground를 추가하시고 바닥이 되는 객체의 Layer를 Ground로 바꿔 주시면 됩니다.
    반응형
Designed by Tistory.