Unity/캐릭터

캐릭터 이동(Input System)

sungmin08 2024. 10. 26. 01:36

Input System의 핵심 개념

Action(액션) : 게임 내의 행동, 동작을 의미

  ▪ 캐릭터의 이동, 회전, 점프, 공격, 방어 등이 모두 Action에 해당

  ▪ 액션들에 해당하는 실제 매핑할 조작 방법을 정의 : 키보드, 마우스 등 정의

Binding : Action을 실제 물리적인 입력 장치와 매핑하는 것을 말함

 

 

1. 첫번째 방법 : 레거시 Input 클래스

키보드, 마우스, 터치, 게임 패드와 같은 외부 입력 장치의 입력 값을 미리 정의해두고 코드에 직접 해당 디바이스로부터 입력값이 있는지를 확인하는 방식

ex)float h=Input.GetAxis("Horizontal");

 

문제점 : 다양한 입력 장치로의 전환의 어려움

ex)게임패드/모바일 디바이스/햅틱 디바이스 등

◦ 이동 및 점프와 같은 디바이스로 변경할 경우 소스 코드르 다시 작성 해야 함

◦ Update 함수는 프레임마다 호출 되는 함수이므로 프레임마다 입력 값을 확인하기 때문에 성능상 좋지 않음

 

 

2. 두번째 방법 : Input System 사용

 

1. Input System Install하기

Input System Install

2. Active Handling 확인

Active Input Handling New로 셋팅 확인

3. Assets->Create->Input Action 생성

Input Action

 

Input System 구조

Input System

● Action Maps : Action들을 포함하고 있는 그룹

   ◦ 캐릭터 조작을 위한 입력 시스템이 있을 수 있고, UI 조작을 위한 입력 시스템이 있을 수 있음

● Actions : 게임 내에서의 행동 (Move / Rotate / Jump / Attack 등)들에 대한 정의

● Properties : Actions들에 대한 속성을 지정

 

 

4. Control Schemes

◦  Input Action -> Add Control Scheme

◦  PC와 Mobile 두개의 스키마 생성

 

5. Action Map 및 Action 생성

◦  주인공 캐릭터의 이동 및 공격 로직에 사용할 Action Map 생성

◦  Actions 영역의 New Actions를 "Move" 변경

◦  Action Type -> Value

◦  Control Type -> Vector2

◦ <No Binding> 지우기

 

◦Add Up/Down/Left/Right Composite 추가

◦아직 연결 정보 X. Path 선택 후 바인딩 연결 셋팅

 

◦이동 동작 바인딩 추가

-Up:<KeyBoard>/upArrow

-Down:<KeyBoard>/downArrow

-Left:/<KeyBoard>/leftArrow

-Right:/<KeyBoard>/rightArrow

+Space(스페이스공격)

 

 

6. Player Input 컴포넌트 추가

 

 

7. PlayerCtrl 코드 작성 (SendMessages 방법)

Behavior -> Send Messages 옵션 - Input Actions에서 설정한 액션을 Send Message 함수를 이용해 호출

#pragma warning disable IDE0051

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

public class PlayerCtrl : MonoBehaviour
{
    private Animator anim;
    private new Transform transform;
    private Vector3 moveDir;

    private void Start()
    {
        anim = GetComponent<Animator>();
        transform=GetComponent<Transform>();
    }

    private void Update()
    {
        if(moveDir!=Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(moveDir); // 진행 방향으로 회전
            transform.Translate(Vector3.forward * Time.deltaTime * 4.0f);// 회전 후 전진 방향으로 이동
        }
    }

    void OnMove(InputValue value)
    {
        Vector2 dir = value.Get<Vector2>();
        //2차원 좌표를 3차원 좌표로 변환
        moveDir = new Vector3(dir.x, 0, dir.y);

        anim.SetFloat("Movement", dir.magnitude);

        Debug.Log($"Move=({dir.x},{dir.y})");
    }

    void OnAttack()
    {
        anim.SetTrigger("Attack");
        Debug.Log("Attack");
    }

◦  네임스페이스 UnityEngine.InputSystem; 사용

◦ #pragma warning disable IDE0051 : 워닝 에러 감추기(함수나 변수를 선언하고 다른 곳에서 사용하지 않을 때 발생 하는 에러)

◦ InputValue 클래스는 Get(), Get<>()으로 받을 수 있음.

 

7. PlayerCtrl 코드 작성(Invoke Unity Events 옵션)

Behavior -> Invoke Unity Events

Move와 Attack이 Unity Event 타입의 속성으로 표시 됨.

 

 

#pragma warning disable IDE0051

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

public class PlayerCtrl : MonoBehaviour
{
    private Animator anim;
    private new Transform transform;
    private Vector3 moveDir;

    private void Start()
    {
        anim = GetComponent<Animator>();
        transform=GetComponent<Transform>();
    }

    private void Update()
    {
        if(moveDir!=Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(moveDir); // 진행 방향으로 회전
            transform.Translate(Vector3.forward * Time.deltaTime * 4.0f);// 회전 후 전진 방향으로 이동
        }
    }

    public void OnMove(InputAction.CallbackContext value)
    {
        Vector2 dir = value.ReadValue<Vector2>();
        Debug.Log($"Move=({dir.x}, 0, {dir.y}");
        moveDir = new Vector3(dir.x, 0, dir.y); //2차원 좌표를 2ㅊ차원으로 변환
        anim.SetFloat("Movement", dir.magnitude);
    }

    public void OnAttack(InputAction.CallbackContext value)
    {
        Debug.Log($"value.phase={value.phase}");
        if(value.performed)
        {
            Debug.Log("Attack");
            anim.SetTrigger("Attack");
        }
    }
}