스파르타코딩클럽_Unity개발과정
유니티 숙련 개인 과제 - 3D 게임 캐릭터 이동과 물리 (2)
ybbro
2025. 5. 22. 22:19
1. 체력 표시, 감소, 회복
캠프 파이어 불 안에 트리거를 두고 그 안의 대미지를 가할 수 있는 오브젝트에 대미지를 지속적으로 주게끔 만들었습니다.
using UnityEngine;
using System.Collections.Generic;
namespace Environment
{
[RequireComponent(typeof(Collider))] // 오브젝트를 부착할 때 콜라이더가 없다면 부여
public class Campfire: MonoBehaviour
{
public int damage;
public float damageDelay;
List<IDamagable> damagables = new List<IDamagable>();
private void Awake()
{
// 콜라이더를 트리거로 변경
TryGetComponent(out Collider col);
col.isTrigger = true;
}
private void Start()
{
// 대미지를 주는 주기마다, 영역 내 대미지를 줄 수 있는 오브젝트들에 대미지
InvokeRepeating("DealDamage", 0, damageDelay);
}
void DealDamage()
{
for (int i = 0; i < damagables.Count; i++)
{
damagables[i].TakeDamage(damage);
}
}
// 캠프파이어 불에 출입하는 대미지를 줄 수 있는 오브젝트들에 대해 이를 등록/해제
private void OnTriggerEnter(Collider other)
{
if(other.TryGetComponent(out IDamagable damagable))
damagables.Add(damagable);
}
private void OnTriggerExit(Collider other)
{
if(other.TryGetComponent(out IDamagable damagable))
damagables.Remove(damagable);
}
}
}
2. 점프대
플레이어 점프 코드를 재사용할 수 있지 않을까 하여 매개변수로 점프력만 바꾸어 높이 점프할 수 있게 하였습니다.
3. 상호작용 가능한 물체 탐색 및 데이터 받기
캐릭터 앞쪽의 오브젝트 중 상호작용이 가능한 것이 있다면 안내 메세지를 띄우도록 하였습니다.
using UnityEngine;
using TMPro;
using System;
using UnityEngine.InputSystem;
public class Interaction : MonoBehaviour
{
public float checkRadius = 1; // 체크 영역의 반경
public float checkDelay = 0.2f; // 체크 딜레이가 너무 짧으면 최소 4프레임 주기로 해야 한다는 경고 주루룩 출현
[SerializeField] TextMeshProUGUI textInfo; // 정보를 표시할 텍스트 UI
public LayerMask layerMask; // Interaction 레이어만 포함하는 레이어마스크
private IInteractable curInteractable;
void Start()
{
// 반복적으로 상호가능 오브젝트 탐색
InvokeRepeating("SearchInteractables", 0, checkDelay);
}
void SearchInteractables()
{
// 해당 스크립트를 부착한 오브젝트가 캐릭터 앞쪽에 위치하여 캐릭터 앞의 상호작용 가능한 물체들을 탐색
// 구 형태로 레이를 쏘아 맞은 상호작용 가능한 오브젝트들
Collider[] hits = Physics.OverlapSphere(transform.position,checkRadius,layerMask);
// 플레이어 위치
Vector3 playerPos = GameManager.Instance.Player.transform.position;
// 맞은 오브젝트가 없다면: 정보를 표시하지 않음
if (hits.Length == 0)
{
curInteractable = null;
textInfo.text = "";
}
// 맞은 오브젝트가 있다면: 정보 표시
else
{
// 플레이어로부터 가장 가까운 상호작용 가능한 오브젝트가 0번에 오게끔 정렬
Array.Sort(hits, (a, b)
=> Vector3.SqrMagnitude(a.transform.position - playerPos).CompareTo(Vector3.SqrMagnitude(b.transform.position - playerPos)));
// 가장 가까운 상호작용 가능 오브젝트의 정보 출력
if (hits[0].TryGetComponent(out curInteractable))
{
textInfo.text = curInteractable.GetInfo();
}
}
}
// 상호작용 기능 발동
public void OnInteraction(InputValue inputValue)
{
if (inputValue.isPressed)
{
curInteractable?.OnInteract();
}
}
// 범위가 어떤지 보기 위한 디버그용 영역 표시
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawSphere(transform.position,checkRadius);
}
}