오늘은 유니티에서 NewInputSystem을 학습해보겠습니다.
저 같은 경우 매번 다시 만들기 귀찮고
그렇다고, 예전 Input.어쩌구를 쓰기는 이제 좀... 그렇고 하여서
아예 하나 레포를 만들어 버렸습니다.
참고하실 분들은 여기로..
https://github.com/ym7596/Unity_Template_NewInputSystem
GitHub - ym7596/Unity_Template_NewInputSystem: 개인 저장용 newinputsystem
개인 저장용 newinputsystem. Contribute to ym7596/Unity_Template_NewInputSystem development by creating an account on GitHub.
github.com
유니티6가 나오면서
이제 유니티에서 NewInputSystem을 따로 패키지에서 설치해주어야 했던 것과는
달리
미리 설치되어있습니다.
하지만 설치되어있고 기본세팅이 있는 것과는 별개로
어떻게 사용해야하는 지를 모르면 말짱 도루묵..
오늘은 사용법에 대해서 알아보겠습니다.
1회성이 아닌 진짜 프로젝트에서 범용적으로 사용한다는 기준으로 작성합니다.
인풋액션을 만들고 눌러보면
액션을 만들 수 있습니다.
좌측의 Action Maps는 어떠한 인풋의 집합체이냐 하는 그룹이름입니다.
따로 나눌 수도 있지만
설계에 따라서 하나의 액션맵에서 공용으로 다 처리할 수도 있습니다.
Actions(가운데) 의 우측 +를 누르면 말그대로
Action 어떠한 행동 (마우스클릭, 손가락 터치등...)에 대한 정의를 내릴 수 있고
내가 만약 맨 위의 Tab처럼 손가락으로 화면을 터치하는 것 혹은 마우스로 클릭하는 행위를
만들고 Tab아래처럼 Press, ButtonClick등 유사한 행위를 나열하는
Binding이라는 작업을 할 수 있습니다.
저리 되면 버튼클릭을 하든 (마우스) 손가락으로 탭을 하든
같은 액션이 호출됩니다.
리턴값은 오른쪽의 Action Type과 Value로 받게 되는데..
Vector2의 리턴값은 내가 터치한 곳의 스크린 위치를 받게 됩니다.
보통 이 값을 통해서 RayCast를 쏘는 역할을 하게 되죠.
마찬가지로 이 Tab의 Action Type은 Button인데
누르는 것에 대한 호출을 담당하겠다는 뜻입니다.
클릭/손가락터치 등등이며,
드래그를 할적에도 첫터치에 대한 액션값을 받을 때 유용합니다..
쨌든... 이런식으로 액션을 구성을 하고 저장을 하면
이제 이 액션을 스크립트에 연결만 해주면 됩니다.
제 액션의 이름은 dduRInput입니다.
//간단히 이렇게 선언할 수 있습니다.
private dduRInput _ddurInput;
참고로, 액션을 불러올 때는 제가 사용하는 방식외에
직접 링크시키는 방법, 인터페이스 등등이 있는데
전 클래스로 호출하는 방식으로 합니다.
(뭐 큰 차이는 없습니다. 다른 곳에서는 다르게 하더라도 결과는 같습니다.)
private dduRInput _dduRInput;
private void Awake(){
_dduRInput = new dduRInput();
_dduRInput.Enable();
}
NewInputSystem을 클래스로 사용할 경우
Awake단에서 초기화를 시켜주어야 합니다.
(그래서 Mono를 상속받아야함..)
Enable을 호출하면 이제 사용할 수 있게 됩니다.
어떻게 사용하는가?
각기 다른 Actions들을 연결해야한다.
예를들면 Tab 을 눌렀을 때 동작하는 함수를 만든다.
참고로 모든 콜백은 InputAction.CallbackContext
모든 동작에는 start, perform, cancel로 나뉨
private void OnEnable()
{
dduRInput.dduRAction.Tab.started += OnTabStarted;
//액션이름.액션맵이름.액션s 에 리스너 연결
dduRInput.dduRAction.Tab.performed += OnTabPerformed;
dduRInput.dduRAction.Tab.canceled += OnTabCanceled;
}
#region Tab
private void OnTabStarted(InputAction.CallbackContext context)
{
IsUITouched = IsUITouch();
UpdatePressedState();
OnLeftMouseState?.Invoke(TouchPhases.Began);
PhaseChange(TouchPhases.Began);
}
private void OnTabPerformed(InputAction.CallbackContext context)
{
UpdatePressedState();
OnLeftMouseState?.Invoke(TouchPhases.Moved);
PhaseChange(TouchPhases.Moved);
}
private void OnTabCanceled(InputAction.CallbackContext context)
{
rayhit = GetRayHit(Pos);
OnLeftMouseState?.Invoke(TouchPhases.Ended);
PhaseChange(TouchPhases.Ended);
}
#endregion
이렇게 보통 연결시켜 놓는다.
추가적으로 많이 사용하는 Value - Vector2 타입의 경우는..
public Vector2 PrimaryPosition { get; private set; }
public Vector2 Pos { get; private set; }
private void OnEnable()
{
movement = dduRInput.dduRAction.Move;
dduRInput.dduRAction.Tab.started += OnTabStarted;
dduRInput.dduRAction.Tab.performed += OnTabPerformed;
dduRInput.dduRAction.Tab.canceled += OnTabCanceled;
dduRInput.dduRAction.Position.started += OnPositionStarted;
dduRInput.dduRAction.Position.performed += OnPositionPerformed;
dduRInput.dduRAction.Position.canceled += OnPositionCanceled;
}
#region Position
private void OnPositionStarted(InputAction.CallbackContext context)
{
PrimaryPosition = context.ReadValue<Vector2>();
}
private void OnPositionPerformed(InputAction.CallbackContext context)
{
Pos = context.ReadValue<Vector2>();
}
private void OnPositionCanceled(InputAction.CallbackContext context)
{ }
#endregion
context에서 ReadValue를 통하여 받아오면 된다.
전체 이러한 코드 전문은 상단의 github에 올려져 있으니 확인을 하시면 될 듯 하구..
자 이러면 이제 우리는 눌렀을 때 원하는 변수에
(그러기 위해선 변수를 public 으로 선언을 해주어야함)
값을 넣어주는 것까지 된 것이고
이제 실제로 사용하려면 이 InputManager.cs를
사용하려는 스크립트에서 호출만 해주면된다.
CameraController.cs (예시)
using UnityEngine;
using UnityEngine.InputSystem;
public class CameraController
{
private InputManager _inputs;
private Transform _camTransform;
private float _maxSpeed = 10f;
private float _speed;
private float _accelration = 10f;
private float _damping = 15f;
//rotation
private float _normalizedConst = .1f;
private float _dragSpeed = 2f;
//screen edge motion
//value set in various functions
private Vector3 _targetPosition;
//use to track and maintain velocity w/o a rigidbody
private Vector3 _horizontalVelocity;
private Vector3 _lastPosition;
//dragging action started
private Vector3 _startDrag = Vector3.zero;
private Vector2 _movementValue;
private Vector3 _movementValueVertical;
public CameraController(Transform cam, InputManager inputManager)
{
_camTransform = cam;
_inputs = inputManager;
Init();
}
private void Init()
{
_inputs.OnActionWASD += SetWASD;
_inputs.OnActionScrollWheel += SetWheelScroll;
_inputs.OnRightClickedReleased += DragClear;
_inputs.OnKeyboardListener += GetKeysValue;
}
public void Update()
{
GetKeyBoardMovement(); //WASD버튼 이동
GetKeyBoardMovementUp(); //QE 이동
GetScrollButtonMovement(); //스크롤버튼 드래그 이동
SetRotateByRightButton(); // 우클릭 회전
UpdateBasePosition();
}
private void DragClear()
{
_startDrag = Vector3.zero;
}
private void SetWheelScroll(float value)
{
float val = value / 120;
Vector3 wheelValue = Vector3.forward * val;
_camTransform.Translate(wheelValue,Space.Self);
}
private void SetWASD(Vector2 dir)
{
_movementValue = dir;
}
private void SetQE(bool isUp)
{
if (isUp)
_movementValueVertical = Vector3.up;
else
{
_movementValueVertical = Vector3.down;
}
}
private void SetRotateByRightButton()
{
if (_inputs.RightIsClicked == false || _inputs.ScrollIsClicked == true)
return;
if(_startDrag == Vector3.zero)
_startDrag = _inputs.PrimaryRightPos;
Vector3 currentPos = _inputs.Pos;
Vector3 dragDelta = currentPos - _startDrag;
float rotX = -dragDelta.y * _normalizedConst;
float rotY = dragDelta.x * _normalizedConst;
_camTransform.Rotate(Vector3.up, rotY, Space.Self); // y축 회전
_camTransform.Rotate(Vector3.right, rotX, Space.Self);
float z = _camTransform.eulerAngles.z;
_camTransform.Rotate(0,0,-z);
_startDrag = currentPos;
}
private void GetScrollButtonMovement()
{
if (_inputs.ScrollIsClicked == false || _inputs.RightIsClicked == true)
return;
if (_startDrag == Vector3.zero)
_startDrag = _inputs.PrimaryWheelPos;
Vector3 currentPos = _inputs.Pos;
Vector3 dragDelta = currentPos - _startDrag;
dragDelta = dragDelta.normalized * _normalizedConst;
Vector3 moveDir = new Vector3(-dragDelta.x, -dragDelta.y, 0) * _dragSpeed;
_camTransform.Translate(moveDir,Space.Self);
//좌우 X축 -+ 상하 Y축 +-
_startDrag = currentPos;
}
private void GetSpaceAndLeftButtonMovement()
{
}
private void GetKeysValue(InputActionPhase phase, string keyName)
{
if (phase == InputActionPhase.Performed)
{
switch (keyName)
{
case "Q":
SetQE(true);
break;
case "E":
SetQE(false);
break;
case "Space":
break;
case "F":
break;
default:
break;
}
}
else if (phase == InputActionPhase.Canceled)
{
switch (keyName)
{
case "Q":
case "E":
_movementValueVertical = Vector3.zero;
break;
}
}
}
#region WASDQE MOVE
private void GetKeyBoardMovementUp()
{
_speed = Mathf.Lerp(_speed, _maxSpeed, Time.deltaTime * _accelration);
_camTransform.Translate(_movementValueVertical *_speed* Time.deltaTime,Space.World);
}
private void GetKeyBoardMovement()
{
Vector3 inputValue = _movementValue.x * GetCameraRight(_camTransform)
+ _movementValue.y * GetCameraForward(_camTransform);
inputValue = inputValue.normalized;
if (inputValue.sqrMagnitude > 0.1f)
_targetPosition += inputValue;
}
private void UpdateBasePosition()
{
if (_targetPosition.sqrMagnitude > 0.1f)
{
_speed = Mathf.Lerp(_speed, _maxSpeed, Time.deltaTime * _accelration);
_camTransform.position += _targetPosition * _speed * Time.deltaTime;
}
else
{
_horizontalVelocity = Vector3.Lerp(_horizontalVelocity, Vector3.zero, Time.deltaTime * _damping);
_camTransform.position += _horizontalVelocity * Time.deltaTime;
}
_targetPosition = Vector3.zero;
}
private Vector3 GetCameraRight(Transform transform)
{
Vector3 right = transform.right;
right.y = 0;
return right;
}
private Vector3 GetCameraForward(Transform transform)
{
return transform.TransformDirection(Vector3.forward);
}
private Vector3 GetCameraUp(Transform transform)
{
return transform.TransformDirection(Vector3.up);
}
#endregion
}
내가 하던 방식은
InputManager.cs에서 Action을 만들어놓고
이 액션과 연결하는 방식이다.
인풋매니저에서는 단독으로 쓰일 수 있게
연결은 시키지 않고 액션 이벤트를 Invoke하는 것 까지가 끝.
https://github.com/ym7596/Unity_Template_NewInputSystem
GitHub - ym7596/Unity_Template_NewInputSystem: 개인 저장용 newinputsystem
개인 저장용 newinputsystem. Contribute to ym7596/Unity_Template_NewInputSystem development by creating an account on GitHub.
github.com
다시 한번 이 git을 받아보시면.. 데모씬도 있으니 쉽게 확인이 가능할 수 있습니다.
'프로그래밍 > Unity' 카테고리의 다른 글
[유니티] Unity - 코루틴 리턴값 받기와 Action에 대하여. (6) | 2024.12.13 |
---|---|
[유니티] Unity WebGL - React.js와 쌍방향 통신하기 (2) | 2024.12.11 |
Unity - Rest API 만들고 적용하기 (0) | 2024.12.09 |
유니티 3D - 인공지능 AI (스크립트) (1) | 2017.12.09 |
유니티 Unity - Curved UI 휘어진 UI 에셋 구매후기. (0) | 2017.12.06 |