조개게임 완료 전

This commit is contained in:
2026-06-22 18:24:25 +09:00
parent 33bad1f50a
commit 5ef59f1c21
5 changed files with 189 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit.Interactables;
public class ClamBiteDetector : MonoBehaviour
{
@@ -14,17 +15,28 @@ public class ClamBiteDetector : MonoBehaviour
[Header("Bite Zone")]
[SerializeField] private Collider biteZoneCollider;
[Tooltip("조개 미션이 시작되었을 때만 물림 판정을 합니다.")]
[SerializeField] private bool missionActiveOnStart = false;
[Tooltip("조개가 닫히는 동안 이미 한 번 물렸으면 추가 판정을 막습니다.")]
[SerializeField] private bool biteOncePerClose = true;
[Header("Target Tags")]
[Header("Target Detection")]
[Tooltip("손 오브젝트에 붙일 태그입니다. 태그를 안 쓰면 XRHandMarker로도 판정합니다.")]
[SerializeField] private string handTag = "PlayerHand";
[Tooltip("기억의 조각 태그입니다. 단, 조각은 잡힌 상태일 때만 물림 대상으로 봅니다.")]
[SerializeField] private string fragmentTag = "MemoryFragment";
[Tooltip("기억의 조각은 플레이어가 잡고 있을 때만 물림 판정합니다.")]
[SerializeField] private bool biteFragmentOnlyWhenGrabbed = true;
[Header("Debug")]
[SerializeField] private bool showDebugLog = true;
private bool missionActive;
private bool hasBittenThisClose;
private readonly HashSet<Collider> collidersInside = new();
private void Awake()
@@ -46,6 +58,8 @@ private void Awake()
if (memoryFragment == null)
memoryFragment = FindFirstObjectByType<MemoryFragmentReset>();
missionActive = missionActiveOnStart;
}
private void OnEnable()
@@ -89,8 +103,34 @@ private void OnTriggerExit(Collider other)
collidersInside.Remove(other);
}
public void StartBiteMission()
{
missionActive = true;
hasBittenThisClose = false;
collidersInside.Clear();
if (showDebugLog)
Debug.Log("[ClamBiteDetector] 조개 미션 시작. 물림 판정 활성 준비.", this);
}
public void StopBiteMission()
{
missionActive = false;
hasBittenThisClose = false;
collidersInside.Clear();
if (biteZoneCollider != null)
biteZoneCollider.enabled = false;
if (showDebugLog)
Debug.Log("[ClamBiteDetector] 조개 미션 정지. 물림 판정 비활성.", this);
}
private void EnableBiteWindow()
{
if (!missionActive)
return;
hasBittenThisClose = false;
if (biteZoneCollider != null)
@@ -113,7 +153,7 @@ private void DisableBiteWindow()
collidersInside.Clear();
if (showDebugLog)
if (showDebugLog && missionActive)
Debug.Log("[ClamBiteDetector] 조개 물림 판정 OFF", this);
}
@@ -124,6 +164,9 @@ private void ResetBiteState()
private bool IsBiteWindowOpen()
{
if (!missionActive)
return false;
if (biteZoneCollider == null)
return false;
@@ -135,13 +178,16 @@ private void TryBite(Collider other)
if (other == null)
return;
if (!missionActive)
return;
if (biteOncePerClose && hasBittenThisClose)
return;
bool isHand = other.CompareTag(handTag) || other.GetComponentInParent<XRHandMarker>() != null;
bool isFragment = other.CompareTag(fragmentTag) || other.GetComponentInParent<MemoryFragmentReset>() != null;
bool isHand = IsHandCollider(other);
bool isGrabbedFragment = IsGrabbedMemoryFragment(other);
if (!isHand && !isFragment)
if (!isHand && !isGrabbedFragment)
return;
hasBittenThisClose = true;
@@ -157,4 +203,40 @@ private void TryBite(Collider other)
Debug.Log($"[ClamBiteDetector] 조개에게 물림. 데미지 {biteDamage}, 기억의 조각 리셋", this);
}
}
private bool IsHandCollider(Collider other)
{
if (other.CompareTag(handTag))
return true;
XRHandMarker marker = other.GetComponentInParent<XRHandMarker>();
return marker != null;
}
private bool IsGrabbedMemoryFragment(Collider other)
{
MemoryFragmentReset fragment = other.GetComponentInParent<MemoryFragmentReset>();
if (fragment == null)
{
if (!other.CompareTag(fragmentTag))
return false;
fragment = memoryFragment;
}
if (fragment == null)
return false;
XRGrabInteractable grab = fragment.GetComponent<XRGrabInteractable>();
if (grab == null)
return !biteFragmentOnlyWhenGrabbed;
if (biteFragmentOnlyWhenGrabbed)
return grab.isSelected;
return true;
}
}