유니티

3D 1인칭 이동 구현 (Input System)

잼잼재미 2023. 12. 14. 00:38

 

 

 

  • W/S/A/D 이동 구현
  • 마우스 카메라 회전 구현
  • Space 1단 점프 구현

 

 

준비


1. Player


Player 빈 오브젝트를 생성하고, 자식 오브젝트로 CameraContainer를 생성

 

 

CameraContainer 안에 Main Camera를 넣음

 

 

Main Camera 설정

 

 

Player 오브젝트에 Capsule Collider, Rigidbody 추가

 

 

2. Input System


 

* 앞 부분은 Input System(2D)와 동일 *

 

https://kkln2486.tistory.com/126

 

2D 이동 (position, velocity, Input System)

position 오브젝트의 position 값을 변경해서 이동 GetAxis -1 ~ 1 까지의 숫자를 입력으로 불러옴 void Update() { float x = Input.GetAxis("Horizontal"); float y = Input.GetAxis("Vertical"); transform.position += new Vector3(x, y, 0) *

kkln2486.tistory.com

 

 

다음과 같이 Action 설정

 

 

3D는 Invoke Unity Events 사용

 

 

  • Send Messages : OnMove와 OnLook 함수를 현재 오브젝트에 있는 스크립트에서 찾음
  • Broadcast Messages : OnMove와 OnLook 함수를 현재, 자식 오브젝트에 있는 스크립트에서 찾음
  • Invoke Unity Events : Button과 같이 함수가 있는 스크립트를 가진 오브젝트를 추가해서 사용

 

3. 스크립트 작성


PlayerController

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

public class PlayerController : MonoBehaviour
{
    [Header("Movement")]
    public float MoveSpeed;
    public float JumpForce;
    public LayerMask GroundLayerMask;
    private Vector2 _curMovementInput;

    [Header("Look")]
    public Transform CameraContainer;
    public float MinXLook;
    public float MaxXLook;
    public float LookSensitivity;
    private float _camCurXRot;
    private Vector2 _mouseDelta;

    [HideInInspector] public bool CanLook = true;

    private Rigidbody _rigidbody;

    private void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
    }


    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;	// 게임 시, 마우스 없앰
    }

    private void FixedUpdate()
    {
        Move();
    }

    private void LateUpdate()
    {
        if (CanLook)
        {
            CameraLook();
        }
    }

    // 이동
    public void OnMoveInput(InputAction.CallbackContext context)
    {
        if (context.phase == InputActionPhase.Performed)
        {
            _curMovementInput = context.ReadValue<Vector2>();
        }
        else if (context.phase == InputActionPhase.Canceled)
        {
            _curMovementInput = Vector2.zero;
        }
    }

    private void Move()
    {
        Vector3 dir = transform.forward * _curMovementInput.y + transform.right * _curMovementInput.x;
        dir *= MoveSpeed;
        dir.y = _rigidbody.velocity.y;

        _rigidbody.velocity = dir;

    }

    // 카메라 조절
    public void OnLookInput(InputAction.CallbackContext context)
    {
        _mouseDelta = context.ReadValue<Vector2>();
    }

    void CameraLook()
    {
        _camCurXRot += _mouseDelta.y * LookSensitivity;
        _camCurXRot = Mathf.Clamp(_camCurXRot, MinXLook, MaxXLook);
        CameraContainer.localEulerAngles = new Vector3(-_camCurXRot, 0, 0);

        transform.eulerAngles += new Vector3(0, _mouseDelta.x * LookSensitivity, 0);
    }

    // 점프
    public void OnJumpInput(InputAction.CallbackContext context)
    {
        if (context.phase == InputActionPhase.Started)
        {
            if (IsGrounded())
                _rigidbody.AddForce(Vector2.up * JumpForce, ForceMode.Impulse);
        }
    }

    private bool IsGrounded()
    {
        Ray[] rays = new Ray[4]
        {
            new Ray(transform.position + (transform.forward * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
            new Ray(transform.position + (-transform.forward * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
            new Ray(transform.position + (transform.right * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
            new Ray(transform.position + (-transform.right * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
        };

        for (int i = 0; i < rays.Length; i++)
        {
            if (Physics.Raycast(rays[i], 0.1f, GroundLayerMask))
            {
                return true;
            }
        }

        return false;
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawRay(transform.position + (transform.forward * 0.2f), Vector3.down);
        Gizmos.DrawRay(transform.position + (-transform.forward * 0.2f), Vector3.down);
        Gizmos.DrawRay(transform.position + (transform.right * 0.2f), Vector3.down);
        Gizmos.DrawRay(transform.position + (-transform.right * 0.2f), Vector3.down);
    }
}

 

 

4. 기타 설정


Player 오브젝트에 스크립트, Player Input 추가하고 다음과 같이 설정

 

 

Player를 누르고 Button 설정과 유사하게 함수를 등록

'유니티' 카테고리의 다른 글

아이템 정보 만들기 (ScriptableObject)  (0) 2023.12.14
인벤토리 스크롤 설정 (Scroll View, Grid Layout Group)  (0) 2023.12.14
Rect Transform (앵커, 피봇)  (0) 2023.12.13
애니메이션 이벤트  (0) 2023.12.13
GameObject 검색  (0) 2023.12.11