본문 바로가기
제출용/TIL

내일배움캠프 19일차 TIL + 입력과 캐릭터 이동, input system

by 유린테 2024. 5. 10.
<<오늘의 교훈>>
대소문자 구분 꼭! 잘해줘야한다!!
스펠링 은근 잘 틀리니까 확인 확인~!!!


 

Time.deltaTime

이전 프레임부터 현재 프레임까지의 경과 시간을 나타낸다

deltaTime은 게임의 프레임 속도에 상관없이 일정한 시간 간격으로 동작하는 게임을 만들 때 유용하게 사용된다

주로 움직임, 애니메이션, 물리 시뮬레이션 등에서 시간에 따른 변화를 조정하는데 사용

ex. transform.Translate(Vector3.forward*speed*Time.deltaTime)과 같이 사용하면 프레임 속도에 관계없이

speed 만큼의 일정한 이동 속도를 보장할 수 있음

Time.deltaTime은 초 단위의 값을 반환하며, 1초에 1에 가까운 값을 가진다.

게임의 로직이 매 프레임마다 일정 속도로 실행되어야 할 때, deltaTime 을 이용하여 이동, 회전, 애니메이션 등의 연산에 일정한 시간 간격을 적용할 수 있다.

이를 통해 게임이 일정한 속도로 동작하고 다양한 기기나 환경에서도 일관된 경험을 제공할 수 있다.

 

delta 는 차이 를 나타낼 때 씀

전 프레임과의 차이 >> 경과 시간

컴퓨터 성능으로 인한 프레임 차이를 어느정도 극복해줄 수 있는 장치

 

접근 제한자와 직렬화 속성

 

Public >>>직렬화 한다

변수나 메서드가 외부에서 접근 가능하도록 공개

다른 클래스나 스크립트에서 해당 멤버에게 접근하여 값을 설정하거나 호출

 

Private 

변수나 메서드가 같은 클래스 내에서만 접근 가능하도록 제한

다른 클래스나 스크립트에서는 접근할 수 없고, 해당 클래스 내부에서만 사용

보통 내부 상태를 관리하거나 내부 구현에 사용

 

SerializeField

private로 선언된 변수를 인스펙터에서 직접 접근

기본적으로 private 변수는 인스펙터에서 표시되지 않지만, SerializeField를 사용하면 해당 변수가 인스펙터에서 수정가능한 필드로 표시

 

Serialize가 안돼는 것도 있다.

[SerializeField]

private ~~ 를 하면 프라이베이트지만 직렬로 볼 수 있다 ??

 

public class ExampleClass : MonoBehaviour
{
    public int publicVariable;
    private int privateVariable;
    
    [SerializeField]
    private int serializedFieldVariable;
    
    private void Start()
    {
        publicVariable = 10;  // 외부에서 접근 가능
        privateVariable = 20; // 클래스 내부에서만 접근 가능
        serializedFieldVariable = 30; // 인스펙터에서 접근 가능
    }
}

 

Vector2 direction = new Vector2(horizontal, vertical);  

이렇게 했을 때  (0,0) , (0,1) (1,1) 등 다양하게 나올 수 있는데 1,1 은 길이가 1이 아니라 루트2가 나오기 때문에

길이를 1로 만들어주는 정규화 작업을 해주어야한다.

 

캐릭터가 바로바로 안멈춘다는 문제 - 

// 매프레임마다 Vertical 축과 Horizontal 축을 가져옵니다
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");

Vector2 direction = new Vector2(horizontal, vertical);  
// 0,0 0,1 1,1 일 수도 있기 때문에 정규화를 해준다
// 정규화 - 길이를 1로 만드는 작업
direction = direction.normalized;

GetComponent<Rigidbody>().velocity = direction * speed;

여기서 GetAxis 를 GetAxisRaw 로 해주면 +1 -1 0 으로만 나워서 좀 더 깔끔하게 움직이는걸로 보인다.

그리고 그래비티 스케일 0으로 안해주면 아래로 떨어짐!

 

계속 똑같은 게임 오브젝트에 접근할 때, 리기드바디 같은걸 한번 걸어놓고 계속 가져오면 됨.

GetComponent  를 매일 하는게 아니라 Start에서 한번 해주고 계속 사용하게 한다

 

    [SerializeField] private float speed;
    Rigidbody2D rb;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }
    // Update is called once per frame
    void Update()
    {
        // 매프레임마다 Vertical 축과 Horizontal 축을 가져옵니다
        float vertical = Input.GetAxisRaw("Vertical");
        float horizontal = Input.GetAxisRaw("Horizontal");

        Vector2 direction = new Vector2(horizontal, vertical);  
        // 0,0 0,1 1,1 일 수도 있기 때문에 정규화를 해준다
        // 정규화 - 길이를 1로 만드는 작업
        direction = direction.normalized;

        GetComponent<Rigidbody>().velocity = direction * speed;

    }

스타트에 저렇게 넣어주고, Rigidbody도 밖에 저렇게 해줌

 GetComponent<Rigidbody>().velocity = direction * speed; 를 이제 겟컴포넌트를 또 가져와 줄 필요 없으니

 

 rb.velocity = direction * speed;  이렇게 rb 로 고친다.

 

이렇게 쓸 수 없는 경우 : 매번 달라져야 할 때 
겟 컴포넌트를 계속 해줘야함

이 인풋이 얘만 관장한다 하면 굳이 리기드바디를 계속 가져올 필요 없이 지금처럼 한번만 가져와주면 된다.

 

InputManager 의 문제

 

조이스틱 등 다양한 입력 장비 대응이 어렵다!

지금 현재 InputManager에서는 다양한 플랫폼에 대응하거나, 키를 변경하는 리바인딩 하는 그런 부분이 부족하다

요즘 게임에서는 키셋팅 변경같은게 나름 흔한데!

 

입력 처리와 실제 로직 실행 주체를 분리

사실 InputManager 자체의 문제로 보기는 어렵지만, 해당 버전에서는 구현했던 내용들이 모두 한 클래스들에 모여있어

클래스들에 대한 확장성과 유지보수성이 많이 떨어지는 문제가 있었다.

기능별로 클래스를 나누는 것은 설계에 많은 도움을 줌

객체지향 프로그래밍에서 이런 설계원칙을 우리는 단일 책임 원칙 (Single Responsibility Principle) 이라 부른다

 

New Input System

1. Input Action : 입력 행동을 정의함

ex.  점프, 공격 등의 행동을 정의하고, 이런 행동을 트리거하는 키 또는 버튼을 지정할 수 있음

2. Input Action Asset : 여러개의 입력 행동을 그룹화 하는 방법

재사용 가능한 입력 설정을 만들어 게임 내의 다른 캐릭터나 메뉴에 적용할 수 있음

3. Player Input Component : 유니티의 New Input System에 추가된 새로운 컴포넌트,

자동으로 입력 행동을 처리하고 해당 게임 오브젝트에 메세지를 보냄

 

New Input System의 장점

1. Cross-platform compativility : New Input System은 다양한 플랫폼과 입력 장치에 대해 일관된 방식으로 작동함

2. Rebinding : 플레이어가 게임 내에서 자신의 입력 설정을 변경할 수 있도록 지원

3. Multiplayer Support : 여러 플레이어가 동일한 장치에서 게임을 플레이하거나, 각각의 장치에서 게임을 플레이할 때 

입력을 쉽게 처리할 수 있음

 

설계하기

컨트롤러는 어떤 오브젝트의 상황에 따라 행동을 결정하고, 이를 TopDownMovement와 같이 실제 로직을 수행하는 컴포넌트들에 이벤트들을 전달하는 역할을 함

이러한 컨트롤러는 플레이어에만 들어가는게 아니므로, 이번에는 PlayerInputController를 만들겠지만

적에게도 사용되는 공통적 기능들은 TopDownController에 정의하여 이를 재활용 할 수 있게 한다

일단 이번 강의에서 TopDownController 에서는 이동과 관련된 액션들을 모두 실행하는 CallMoveEvent, 

마우스와 관련된 이벤트를 모두 실행하는 OnLockEvent를 정의하고 이를 호출하는 기능만 추가

 

탑다운컨트롤러 자체에는 몬스터도 쓰고, 캐릭터도 쓰고 하는 이동같은 할 수 있는 행동들을 전반적으로 가지고 있을거고,플레이어인풋컨트롤러에는 플레이어의 행동들 (우리가 컨트롤 해야하는!@)_ 부분들이 들어감

 

탑다운 컨트롤러는 이동해야 하는 상황에서 탑다운무브먼트를 호출

이걸 효과적으로 관리하기 위해 Action 을 사용 >> 옵저버 패턴이라고 함

구독을 해 놓으면 : 움직일 때, 이거 해야한다 라고 등록을 해놓으면 그렇게 처리름 함 Invoke

Pubsub  패턴이라고도 함 (public subcribe) 

 

 


 

 

 

이번주 안에 강의도 다 들어야하고.. 개인프로젝트도 해야하는데 솔직히 좀 버겁다

강의듣는 주에는 그냥 강의만 듣게 해줬으면 좋겠어

빨리 강의 듣고 과제해야하는데..!!! 하는 마음에 강의도 집중이 안돼고, 마음도 계속 초조하다

저번 TxtRPG 때도 그랬지만 강의 습득이 제대로 안된 상태 + 마음급함 + 시간없음 이 되다 보니 과제에 필요한 부분까지 듣고 그 뒷부분을 미뤄놨다가 계속 몰아치는 다른 강의와 과제 때문에 듣지 못했다

강의를 제대로 모르니 코드는 복붙만 계속 하게되고... 뭔가 붙잡고 생각할 시간이 되지 않는 느낌?

물론 다른 사람들은 잘 따라가고 있고.. 내가 느려서 뒤쳐진거겠지만... 

사실 내 집중력 문제가 맞을 것이다.

음. 암튼 화이팅.