using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; // "지정한 물건들을 전부 이 존 안으로 옮기기" 목표. // 트리거 콜라이더가 붙은 존 오브젝트에 추가하고 물건들을 목록에 등록한다. // 물건 쪽에 Rigidbody가 있어야 트리거 이벤트가 발생한다 (XRGrabInteractable이면 이미 있음). [RequireComponent(typeof(Collider))] public class MoveItemsToZoneObjective : MissionObjective { [Tooltip("이 존 안으로 옮겨야 하는 물건들 (씬 오브젝트 루트)")] [SerializeField] private List _requiredItems = new(); [Tooltip("들어온 개수가 바뀔 때마다 (현재 개수, 전체 개수) — 진행 UI 연결용")] public UnityEvent OnCountChanged; [Tooltip("대사 텍스트에서 {키}로 진행 상황을 쓰려면 키 이름 지정 (값 예: \"3/5\"). 비우면 안 씀")] [SerializeField] private string _dialogVariableKey; private readonly HashSet _inside = new(); public int Count => _inside.Count; public int Total => _requiredItems.Count; public override bool IsComplete => Count >= Total; private void Awake() { var col = GetComponent(); 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(); } }