using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using UnityEngine.XR.Interaction.Toolkit.Interactors; public class CodingModeManager : MonoBehaviour { [Header("ソケットスロットの設定")] [Tooltip("台座に配置した Slot_A の XRSocketInteractor を指定してください")] [SerializeField] private XRSocketInteractor socketA; [Tooltip("台座に配置した Slot_B の XRSocketInteractor を指定してください")] [SerializeField] private XRSocketInteractor socketB; [Header("XR Interaction Toolkit 移動系コンポーネント")] [Tooltip("Continuous Move Provider などの移動スクリプトをアタッチ")] [SerializeField] private Behaviour moveProvider; [Tooltip("Snap Turn Provider や Continuous Turn Provider などの旋回スクリプトをアタッチ")] [SerializeField] private Behaviour turnProvider; public bool IsCodingModeActive { get; private set; } = false; private void OnEnable() { // ソケットにオブジェクトが「ハメ込まれた瞬間」のイベントを登録 if (socketA != null) socketA.selectEntered.AddListener(OnSocketAEntered); if (socketB != null) socketB.selectEntered.AddListener(OnSocketBEntered); } private void OnDisable() { // イベントの登録解除 if (socketA != null) socketA.selectEntered.RemoveListener(OnSocketAEntered); if (socketB != null) socketB.selectEntered.RemoveListener(OnSocketBEntered); } // Slot_A に何かがハメ込まれた時のコールバック private void OnSocketAEntered(SelectEnterEventArgs args) { CheckPuzzleCompletion(); } // Slot_B に何かがハメ込まれた時のコールバック private void OnSocketBEntered(SelectEnterEventArgs args) { CheckPuzzleCompletion(); } private void CheckPuzzleCompletion() { if (socketA == null || socketB == null) return; // 両方のソケットがオブジェクトを保持(hasSelection)しているか確認 if (socketA.hasSelection && socketB.hasSelection) { // ハメ込まれているオブジェクト(Interactable)を取得 var objA = socketA.firstInteractableSelected; var objB = socketB.firstInteractableSelected; if (objA != null && objB != null) { // オブジェクトの名前から、どのバフ四角形かを判別する文字列を抽出 string buff1 = GetBuffNameFromObjectName(objA.transform.gameObject.name); string buff2 = GetBuffNameFromObjectName(objB.transform.gameObject.name); Debug.Log($"💻 パズル連結完了! 検出されたコンボ: [{buff1}] + [{buff2}]"); ClearSockets(); // PlayerStatusManagerにバフを適用させ、時間停止を解除してプレイ画面に戻る if (PlayerStatusManager.Instance != null) { //PlayerStatusManager.Instance.ApplyBuffsAndResume(buff1, buff2); } } } } private string GetBuffNameFromObjectName(string objName) { if (objName.Contains("AttackUp")) return "AttackUp"; if (objName.Contains("DefenseUp")) return "DefenseUp"; if (objName.Contains("Heal")) return "Heal"; return "Unknown"; } private void ClearSockets() { if (socketA.firstInteractableSelected != null) { socketA.firstInteractableSelected.transform.position = transform.position + (transform.forward * -0.2f); } if (socketB.firstInteractableSelected != null) { socketB.firstInteractableSelected.transform.position = transform.position + (transform.forward * -0.2f) + (transform.right * 0.1f); } } public void ToggleCodingMode() { IsCodingModeActive = !IsCodingModeActive; // CodingModeが有効(true)なら、enabled を false にして足止めする if (moveProvider != null) moveProvider.enabled = !IsCodingModeActive; if (turnProvider != null) turnProvider.enabled = !IsCodingModeActive; Debug.Log($"💻 CodingMode: {(IsCodingModeActive ? "ON (移動・旋回を一時ロック)" : "OFF (移動解禁)")}"); } }