203 lines
5.4 KiB
C#
203 lines
5.4 KiB
C#
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 bool initialIsKinematic;
|
|
private bool initialUseGravity;
|
|
|
|
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;
|
|
|
|
// ★初期状態の重力・キネマティック設定を保持
|
|
if (rb != null)
|
|
{
|
|
initialIsKinematic = rb.isKinematic;
|
|
initialUseGravity = rb.useGravity;
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
// PuzzleBlock.cs
|
|
BuffType buff = ConvertColorToBuffType(Color);
|
|
if (PlayerStatusManager.Instance != null)
|
|
{
|
|
PlayerStatusManager.Instance.ApplyBuffAndResume(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()
|
|
{
|
|
ForceDrop();
|
|
|
|
isConnected = false;
|
|
nearbyPartner = null;
|
|
|
|
if (initialParent != null && transform.parent != initialParent)
|
|
{
|
|
transform.SetParent(initialParent, false);
|
|
}
|
|
|
|
transform.localPosition = initialLocalPosition;
|
|
transform.localRotation = initialLocalRotation;
|
|
transform.localScale = initialLocalScale;
|
|
|
|
// ★修正:初期設定(記憶した値)へ正確に復元
|
|
if (rb != null)
|
|
{
|
|
rb.linearVelocity = Vector3.zero;
|
|
rb.angularVelocity = Vector3.zero;
|
|
rb.isKinematic = initialIsKinematic;
|
|
rb.useGravity = initialUseGravity;
|
|
}
|
|
|
|
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
|
|
};
|
|
}
|
|
} |