68 lines
2.5 KiB
C#
68 lines
2.5 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
// "지정한 물건들을 전부 이 존 안으로 옮기기" 목표.
|
|
// 트리거 콜라이더가 붙은 존 오브젝트에 추가하고 물건들을 목록에 등록한다.
|
|
// 물건 쪽에 Rigidbody가 있어야 트리거 이벤트가 발생한다 (XRGrabInteractable이면 이미 있음).
|
|
[RequireComponent(typeof(Collider))]
|
|
public class MoveItemsToZoneObjective : MissionObjective
|
|
{
|
|
[Tooltip("이 존 안으로 옮겨야 하는 물건들 (씬 오브젝트 루트)")]
|
|
[SerializeField] private List<Transform> _requiredItems = new();
|
|
|
|
[Tooltip("들어온 개수가 바뀔 때마다 (현재 개수, 전체 개수) — 진행 UI 연결용")]
|
|
public UnityEvent<int, int> OnCountChanged;
|
|
|
|
[Tooltip("대사 텍스트에서 {키}로 진행 상황을 쓰려면 키 이름 지정 (값 예: \"3/5\"). 비우면 안 씀")]
|
|
[SerializeField] private string _dialogVariableKey;
|
|
|
|
private readonly HashSet<Transform> _inside = new();
|
|
|
|
public int Count => _inside.Count;
|
|
public int Total => _requiredItems.Count;
|
|
public override bool IsComplete => Count >= Total;
|
|
|
|
private void Awake()
|
|
{
|
|
var col = GetComponent<Collider>();
|
|
if (!col.isTrigger)
|
|
Debug.LogWarning($"[MoveItemsToZoneObjective] 콜라이더가 트리거가 아님: {name}");
|
|
}
|
|
|
|
private void Start() => Publish(); // UI/대사 변수 초기값 (0/N)
|
|
|
|
private void OnTriggerEnter(Collider other)
|
|
{
|
|
var item = FindRequiredItem(other);
|
|
if (item != null && _inside.Add(item)) Publish();
|
|
}
|
|
|
|
private void OnTriggerExit(Collider other)
|
|
{
|
|
var item = FindRequiredItem(other);
|
|
if (item != null && _inside.Remove(item)) Publish();
|
|
}
|
|
|
|
// 콜라이더에서 등록된 물건을 찾는다 (자식 콜라이더 대응 — 부모로 거슬러 올라가며 확인)
|
|
private Transform FindRequiredItem(Collider col)
|
|
{
|
|
var t = col.attachedRigidbody != null ? col.attachedRigidbody.transform : col.transform;
|
|
while (t != null)
|
|
{
|
|
if (_requiredItems.Contains(t)) return t;
|
|
t = t.parent;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void Publish()
|
|
{
|
|
_inside.RemoveWhere(t => t == null); // 파괴된 물건 정리
|
|
if (!string.IsNullOrEmpty(_dialogVariableKey))
|
|
DialogVariables.Set(_dialogVariableKey, $"{Count}/{Total}");
|
|
OnCountChanged?.Invoke(Count, Total);
|
|
RaiseChanged();
|
|
}
|
|
}
|