Files
VRProject/Assets/_Scripts/PuzzleBlock.cs
ohgushiyuga f0df7736f4 codingmosaku
2026-07-23 16:30:29 +09:00

148 lines
4.5 KiB
C#
Raw Permalink 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 UnityEngine;
using UnityEngine.XR.Interaction.Toolkit.Interactables; // XR Toolkit用
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; }
[Header("スナップ(合体)位置の設定")]
[Tooltip("相手と合体する基準位置空のGameObjectを指定。未設定でも中心位置でスナップします")]
[SerializeField] private Transform snapPoint;
private PuzzleBlock nearbyPartner; // 近くにある結合対象のブロック
private bool isConnected = false; // 結合済みフラグ
// リセット用の初期座標・回転保持用
private Vector3 initialPosition;
private Quaternion initialRotation;
private Rigidbody rb;
private XRGrabInteractable grabInteractable;
private void Awake()
{
rb = GetComponent<Rigidbody>();
grabInteractable = GetComponent<XRGrabInteractable>();
// 初期スポーン位置・回転を記憶しておく
initialPosition = transform.position;
initialRotation = transform.rotation;
}
private void OnTriggerEnter(Collider other)
{
if (isConnected) return;
PuzzleBlock partner = other.GetComponentInParent<PuzzleBlock>();
if (partner != null && IsValidPartner(partner))
{
nearbyPartner = partner;
Debug.Log($"🧩 パートナー検知: {partner.Color} の {partner.ShapeType}");
}
}
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 == this.Color && partner.ShapeType != this.ShapeType;
}
public void OnReleased()
{
if (isConnected) return;
if (nearbyPartner != null)
{
ConnectToPartner(nearbyPartner);
}
}
private void ConnectToPartner(PuzzleBlock partner)
{
isConnected = true;
partner.isConnected = true;
// 1. 位置・回転のスナップ補正
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;
}
// 2. 物理VR掴み動作の完全ロック完成後に崩れないようにする
LockBlockState();
partner.LockBlockState();
Debug.Log($"🎉 マグネット合体成功! 色: {Color}");
// 3. バフ適用してCodingMode完了へ
string buffName = ConvertColorToBuffName(Color);
PlayerStatusManager.Instance.ApplyBuffsAndResume(buffName, buffName);
}
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()
{
isConnected = false;
nearbyPartner = null;
transform.position = initialPosition;
transform.rotation = initialRotation;
if (rb != null)
{
rb.isKinematic = false;
rb.linearVelocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
if (grabInteractable != null) grabInteractable.enabled = true;
}
public static void ResetAllBlocksInScene()
{
foreach (var block in FindObjectsByType<PuzzleBlock>(FindObjectsSortMode.None))
{
if (block != null) block.ResetBlock();
}
}
private string ConvertColorToBuffName(BlockColor color)
{
return color switch
{
BlockColor.Red => "AttackUp",
BlockColor.Blue => "DefenseUp",
BlockColor.Green => "Heal",
_ => "AttackUp"
};
}
}