본문 바로가기
제출용/TIL

내일배움캠프 20일차 TIL + inputsystem

by 유린테 2024. 5. 13.

package 추가하기

요즘 유니티가 용량을 줄이기 위해 패키지들 없이 다운이 된다.

필요한걸 찾아서 직접 다운해줘야함.

 

Window - Package Manager - Unity Register  - Input System - Install

 

프로젝트뷰에 Input 이라는 폴더 만들고 create- Input Actions 만들어줌

InputActions 이름 TopDownController2D 

No Control Scheme - 엑스박스용인지, PC 용인지 분류를 나누는 것.

 

애드 컨트롤 스키미 해주면 되는데, 여기서 저 + 해서 들어간 것들은 좌클릭이 안먹는다. 우클릭 하면 됨

23버전에선 고쳤다는데 22버전에서는 아직 버그가 존재함

 

Action Maps를 추가해주는데, Player 라는 이름으로 만들어줌

>> Player 가 할 수 있는 액션들이다!!

 

Actions 에 Move, Look, Fire 추가해줌

Move 는 움직일 때 - wasd 왔다갔다 - Vector2로 표현 할 수 있는

Look은 마우스 따라 왼쪽봤다 오른쪽 봤다  - Vector2로 표현 할 수 있는

Fire는 클릭할 때 - 눌렀다 안눌렀다 두개밖에 없어서 Vector 2 는 아님

 

Move 랑 Look은 액션타입 밸류, 컨트롤타입 Vector2 로 해준다

Fire 는 밸류, Any 로 한다 ( Any는 눌렀다 안눌렀다 같은 평가하기 편한 플로트같은 거)

 

Move는 업다운레프트라이트 컴포지트 저거 추가해줌

- 하나하나 등록하기 귀찮으니 만들어놓은 프리셋 같은 거

추가해주면 이렇게 됨

그리고 Up, Down, Left, Right 에 하나씩 넣어주는데, 이것도 22의 오류가 있다.

Path를 누르고 왼쪽 위의 바를 누르면 Listening for Axis...  가 뜨는데, 여기서 원하는 키를 눌러주면 그게 나온다.

 

다 하면 이렇게 되는데, 여기서 윗줄 중간에 Save Asset 을 눌러줘야 설정한게 저장이 된다.

Empty 만들어주고 MainSprite 를 해주는 이유는 스프라이트가 회전되있거나 그런거 메인스프라이트 안에서 처리하고, 실제 플레이어는 회전 안된것처럼 해주기 위함

그리고 MainSprite 에 스프라이트렌더러 추가해주고 Knight 넣어줌

player에 Rigidbody2d를 넣어주고 떨어지지않게 그래비티 0, 돌아가지 않게 Freeze Z 해준다.

그리고 Player input 추가해서 Actions에 탑다운컨트롤러 넣어주고, 디폴트 Any 되어있는걸 키보드마우스로 바꿔줌.

(지금은 키보드마우스 하나만 만들어 놓았기 때문에 Any 로 놔둬도 상관없다.)

 

Behavior 정리

 

Scripts 만들어서 TopDownController 만들기

탑다운컨트롤러에 액션들을 등록

탑다운 무브먼트에서 무브먼트 발생했을 때 이 함수 실행해주세여~ 를 컨트롤러에 등록

>> 컨트롤러에서 On Move Event 에서 무브이벤트 발생했을 때 등록한걸 인보크 해줌

왜하냐

온무브할때 이것저것 행동이 발생 (땅도흔들리고 뭐도 발생하고~) 이런걸 등록해놓고
발생했을때 다다다다 알려주는거임

Event 랑 Action 쓸거임

Event - 온무브이벤트 호출할 수 있음

Action 

 

public event Action<Vector2> OnMoveEvent; // Action 은 무조건 void만 반환해야함 아니면 함수
public event Action<Vector2> OnLookEvent; // Look 저거는 마우스

public void CallMoveEvent(Vector2 direction)   // MoveEvent 말생했을때 Invoke하는 역할 - 디렉션 : 어느방향으로 움직여!
{
    OnMoveEvent?.Invoke(direction);
}

public void CallLookEvent(Vector2 direction)
{
    OnLookEvent?.Invoke(direction);   //  ?. ==  없으면 말고 있으면 실행한다는 뜻
}

TopDownController 에는 이렇게 작성해준다.

 

public class PlayerInputController : TopDownController
{

}

그리고 이거를 넣어서 PlayerInputController 는 TopDownController 를 상속받는다!

클래스 이름에서 컨트롤 점 누르면 - PlayerInputController.cs로 형식 이동이 뜨고 누르면 바로 넘어가진다!

 

public class PlayerInputController : TopDownController
{
    private Camera camera;

    private void Awake()
    {
        camera = Camera.main; //mainCamera 태그가 붙어있는 카메라를 가져온다

    }

    public void OnMove(InputValue value)
    {
        Vector2 moveInput = value.Get<Vector2>().normalized;
        CallMoveEvent(moveInput);
        // 실제 움직이는 처리는 여기서 하는게 아니라 PlayerMovement 에서 함
    }

    public void OnLook (InputValue value) 
    {
        Vector2 newAim = value.Get<Vector2>();
        Vector2 worldPos = camera.ScreenToWorldPoint(newAim);
        newAim = (worldPos - (Vector2) transform.position).normalized; 

        CallLookEvent(newAim);
    }
}

 

그리고 

public class TopDownMovement : MonoBehaviour
{

}

 

만들어서 컨트롤 점 해주면 또 탑다운무브먼트 스크립트가 생성

 

 private TopDownController controller;
 private Rigidbody2D movementRigidbody;

 private void Awake()
 {
     // controller 랑 TopDownMovement랑 같은 게임오브젝트 안에 있다는 가정
     controller = GetComponent<TopDownController>();
     movementRigidbody = GetComponent<Rigidbody2D>();
 }

이거 해준 다음에 밑에

 private void Start()
 {
     controller.OnMoveEvent += Move;
 }

Move 함수를 만들지 않았기 때문에 빨간줄이 뜨는데, Move에 마우스 갖다대고 컨트롤 점 하면 메서드 생성이 됨!

 

private void Move(Vector2 vector)
{
    throw new NotImplementedException();
}

 

그럼 저절로 이게 밑에 적혀진다. 신기

중괄호 안에 있는거 지우고 새로 적어주기

 

 private void Move(Vector2 direction)
 {
     movementDirection = direcion;

 }

여기에도 movementDirecrtion 컨트롤 점 해서 필드생성 해주면 private 어쩌고 생김

private object movementDirection; 이렇게 생기는데 object 아니고 Vector2 로 바꿔주고 오류가 날 수 있으니

private Vector2 movementDirection = Vector2.zero; 로 기본값을 zero 로 잡아준다!

private void ApplyMovement (Vector2 direction) 
{
    direction = direction * 5;
    movementRigidbody.velocity = direction;

}

 

이렇게 해주면  ApplyMovement 는 실제로 실행이 안돼기 때문에 FixedUpdate 해줘야함

 

private void FixedUpdate()
{
    // FixedUpdate 는 물리 업데이트 관련
    // rigidbody의 값을 바구니까 FixedUpdate


}

FixedUpdate는 물리 업데이트 관련! 

 

move는 업데이트 베이스로 돌고 >> 프레임 기반임

얘를 FixedUpdate 기반으로 돌려주는거?

movementdirection 에다 걸어놓기만 하고 

실제 움직임을 처리하는건 FixedUpdate, 그거에 대한 함수가 ApplyMovement

 

그리고 다시 유니티로 돌아와서 Player 선택해주고 (중요)

Player Input Controller , TopDownMovement    Add 해주기

 

전에 한것과 기능적으로는 차이가 없지만, 확장가능성을 더 키워준것임

OnMove했을때 발생할 수 있는 이벤트가 더 다양해짐

각 컴포넌트마다 추가 추가 추가 한 다음에 

마지막에 인보크만 때려주면 되서 훨씬 편하다! 

 

< 정리 >

TopDownCotroller 는 캐릭터와 몬스터 공통적인 기능들을 넣어놓는 곳

여기서 Invoke를 할 수 있게 event 를 달아놨다

Action에 등록을 할 수 있게 만들어놨음

>>

Action 은 

Move라는건 방향이 있는 것  Vector2를 받아서 행동을 처리할거다.

OnLook은 마우스 방향 받아서 처리하겠다

 

CallMoveEvent는 등록되있던 Move 이벤트들을 Invoke 해주는거

>> OnMove에서 진행 

 

OnMove라는 함수를 왜 또 만들었느냐? 라고 하면

노멀라이즈드 하고, 스크린투월드포인트 만들어서 방향 만들어주고 이런 전처리 작업을 해주기 위함

 

전처리를 한 다음에, 그걸 바탕으로 CallMoveEvent를 실행시켜서 OnMoveEvent를 전체적으로 뿌려준다

 

OnLook 설명

 public void OnLook (InputValue value) 
 {
     Vector2 newAim = value.Get<Vector2>();
     Vector2 worldPos = camera.ScreenToWorldPoint(newAim);
     newAim = (worldPos - (Vector2) transform.position).normalized; 

     CallLookEvent(newAim);
 }

Vector2 worldPos = camera.ScreenToWorldPoint(newAim); 

카메라가 어딜 잡고 있는지를 알아야 하기 때문에 

camera.ScreenToWorldPoint - 카메라를 기준으로 마우스 좌표계가 존재하는 스크린 좌표계에서 월드좌표계로 바꿔라.

마우스의 위치를 월드기준으로 바꿔주는거임

 

 newAim = (worldPos - (Vector2) transform.position).normalized; 

마우스와 캐릭터의 차이가 얼마나 되냐 - 

worldPos에서 - 해주는 이유 : 얼마나 차이나는지 구할때 A>B 면 B-A 해서 거리를 구하는 거임

트랜스폼 포지션에서 월드가 어떤방향, 어느위치인지를 표현한 것

그 위치를 normalized .. 사이즈 1로 만들어준다고? 

 


 

저번 C#강의 튜터님은 말이 상당히 느리셨는데 

이번 유니티 강의 튜터님은 말이 상당히 빠르시다

뭐 하는지도 모르게 쉭쉭 지나가버리고 빨라서 다시듣기 삼백번씩 해야함

중간은 없는걸까?