UNITY에서 오브젝트를 움직이는 데는 여러 방법이 있다.
그 중 옵저버 패턴을 이용한 이동 기능 구현을 기록한다.
우선, 아래는 오늘 제작한 UNITY 캐릭터 이동 코드를 담은 스크립트 3개다.
using System;
using UnityEngine;
public class TopDownCharacterController : MonoBehaviour
{
public event Action<Vector2> OnMoveEvent;
public event Action<Vector2> OnLookEvent;
public void CallMoveEvent(Vector2 direction)
{
OnMoveEvent?.Invoke(direction);
}
public void CallLookEvent(Vector2 direction) // 아직 미구현
{
OnLookEvent?.Invoke(direction);
}
}
위 스크립트는 캐릭터가 이동 입력WASD를 받을 경우 이벤트 함수OnMoveEvent, OnLookEvent를 실행하는 클래스다.
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerInputController : TopDownCharacterController
{
private Camera _camera;
private void Awake()
{
_camera = Camera.main;
}
public void OnMove(InputValue value)
{
Vector2 movePositionInput = value.Get<Vector2>().normalized; // 입력값의 vector2값을 normalize해서 할당
CallMoveEvent(movePositionInput); // 받은 값(vector2 형식)으로 CallMoveEvent함수 실행
} // 이 함수만으로는 아직 event함수OnMoveEvent는 null이다.
public void OnLook(InputValue value)
{
Vector2 newAim = value.Get<Vector2>(); // 입력값의 vector2값을 normalized해서 할당(현재 마우스 위치)
// 현재 스크린에 비치는 마우스의 위치를 월드 좌표로 계산해 할당
Vector2 worldPos = _camera.ScreenToWorldPoint(newAim);
// (현재 마우스 좌표 - 플레이어(이 스크립트를 들고 있는 오브젝트)의 위치 좌표)를 normalize해서 할당
newAim = (worldPos - (Vector2)transform.position).normalized;
if (newAim.magnitude >= 0.9f) // ?if문? 그냥 방어코든가?
{
CallLookEvent(newAim);
}
}
public void OnFire(InputValue value)
{
Vector2 fireVector = value.Get<Vector2>(); // 미구현, 그냥 써 놓은 거다.
Debug.Log($"OnFire Operated at : x={fireVector.x}, y={fireVector.y}"); // 미구현, 그냥 써 놓은 거다.
}
}
위 스크립트는 사용자의 입력값을 호출할 함수의 매개변수 형식에 맞게 수정하고, 호출한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TopDownMovement : MonoBehaviour // 캐릭터의 움직임
{
private TopDownCharacterController _controller;
private Vector2 _moveDirection = Vector2.zero;
private Rigidbody2D _rigidbody;
private void Awake()
{
_controller = GetComponent<TopDownCharacterController>();
_rigidbody = GetComponent<Rigidbody2D>();
}
private void Start()
{
_controller.OnMoveEvent += Move;
} // 이 함수 할당으로 비로소 OnMoveEvent이벤트는 값을 가지게 된다.
private void FixedUpdate()
{
ApplyMove(_moveDirection);
}
private void Move(Vector2 direction)
{
_moveDirection = direction;
}
private void ApplyMove(Vector2 direction)
{
_rigidbody.velocity = direction * 5;
}
}
위 코드를 통해 이벤트를 보고 있는 코드(이벤트 구독 상태의 코드-옵저버)를 생성하고, 사용자의 입력이 있을 때 이벤트는 자신의 매개변수로 자신을 옵저버를 작동시킨다.
이렇게 이해하면 되나? 나름 반 정도는 이해를 한 것도 같은데, 나머지 Look,Fire 코드 작성 때 좀 더 확실히 하겠다.
'UNITY' 카테고리의 다른 글
| UNITY_20230907[UNITY개인 프로젝트 회고] (0) | 2023.09.07 |
|---|---|
| UNITY_20230906[UNITY - 오브젝트의 물리 정보 표현] (0) | 2023.09.07 |
| UNITY_20230811[1주차 회고록] (0) | 2023.08.11 |
| UNITY_20230811[팀 프로젝트_4] (0) | 2023.08.11 |
| UNITY_20230810[팀 프로젝트_3] (0) | 2023.08.10 |