2-2)TIL /./InputSystem, PlayerDamage

최보훈·2024년 2월 2일
0

TIL

목록 보기
22/28
post-thumbnail

InputSystem

이번 강의에선 플레이어 인풋시스템의 Behavior을 Invoke Unity Events 로 설정해주었다. 기존의 SendMessage 방식의 경우 On + Event 이름으로 설정을 해주어야 했지만 이경우 함수명이 정해지진 않았다.
하지만 이벤트 함수의 네이밍 규칙에 따라 On 을 붙여 함수명을 만드는것이 일반적이다.

함수의 인자값으로 public void OnMoveInput(InputAction.CallbackContext context)
과 같이 CallBackContext 를 지정할경우 아래의 인스펙터의 창에 따로 칸이 만들어져 나타나게 된다.

플레이어의 이동구현

public void OnMoveInput(InputAction.CallbackContext context)
{
    if(context.phase == InputActionPhase.Performed) //이벤트의 발생위치를 정하는거  started면 프레임에서 맨 처음 한번/ 누르는동안 =performed/ 떼질때 Calceled
    {
        curMovementInput = context.ReadValue<Vector2>();
    }
    else if(context.phase == InputActionPhase.Canceled)
    {
        curMovementInput = Vector2.zero;
    }
}
private void Move()
{
    Vector3 dir = transform.forward * curMovementInput.y + transform.right * curMovementInput.x;
    dir *= moveSpeed;
    dir.y = _rigidbody.velocity.y;

    _rigidbody.velocity = dir;  
}

Input System을 이용해 플레이어의 이동을 구현한 코드이다.
사용자의 키보드 입력이 OnMoveInput 으로 Vector2로 입력이 된다.vector2 curMovementInput 에 좌우는x 전후는y 로
이 입력값이 Move 함수에서 Vector3값으로 변경이 된다.
transform.forward(0,0,1) curMovementInput의 y값
transform.right(1,0,0) curMovementInput의 x값이다.
3D에서는 플레이어의 평면이동은 Vector3의 x,z가 관여한다. y는 높이.

카메라 회전및 플레이어 회전


Look의 경우 Mouse의 Delta값을 반환해주도록 설정을 하였다. 하지만 이 Delta가 어떤 값을 리턴하는것인지 몰라서 InputDebugger을 확인해보기로 하였다.

InputDebugger 을 이용해 확인해본 결과
Delta값은 마우스의 움직임정도를 Vector2값으로 나타내준다는것을 알게 되었다.

  • 좌우 이동은 vector2 x
  • 상하 이동은 y 로 치환된다.
void CameraLook()
{
    camCurXRot += mouseDelta.y * lookSensitivity; //마우스 위아래 이동\
    camCurXRot = Mathf.Clamp(camCurXRot, minXLook, maxXLook);
    cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);

    transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);

}
public void OnLookInput(InputAction.CallbackContext context)
{
    mouseDelta = context.ReadValue<Vector2>();
}

회전은 생각보다 간단했다. 마우스의 값을 그냥 그대로 Transform에 적용시켜주면 된다.
좌우 회전은 플레이어가 회전하도록 하였고
transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);,
상하 회전은 카메라가 회전하도록 하였다.
cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);

플레이어 데미지

인터페이스를 이용해 구현을 했다,

public interface IDamageable
{
    void TakePhysicalDamage(int damageAmount);
}

데미지를 입을 수 있는 물체들에게 이 인터페이스를 적용시키고

public void TakePhysicalDamage(int damageAmount)
{
    health.Subtract(damageAmount);
    onTakeDamage?.Invoke();
}

플레이어에게 TakePhysicalDamage = 데미지를 받는 함수를 작성해주었다.

데미지를 주는 물체로 캠프파이어이다.
캠프파이어는 다른 물체외 충돌할 경우
private List<IDamageable> thingsToDamage = new List<IDamageable>();

  private void OnTriggerEnter(Collider other)
  {
      if(other.gameObject.TryGetComponent(out IDamageable damageable))
      {
          thingsToDamage.Add(damageable);
      }
  }

TryGetComponent 로 Idamagable인지 확인해 리스트에 추가해준다.

 private void Start()
 {
     InvokeRepeating("DealDamage", 0, damageRate);
 }

 void DealDamage()
 {
     for(int i = 0;  i< thingsToDamage.Count; i++)
     {
         thingsToDamage[i].TakePhysicalDamage(damage);
     }
 }

추가된 IDamagable에 대해서 DealDamage를 통해 TakePhysicalDamage함수를 실행한다.

화면 효과

화면 효과의 경우 UnityEvent를 이용하였다.
public UnityEvent onTakeDamage;
onTakeDamage 유니티 이벤트 변수를 만들어
인스펙터 상에서 위와 같이 이벤트를 할당할 수 있도록 만들어 주었다.

public void TakePhysicalDamage(int damageAmount)
{
    health.Subtract(damageAmount);
    onTakeDamage?.Invoke(); //화면 효과에 사용중
}

플레이어 데미지 구현에 사용했던 함수에서 onTakeDamage이벤트를 실행해주면 완성이다!

아이템 상호작용

트러블 발생!

RigidBody와 collider가 설정된 부모 Empty오브젝트와 하위 실제 오브젝트 모야을 가진 >Prefab들이 따로 노는 현상이 발생

해결 방법

자식 오브젝트의 설정이 Static으로 되어있었다. 이를 체크해제하면서 해결

아이템 구현

ScriptableObject 를 이용해 아이템 데이터 구현

이번에도 Interface을 활용해 구현하였다.

public interface IInteractable
{
    string GetInteractPrompot();
    void OnInteract();
}

오브젝트와의 상호작용은 Ray를 이용하였다.
Ray ray = camera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2));
스크린의중앙에서 카메라 방향으로 향하는 레이를 생성해 오브젝트를 찾을수 있었다.

0개의 댓글