▶▷ 아이템
어제 InputSystem에서 추가했던 F키를 통해 상호작용할 수 있는 아이템을 구현하였다.
using UnityEngine;
// 아이템의 종류를 나타내는 열거형
public enum ItemType
{
Resource, // 자원 타입
Consumable // 소비 가능한 아이템 타입
}
// 소비 아이템의 종류를 나타내는 열거형
public enum ConsumableType
{
Health, // 체력 회복
Speed // 속도 증가
}
// 소비 아이템의 데이터를 저장하는 클래스
[System.Serializable]
public class ItemDataConsumable
{
public ConsumableType type; // 소비 아이템의 종류
public float value; // 소비 아이템의 효과 값
}
// ScriptableObject를 상속받아 아이템 데이터를 저장하는 클래스
[CreateAssetMenu(fileName = "Item", menuName = "New Item")] // 생성 메뉴에 "New Item" 추가
public class ItemData : ScriptableObject
{
[Header("Info")]
public string displayName; // 아이템의 이름
public string description; // 아이템의 설명
public ItemType type; // 아이템의 타입
public GameObject dropPrefab; // 아이템 드랍 시 사용할 프리팹
[Header("Consumable")]
public ItemDataConsumable[] consumables; // 소비 아이템 관련 데이터 배열
}
아이템 타입을 enum을 통해 일반 자원과 사용 가능한 것으로 나누었고 사용 가능한 아이템에는 체력과 속도 관련 아이템이 있다.
이렇게 작성하면 이제 생성 메뉴에 New Item이라는 항목이 생기는데 해당 항목을 추가하여 아래와 같이 아이템의 데이터를 생성할 수 있다.
데이터를 생성한 다음엔 플레이어의 정면으로 레이캐스트를 발사하고 탐지됐을 경우와 탐지 후 상호작용을 했을 경우의 상태를 작성했다.
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
public class Interaction : MonoBehaviour
{
// 상호작용 오브젝트를 체크하는 주기
public float checkRate = 0.05f;
// 마지막으로 체크한 시간을 저장하는 변수
private float lastCheckTime;
// 레이캐스트를 통해 체크할 최대 거리
public float maxCheckDistance;
// 레이캐스트 대상이 되는 레이어를 지정하는 마스크
public LayerMask layerMask;
// 현재 상호작용 가능한 게임 오브젝트
public GameObject curInteractGameObject;
// 현재 상호작용 가능한 오브젝트의 인터페이스
private IInteractable curInteractable;
// 상호작용 프롬프트 객체
public TextMeshProUGUI promptText;
// 메인 카메라 참조
private Camera camera;
// 게임 시작 시 한 번 호출되는 초기화 함수
void Start()
{
// 현재 씬의 메인 카메라를 찾아 할당
camera = Camera.main;
}
// 매 프레임마다 호출되는 업데이트 함수
void Update()
{
// 마지막 체크 이후 경과 시간이 checkRate보다 크면 상호작용 체크를 진행
if (Time.time - lastCheckTime > checkRate)
{
// 현재 시간을 lastCheckTime에 저장
lastCheckTime = Time.time;
// 화면 중앙에서 카메라를 통해 레이 생성
Ray ray = camera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2));
RaycastHit hit;
// 지정한 최대 거리와 레이어 마스크를 사용하여 레이캐스트 수행
if (Physics.Raycast(ray, out hit, maxCheckDistance, layerMask))
{
// 레이캐스트에 탐지된 오브젝트가 현재 저장된 오브젝트와 다를 경우
if (hit.collider.gameObject != curInteractGameObject)
{
// 탐지된 오브젝트로 현재 상호작용 대상을 업데이트
curInteractGameObject = hit.collider.gameObject;
// 해당 오브젝트에서 IInteractable 컴포넌트를 가져옴 (없으면 null)
curInteractable = hit.collider.GetComponent<IInteractable>();
// 상호작용 프롬프트 텍스트를 갱신
SetPromptText();
}
}
else // 레이캐스트에 탐지된 오브젝트가 없을 경우
{
// 상호작용 대상 초기화 및 프롬프트 텍스트 비활성화
curInteractGameObject = null;
curInteractable = null;
promptText.gameObject.SetActive(false);
}
}
}
// 상호작용 가능한 오브젝트의 프롬프트 텍스트를 설정하는 함수
private void SetPromptText()
{
// 프롬프트 텍스트 UI 활성화
promptText.gameObject.SetActive(true);
// 현재 상호작용 대상의 인터페이스에서 상호작용 프롬프트 메시지를 받아와 텍스트로 표시
promptText.text = curInteractable.GetInteractPrompt();
}
// 입력 시스템을 통해 상호작용 입력 이벤트가 발생하면 호출되는 함수
public void OnInteractInput(InputAction.CallbackContext context)
{
// 입력 이벤트가 시작되었고, 현재 상호작용 대상이 존재할 경우
if (context.phase == InputActionPhase.Started && curInteractable != null)
{
// 상호작용 대상의 OnInteract() 함수를 호출하여 상호작용 수행
curInteractable.OnInteract();
// 상호작용 후 대상 및 인터페이스 초기화, 프롬프트 텍스트 숨김
curInteractGameObject = null;
curInteractable = null;
promptText.gameObject.SetActive(false);
}
}
}
using UnityEngine;
// 인터랙션 가능한 객체를 위한 인터페이스
public interface IInteractable
{
public string GetInteractPrompt(); // 인터랙션 시 표시할 텍스트
public void OnInteract(); // 인터랙션 실행 함수
}
public class ItemObject : MonoBehaviour, IInteractable
{
public ItemData data; // 아이템 데이터
public string GetInteractPrompt()
{
// 아이템 이름과 설명을 조합하여 반환
return $"{data.displayName}\n{data.description}";
}
public void OnInteract()
{
// 플레이어에게 아이템 데이터를 전달 후 아이템 오브젝트 제거
CharacterManager.Instance.Player.itemData = data;
CharacterManager.Instance.Player.addItem?.Invoke();
Destroy(gameObject);
}
}
가까이 가서 조준점을 갖다대면 하단에 설명이 나오고 F키를 누르면 아이템과 상호작용할 수 있다.
아이템과 상호작용 했을 경우 생기는 효과는 아직 구현 중에 있다.
▶▷ 점프대
점프대는 간단하게 일정 구간에 Collider를 생성하고 해당 구간으로 가면 ForceMode.Impulse를 이용해 순간적인 힘을 강하게 주는 방식으로 구현했다.
private void OnCollisionEnter(Collision target)
{
if (target.collider.CompareTag("Trampoline"))
{
rb.AddForce(Vector3.up * jumpPower * 5, ForceMode.Impulse);
}
}
▶▷ 오늘의 회고
비주얼 스튜디오에서 주석을 달아가면서 작업을 하는데 깃허브 데스크탑에서 보니 한글이 자꾸 깨지는 현상이 있었다. 이 현상은 현재 인코딩 방식이 utf-8이 아닌 cp949로 되어있기 때문에 생기는 것이었다.
해결 방법은 비주얼 스튜디오 상단에서
도구 클릭 -> 옵션 -> 텍스트 편집기 -> C# -> 코드 스타일 -> '설정에서 .editorconfig 파일 생성' 버튼 클릭
이렇게 하면 폴더에 .editerconfig 파일이 생성되고 해당 파일을 열어 맨 아래에
[*]
charset = utf-8
이 내용을 추가하면 깨짐 현상이 사라진다.
이미 작성했던 스크립트의 깨짐 현상은 비주얼 스튜디오에서
파일 -> 다른 이름 저장 -> 저장 버튼 옆 화살표 클릭하여 인코딩하여 저장 -> 인코딩을 utf-8로 변경
이 과정을 통해 수정할 수 있다.
'게임 개발 공부 기록' 카테고리의 다른 글
33일차 - 직렬화, 역직렬화 (0) | 2025.03.11 |
---|---|
32일차 - 3D Practice 3 (아이템 코루틴, 레이저 트랩) (0) | 2025.03.10 |
30일차 - 3D Practice 1 (이동, 체력) (0) | 2025.03.06 |
29일차 - AI Navigation (0) | 2025.03.05 |
28일차 - ForceMode, Raycast, Coroutine, Light (0) | 2025.03.04 |