Q. Unity2D랑 Unity3D랑 나눌 정도로 InpuySystem이 많이 바껴?

A.우선 Vector2 -> Vector3로 바뀌는 정도가 있긴하지만

이동은 x축과 z축으로 이동하기에 비슷하게 동작한다.

 

내 개인 얘기가 들어가기에 이 질문을 적었다.

나는 보통 3D 프로젝트 개발로 캐릭터 이동 구현을 할때 InputManager와 비슷하게 구성을 했다.

InpuiManager의 이동을 Vertical과 Horizantal로 처리하는것을 InputSystem에서 비슷하게 구현

InputActionMap에서도 Type을 value - Axis로 해서 축 데이터를 받아 사용을 했었다.

 

하지만 오늘 Unity3D 강의를 듣는 중 튜터님의 방식이 직관성도 좋고 쉬워보여서 이 방법을 적기 위해 적었다.

Value 값으로 Vector2 값을 받음

 

PlayerInput 동작 방식을 InvokeUnityEvents로 구현하였음

 

위의 방식으로 PlayerInput컴포넌트를 이용해서 이동을 제어하게 구현 하였다.

 

   private Vector2 curMovementInput;
 
 public void OnMove(InputAction.CallbackContext context)
 {
     //InputActionPhase : 해당 키의 입력 상태를 나타낸 열거형 변수
     
     //키가 눌리고 있을때 해당 Input값을 Vector2로 변환하여 반환하고 있다.
     if (context.phase == InputActionPhase.Performed)
     {
         curMovementInput = context.ReadValue<Vector2>();
     }
      //키를 손에서 땟을때 해당 Input값을 (0,0) 으로 초기화 하고있다.
     else if (context.phase == InputActionPhase.Canceled)
     {
         curMovementInput = Vector2.zero;
     }
 }

 

OnMove 함수에서 주의 깊게 볼건 InputActionPhase 라는 enum형 변수이다.

원문을 가져오려헀으나 원문 주석이 꽤 길다.

보통 나는 해당 키 상태를 하나하나 메서드로 나눠서 event 형태로 사용했었다.(그 방법밖에 몰랐기 때문에)

 

p.s Event 형태로 사용하는 InputSystem 예제

더보기
using UnityEngine;
using UnityEngine.InputSystem;

public class ActionMapSwitcher : MonoBehaviour
{
    // InputActionAsset은 Unity의 Input Actions Asset 파일을 연결할 때 사용됩니다.
    public InputActionAsset inputActions;

    // Action Maps
    private InputActionMap playerActionMap;

    private void Awake()
    {
        // InputActionAsset에서 각 Action Map을 가져옴
        playerActionMap = inputActions.FindActionMap("Player");

        // Player Action Map에서 'Move' 액션을 가져와 이벤트 등록
        InputAction moveAction = playerActionMap.FindAction("Move");
        moveAction.started += OnMoveStarted;
        moveAction.performed += OnMovePerformed;
        moveAction.canceled += OnMoveCanceled;
    }

    private void OnEnable()
    {
        // 기본적으로 Player Action Map 활성화
        playerActionMap.Enable();
    }

    private void OnDisable()
    {
        // 비활성화 시 모든 액션맵을 비활성화
        playerActionMap.Disable();
    }

    // 'Move' 액션 관련 콜백 함수들
    private void OnMoveStarted(InputAction.CallbackContext context)
    {
        Debug.Log("Move started");
    }

    private void OnMovePerformed(InputAction.CallbackContext context)
    {
        Vector2 moveInput = context.ReadValue<Vector2>();
        Debug.Log($"Move performed: {moveInput}");
    }

    private void OnMoveCanceled(InputAction.CallbackContext context)
    {
        Debug.Log("Move canceled");
    }

}

 

사실 해당 코드는 비활성화 되거나 파괴될때 event에 등록된 메서드들을 제외해야되는데

해당 코드가 없어 좋지 않은 코드다.

하지만 프로젝트 규모가 크지 않거나 간단한거면  InputActionPhase 를 이용하면 훨씬 가독성이 좋다는것을 느꼇기에 글을 적어보았다.

 


카메라 회전 

나는 오브젝트를 따라다니는 카메라를 만들거나 쳐다보는 카메라를 만들때 Cinemachine을 자주 사용한다. 

하지만 시네머신을 활용하지 않고 직접 구현을 해봄으로 유니티엔진의 좌표계를 이해하려고 한다.

 

유니티는 왼손 좌표계를 사용한다,

Unity3D에서는 왼손 좌표계를 사용한다.

D3D(DirectX3D)에서 사용되는 좌표계라고 생각하면된다. OpneGL은 오른손 좌표계를 사용한다.

왼손의 엄지가 축방향이라고 가정할때 말아쥔 손가락이 회전방향(Inspector에 양수를 적용시키면 적용되는 회전방향)을 의미한다. 

 

Q.그럼 이 좌표계가 무슨 의미가 있어?

A. 오브젝트의 이동에따라 카메라가 회전할때 이 축방향을 정보로 회전하기 때문이다. 

 

캐릭터의 시야가 좌우로 이동시 카메라는 Y축 회전을 해야되고

캐릭터의 시야가 위아래로 이동시 카메라는 X축 회전을 해야된다.

 

우선 마우스에 의해 캐릭터의 회전(시야)를 조절하기 위해 InputAction을 통해 키 바인딩을 한다.

Mouse의 Delta값을 이용

Delta값은 컴퓨터의 성능에 따라 동작이 다르게 보이는것을 방지하기 위해 Time.deltaTime 사용했을때 봤을것이다.

즉 , Mouse의 Delta는 두 프레임 사이에 마우스가 이동한 < 변화량 >으로 이해하면된다. 

변화량이라고 어필하는 이유는 가끔 이것을 좌표값이나 위치의 데이터 값으로 이해 할 수도 있어서 그렇다.

 

그럼 이 Input값을 통해서 우리는 마우스가 이동한 변화량을 반환 받아 카메라 회전에 사용 할 수 있다.

 

    [Header("Look")] //카메라 회전 관련 필드
    public Transform cameraContainer; //플레이어 자식 오브젝트의 메인카메라를 저장할 변수
    public float minXLook; //x의 회전범위 최솟값
    public float maxXLook; //x의 회전범위 최대값
    private float camCurXRot; //현재 카메라의 X축 각도 
    public float lookSensitivy; //카메라 민감도 
    private Vector2 mouseDelta;//마우스 델타값을 저장할 변수

  void CameraLook()
  {
      //위 아래 카메라 회전
      //mouseDelta : 두 프레임 사이의 마우스가 이동한 <변화량>을 Vector2로 반환받음
      //카메라 위,아래 회전시 X축이 회전 되야함 -> Mouse.delta는 Vector2로 x,y 이동한 변화량을 반환
      //위 아래 회전시 X축으로 회전 , 2D에서 위,아래 관련 이동 데이터는 y축에 있기에
      //회전 각도로 사용하려면 Delta.y값을 사용 해야한다. 
      camCurXRot += mouseDelta.y * lookSensitivy;
      camCurXRot = Mathf.Clamp(camCurXRot, minXLook, maxXLook);
      //유니티는 왼손 좌표계이기에 x축의 정회전방향은 아래(아래로 회전시 양수)이다.
      //즉, 반대로 움직이기 때문에 -를 곱해서 정상적으로 움직이게 구현한것 
      cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);

      //좌 우 카메라 회전
      transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivy, 0);
  }

 

위,아래 회전은 cameraContatiner를 회전하였고 좌,우 회전은 오브젝트 자체를 회전했다.

이것도 중요한 내용이다, 3D 게임에서 만약 위아래 회전을 카메라가 아닌 오브젝트에 주게 된다면 

카메라가 위 아래로 이동할때마다 오브젝트 미친듯이 회전될거다.

왼쪽 이미지를 위아래로 회전시키면 오브젝트는 저렇게 말도 안되게 x축 회전을 하게된다.

 

이러한 현상 때문에 시야를 위,아래로 회전시키는 x축 회전을 카메라 에서 동작하게 한 것이고

좌,우 회전은 오브젝트가 그방향으로 바라볼때 몸도 그 방향으로 움직이는게 자연스럽기에 직접 회전을 시킨 것이다. 

자식으로 MainCamera를 가지고있는 cameraContainer를 참조

 

'Unity > Unity3D' 카테고리의 다른 글

Unity3D :: Ray,RayCast,RayCastHit  (0) 2024.10.24
Unity3D :: Skybox에 대해서  (0) 2024.10.24

+ Recent posts