Files
VRProject/Assets/_Scripts/PuzzleBlock.cs
ohgushiyuga 52341100ed otamesi
2026-08-27 12:51:15 +09:00

195 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Interactables;
public enum BlockColor { Red, Blue, Green }
public enum BlockShapeType { TShape, CShape }
public class PuzzleBlock : MonoBehaviour
{
[field: SerializeField] public BlockColor Color { get; private set; }
[field: SerializeField] public BlockShapeType ShapeType { get; private set; }
[SerializeField] private Transform snapPoint;
public static event Action<BlockColor> OnPuzzleCompleted;
private static readonly HashSet<PuzzleBlock> allBlocks = new HashSet<PuzzleBlock>();
private PuzzleBlock nearbyPartner;
private bool isConnected;
// ★ワールド情報ではなく「親階層」と「ローカル情報」を記憶
private Transform initialParent;
private Vector3 initialLocalPosition;
private Quaternion initialLocalRotation;
private Vector3 initialLocalScale;
private Rigidbody rb;
private XRGrabInteractable grabInteractable;
private void Awake()
{
rb = GetComponent<Rigidbody>();
grabInteractable = GetComponent<XRGrabInteractable>();
// ★開始時の「親」と「ローカル座標・回転・スケール」を保持
initialParent = transform.parent;
initialLocalPosition = transform.localPosition;
initialLocalRotation = transform.localRotation;
initialLocalScale = transform.localScale;
}
private void OnEnable()
{
allBlocks.Add(this);
}
private void OnDisable()
{
allBlocks.Remove(this);
}
private void OnTriggerEnter(Collider other)
{
if (isConnected) return;
PuzzleBlock partner = other.GetComponentInParent<PuzzleBlock>();
if (partner != null && IsValidPartner(partner))
{
nearbyPartner = partner;
}
}
private void OnTriggerExit(Collider other)
{
PuzzleBlock partner = other.GetComponentInParent<PuzzleBlock>();
if (partner == nearbyPartner)
{
nearbyPartner = null;
}
}
private bool IsValidPartner(PuzzleBlock partner)
{
if (partner == null || partner.isConnected) return false;
return partner.Color == Color && partner.ShapeType != ShapeType;
}
public void OnReleased()
{
if (isConnected) return;
if (nearbyPartner != null)
{
ConnectToPartner(nearbyPartner);
}
}
private void ConnectToPartner(PuzzleBlock partner)
{
isConnected = true;
partner.isConnected = true;
if (snapPoint != null && partner.snapPoint != null)
{
transform.position = partner.snapPoint.position;
transform.rotation = partner.snapPoint.rotation;
}
else
{
transform.position = partner.transform.position;
transform.rotation = partner.transform.rotation;
}
LockBlockState();
partner.LockBlockState();
OnPuzzleCompleted?.Invoke(Color);
BuffType buff = ConvertColorToBuffType(Color);
if (PlayerStatusManager.Instance != null)
{
PlayerStatusManager.Instance.ApplyBuffsAndResume(buff, buff);
}
}
private void LockBlockState()
{
if (rb != null)
{
rb.linearVelocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
rb.isKinematic = true;
}
if (grabInteractable != null) grabInteractable.enabled = false;
}
public void ResetBlock()
{
// 1. 手で掴んでいる場合は手離し処理
ForceDrop();
isConnected = false;
nearbyPartner = null;
// 2. ★親オブジェクト(Canvas)の子へ戻す
if (initialParent != null && transform.parent != initialParent)
{
transform.SetParent(initialParent, false);
}
// 3. ★Canvas内のローカル位置・回転・スケールを完全復元
transform.localPosition = initialLocalPosition;
transform.localRotation = initialLocalRotation;
transform.localScale = initialLocalScale;
// 4. 物理状態の再初期化
if (rb != null)
{
rb.isKinematic = false;
rb.linearVelocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
// 5. 掴み機能の再有効化
if (grabInteractable != null)
{
grabInteractable.enabled = true;
}
}
private void ForceDrop()
{
if (grabInteractable == null || !grabInteractable.isSelected) return;
if (grabInteractable.interactionManager != null && grabInteractable.firstInteractorSelecting != null)
{
grabInteractable.interactionManager.SelectExit(grabInteractable.firstInteractorSelecting, grabInteractable);
}
}
public static void ResetAllBlocksInScene()
{
foreach (var block in allBlocks)
{
if (block != null)
{
block.ResetBlock();
}
}
}
private BuffType ConvertColorToBuffType(BlockColor color)
{
return color switch
{
BlockColor.Red => BuffType.AttackUp,
BlockColor.Blue => BuffType.DefenseUp,
BlockColor.Green => BuffType.Heal,
_ => BuffType.AttackUp
};
}
}