HPbarzissou

This commit is contained in:
ohgushiyuga
2026-08-27 17:59:06 +09:00
parent 52341100ed
commit 9864b95a91
48 changed files with 3379 additions and 19467 deletions

View File

@@ -1,44 +0,0 @@
using UnityEngine;
public class BossDebugController : MonoBehaviour
{
private BossController bossController;
private void Awake()
{
// 同一オブジェクトにあるBossControllerを自動取得
bossController = GetComponent<BossController>();
}
private void Update()
{
// ─── ★キーボードの『U(Ultimate)』キーを押したら強制発動 ───
if (Input.GetKeyDown(KeyCode.U))
{
TriggerDebugUltimate();
}
// ─── ついでにあると便利な機能:『S(Stun)』キーで即座にパリィスタン ───
if (Input.GetKeyDown(KeyCode.S))
{
TriggerDebugStun();
}
}
private void TriggerDebugUltimate()
{
if (bossController == null) return;
Debug.Log("🛠️ 【キーボードデバッグ】強制的に必殺技(天井ジャンプ)を発動します。");
bossController.PendingUltimate = true;
bossController.ChangeState<SpiderJumpToCeilingState>();
}
private void TriggerDebugStun()
{
if (bossController == null) return;
Debug.Log("🛡️ 【キーボードデバッグ】強制的にパリィスタン(チャンスタイム)を発動します。");
bossController.ChangeState<SpiderStunState>();
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: d2cd755b0c100204e833df85acb412e8

View File

@@ -49,6 +49,9 @@ public class BuffHandler
private void ExecuteHeal()
{
Debug.Log($"💚 HP回復バフ発動:回復量 {hpHealAmount}");
if (PlayerStatusManager.Instance != null)
{
PlayerStatusManager.Instance.Heal(hpHealAmount);
}
}
}

View File

@@ -18,7 +18,6 @@ public class EnemyAI : MonoBehaviour, IPauseable
[Header("攻撃設定")]
[SerializeField] private float attackRange = 1.5f;
[SerializeField] private float attackDamage = 10f;
[SerializeField] private float attackCooldown = 2.0f;
[SerializeField] private float telegraphDuration = 0.6f;
[SerializeField] private Collider rightHandCollider;

View File

@@ -0,0 +1,25 @@
using UnityEngine;
[RequireComponent(typeof(Collider))]
public class EnemyDamageHitbox : MonoBehaviour
{
[SerializeField] private float damageAmount = 15f;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
IDamageable player = other.GetComponentInParent<IDamageable>();
if (player != null)
{
DamageInfo info = new DamageInfo
{
amount = damageAmount,
hitPosition = transform.position,
punchDirection = transform.forward
};
player.TakeDamage(info);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cc0e815d758adf14f92abc78ef490f4b

View File

@@ -7,8 +7,10 @@ public class EnemyHealth : MonoBehaviour, IDamageable
[SerializeField] private float knockbackDuration = 0.5f;
public float CurrentHealth { get; private set; }
public float MaxHealth => maxHealth;
public bool IsDead { get; private set; }
public event Action<float, float> OnHealthChanged; // ★追加:HP変更イベント(現在HP, 最大HP)
public event Action<float> OnKnockbackRequested;
public event Action OnDeath;
@@ -26,6 +28,11 @@ public class EnemyHealth : MonoBehaviour, IDamageable
col = GetComponent<Collider>();
}
private void Start()
{
OnHealthChanged?.Invoke(CurrentHealth, maxHealth);
}
private void OnEnable()
{
if (enemyAI != null)
@@ -49,6 +56,7 @@ public class EnemyHealth : MonoBehaviour, IDamageable
if (IsDead) return;
CurrentHealth = Mathf.Max(0f, CurrentHealth - damageInfo.amount);
OnHealthChanged?.Invoke(CurrentHealth, maxHealth); // ★HP変更をUIに通知
if (CurrentHealth <= 0f)
{

View File

@@ -0,0 +1,74 @@
using UnityEngine;
using UnityEngine.UI;
public class EnemyHealthBar : MonoBehaviour
{
[Header("UI設定")]
[SerializeField] private Slider hpSlider;
[SerializeField] private EnemyHealth targetEnemyHealth;
[Header("追従設定")]
[Tooltip("敵の原点から頭上へどれだけ浮かせるか(メートル)")]
[SerializeField] private Vector3 offset = new Vector3(0, 2.0f, 0);
private Transform targetTransform;
private Transform mainCameraTransform;
private void Start()
{
// ターゲットのEnemyHealthを自動検索
if (targetEnemyHealth == null)
{
targetEnemyHealth = GetComponentInParent<EnemyHealth>();
}
if (targetEnemyHealth != null)
{
targetTransform = targetEnemyHealth.transform;
targetEnemyHealth.OnHealthChanged += UpdateHp;
targetEnemyHealth.OnDeath += HandleDeath;
UpdateHp(targetEnemyHealth.CurrentHealth, targetEnemyHealth.MaxHealth);
}
if (Camera.main != null)
{
mainCameraTransform = Camera.main.transform;
}
}
private void OnDestroy()
{
if (targetEnemyHealth != null)
{
targetEnemyHealth.OnHealthChanged -= UpdateHp;
targetEnemyHealth.OnDeath -= HandleDeath;
}
}
private void LateUpdate()
{
if (targetTransform == null || mainCameraTransform == null) return;
// 1. 敵の頭上に位置を追従
transform.position = targetTransform.position + offset;
// 2. 常にカメラの向きへ正対(ビルボード処理:鏡像反転を防ぐためカメラの向きと平行にする)
transform.forward = mainCameraTransform.forward;
}
private void UpdateHp(float current, float max)
{
if (hpSlider != null)
{
hpSlider.maxValue = max;
hpSlider.value = current;
}
}
private void HandleDeath()
{
// 敵が死んだらバーを即座に非表示
gameObject.SetActive(false);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1443ed714a8be8b47a421694985d521a

View File

@@ -1,58 +0,0 @@
using UnityEngine;
using UnityEngine.InputSystem;
public class InputManagerLR : MonoBehaviour
{
private static InputManagerLR instance;
[SerializeField] private InputActionAsset actionAsset;
private InputActionMap actionMap;
private InputAction primaryButtonR;
private InputAction secondaryButtonR;
private InputAction primaryButtonL;
private InputAction secondaryButtonL;
private void Awake()
{
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
instance = this;
DontDestroyOnLoad(gameObject);
if (actionAsset != null)
{
actionMap = actionAsset.FindActionMap("Test");
if (actionMap != null)
{
primaryButtonR = actionMap.FindAction("XR_PrimaryButtonR", throwIfNotFound: false);
primaryButtonL = actionMap.FindAction("XR_PrimaryButtonL", throwIfNotFound: false);
secondaryButtonR = actionMap.FindAction("XR_SecondaryButtonR", throwIfNotFound: false);
secondaryButtonL = actionMap.FindAction("XR_SecondaryButtonL", throwIfNotFound: false);
}
}
}
private void OnEnable() => actionMap?.Enable();
private void OnDisable() => actionMap?.Disable();
public static bool PrimaryButtonR() => instance?.primaryButtonR?.IsPressed() ?? false;
public static bool PrimaryButtonR_OnPress() => instance?.primaryButtonR?.WasPressedThisFrame() ?? false;
public static bool PrimaryButtonR_OnRelease() => instance?.primaryButtonR?.WasReleasedThisFrame() ?? false;
public static bool PrimaryButtonL() => instance?.primaryButtonL?.IsPressed() ?? false;
public static bool PrimaryButtonL_OnPress() => instance?.primaryButtonL?.WasPressedThisFrame() ?? false;
public static bool PrimaryButtonL_OnRelease() => instance?.primaryButtonL?.WasReleasedThisFrame() ?? false;
public static bool SecondaryButtonR() => instance?.secondaryButtonR?.IsPressed() ?? false;
public static bool SecondaryButtonR_OnPress() => instance?.secondaryButtonR?.WasPressedThisFrame() ?? false;
public static bool SecondaryButtonR_OnRelease() => instance?.secondaryButtonR?.WasReleasedThisFrame() ?? false;
public static bool SecondaryButtonL() => instance?.secondaryButtonL?.IsPressed() ?? false;
public static bool SecondaryButtonL_OnPress() => instance?.secondaryButtonL?.WasPressedThisFrame() ?? false;
public static bool SecondaryButtonL_OnRelease() => instance?.secondaryButtonL?.WasReleasedThisFrame() ?? false;
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 5fc595679af414674be369cd3d5bc765

View File

@@ -1,62 +0,0 @@
using UnityEngine;
public class ItemCountDown : MonoBehaviour
{
public GameObject gameObjectRestore; //ゲームオブフェクトの復帰する座標を指定する
private bool isGrabbed = false;
private bool isTouching = false;
public float grabItemTimeLimit = 5.0f; //ゲームオブジェクトの位置がリセットされるまでのタイマー
private float timer; //スクリプト内のタイマーに用いる変数
void Start()
{
timer = 0.0f;
}
public void GetGrab()
{
isGrabbed = true;
isTouching = true;
}
public void ExitGrab()
{
isTouching = false;
}
void Update()
{
//制限時間が0秒の場合は、位置のリセットを実行しない
if (grabItemTimeLimit != 0)
{
if (isGrabbed == true)
{
if (isTouching == false)
{
timer += Time.deltaTime;
if (timer > grabItemTimeLimit)
{
//ゲームオブジェクトの速度をリセット
var rigidbody = GetComponent<Rigidbody>();
rigidbody.linearVelocity = Vector3.zero;
//ゲームオブジェクトを指定位置に配置する
rigidbody.transform.position = gameObjectRestore.transform.position;
rigidbody.transform.rotation = gameObjectRestore.transform.rotation;
//ゲームオブジェクトは不動の状態に戻る
isGrabbed = false;
timer = 0.0f;
}
}
//プレイヤーが触っている場合はカウントダウンをリセット
else
{
timer = 0.0f;
}
}
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 45dd4c486e2a64ef5a8f38d756b9dc2d

View File

@@ -0,0 +1,64 @@
using UnityEngine;
using UnityEngine.UI;
public class PlayerHUD : MonoBehaviour
{
[Header("HP表示設定")]
[SerializeField] private Slider hpSlider;
[SerializeField] private Text hpText;
[Header("Codingゲージ表示設定")]
[SerializeField] private Slider gaugeSlider;
[SerializeField] private Text gaugeText;
private void Start()
{
if (PlayerStatusManager.Instance != null)
{
// 初期値の反映
UpdateHpUI(PlayerStatusManager.Instance.CurrentHp, PlayerStatusManager.Instance.MaxHp);
UpdateGaugeUI(PlayerStatusManager.Instance.CurrentGauge, PlayerStatusManager.Instance.MaxGauge);
// イベントの購読
PlayerStatusManager.Instance.OnHpChanged += UpdateHpUI;
PlayerStatusManager.Instance.OnGaugeChanged += UpdateGaugeUI;
}
}
private void OnDestroy()
{
if (PlayerStatusManager.Instance != null)
{
PlayerStatusManager.Instance.OnHpChanged -= UpdateHpUI;
PlayerStatusManager.Instance.OnGaugeChanged -= UpdateGaugeUI;
}
}
private void UpdateHpUI(float current, float max)
{
if (hpSlider != null)
{
hpSlider.maxValue = max;
hpSlider.value = current;
}
if (hpText != null)
{
hpText.text = $"HP: {Mathf.CeilToInt(current)} / {Mathf.CeilToInt(max)}";
}
}
private void UpdateGaugeUI(float current, float max)
{
if (gaugeSlider != null)
{
gaugeSlider.maxValue = max;
gaugeSlider.value = current;
}
if (gaugeText != null)
{
gaugeText.text = $"GAUGE: {Mathf.FloorToInt(current)}%";
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 00f8d88793224ea4a8c6af33c944a675

View File

@@ -1,39 +0,0 @@
using UnityEngine;
public class PlayerMove : MonoBehaviour
{
// パラメータ
public float moveSpeed = 5f; // 移動速度
public float gravity = -9.8f; // 重力加速度
public CharacterController controller; // 移動に使うCharacterController
// 演算用変数
private Vector3 velocity; // 加速度を保持する変数
private bool isGrounded; // 地面に着地しているかどうかのフラグ変数
// ゲーム中実行されるUpdate関数
void Update()
{
// 着地状態のチェック
isGrounded = controller.isGrounded;
// 着地している場合は落下速度をリセット
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f; // 地面に着いた場合、速度をリセット
}
// 入力の取得
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
// ローカル座標をワールド座標に変換して移動方向を計算
Vector3 moveDirection = transform.TransformDirection(new Vector3(h, 0, v)) * moveSpeed;
// 重力を加算
velocity.y += gravity * Time.deltaTime;
// 移動と重力を一度のcontroller.Moveで処理
controller.Move((moveDirection + velocity) * Time.deltaTime);
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 3c101f16cf16d4195ba45ae89a7f14d8

View File

@@ -1,37 +0,0 @@
using UnityEngine;
public class PlayerPOV : MonoBehaviour
{
// パラメータ
public Transform neck; // プレイヤーの首のTransformを指定
public float sensitivity = 2.0f; // マウス感度(視点の移動の速さを調整)
public float minVertical = -90.0f; // 視点の最小角度(縦の回転制限)
public float maxVertical = 90.0f; // 視点の最大角度(縦の回転制限)
// 演算用変数
private float rotationX = 0f; // 縦方向の回転角度(首の回転)
// ゲーム開始時に呼ばれる
void Start()
{
// カーソルを非表示&ロック
Cursor.lockState = CursorLockMode.Locked; // カーソルを画面中央に固定
Cursor.visible = false; // カーソルを非表示にする
}
// 毎フレーム実行される
void Update()
{
// マウス入力の取得
float mouseX = Input.GetAxis("Mouse X") * sensitivity; // 横のマウス移動量を取得し、感度で調整
float mouseY = Input.GetAxis("Mouse Y") * sensitivity; // 縦のマウス移動量を取得し、感度で調整
// Player(体)の回転(左右)
transform.Rotate(0, mouseX, 0); // プレイヤー(体)の左右の回転をマウスX方向の入力に合わせて行う
// Neck(首)の回転(上下)
rotationX -= mouseY; // マウスY方向の入力によって縦方向の回転を更新
rotationX = Mathf.Clamp(rotationX, minVertical, maxVertical); // 回転角度を指定された範囲に制限
neck.localRotation = Quaternion.Euler(rotationX, 0, 0); // 首の回転を設定。縦方向のみ回転させる
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 20e0bce59a58a401ca841697d32fb339

View File

@@ -1,10 +1,20 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.XR;
public class PlayerStatusManager : MonoBehaviour
public class PlayerStatusManager : MonoBehaviour, IDamageable
{
public static PlayerStatusManager Instance { get; private set; }
[Header("HP・ステータス設定")]
[SerializeField] private float maxHp = 100f;
[SerializeField] private float currentHp = 100f;
[Tooltip("被ダメージ後の無敵時間(秒)")]
[SerializeField] private float invincibilityDuration = 0.8f;
[Header("デバッグ設定")]
[SerializeField] private bool ignoreGaugeForDebug = true;
@@ -30,30 +40,30 @@ public class PlayerStatusManager : MonoBehaviour
[SerializeField] private BuffHandler buffHandler = new BuffHandler();
private float codingTimer;
private bool isInvincible;
public bool IsCodingMode { get; private set; }
public bool IsDead { get; private set; }
public float CurrentHp => currentHp;
public float MaxHp => maxHp;
public float CurrentGauge => currentGauge;
public float MaxGauge => maxGauge;
public BuffHandler Buffs => buffHandler;
public event Action<float, float> OnHpChanged;
public event Action<float, float> OnGaugeChanged;
public event Action OnDeath;
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
if (Instance == null) Instance = this;
else Destroy(gameObject);
currentHp = maxHp;
}
private void OnEnable()
{
SetActionsEnabled(true);
}
private void OnDisable()
{
SetActionsEnabled(false);
}
private void OnEnable() => SetActionsEnabled(true);
private void OnDisable() => SetActionsEnabled(false);
private void SetActionsEnabled(bool enable)
{
@@ -73,10 +83,14 @@ public class PlayerStatusManager : MonoBehaviour
private void Start()
{
if (codingModeUI != null) codingModeUI.SetActive(false);
OnHpChanged?.Invoke(currentHp, maxHp);
OnGaugeChanged?.Invoke(currentGauge, maxGauge);
}
private void Update()
{
if (IsDead) return;
CheckComboInput();
if (!IsCodingMode)
@@ -95,8 +109,85 @@ public class PlayerStatusManager : MonoBehaviour
public void AddGauge(float amount)
{
if (IsCodingMode) return;
if (IsCodingMode || IsDead) return;
currentGauge = Mathf.Clamp(currentGauge + amount, 0f, maxGauge);
OnGaugeChanged?.Invoke(currentGauge, maxGauge);
}
public void TakeDamage(DamageInfo damageInfo)
{
if (IsDead || isInvincible || IsCodingMode) return;
// 防御バフ適用(倍率を掛けて被ダメージを軽減)
float finalDamage = damageInfo.amount * buffHandler.CurrentDefenseMultiplier;
currentHp = Mathf.Max(0f, currentHp - finalDamage);
OnHpChanged?.Invoke(currentHp, maxHp);
Debug.Log($"💥 プレイヤー被ダメージ: {finalDamage:F1} (残HP: {currentHp:F1} / {maxHp})");
// コントローラーへの被弾振動フィードバック
TriggerDamageHaptics(0.6f, 0.15f);
if (currentHp <= 0f)
{
Die();
}
else
{
StartCoroutine(InvincibilityRoutine());
}
}
public void Heal(float amount)
{
if (IsDead) return;
currentHp = Mathf.Min(maxHp, currentHp + amount);
OnHpChanged?.Invoke(currentHp, maxHp);
Debug.Log($"💚 HP回復: +{amount} (現在HP: {currentHp} / {maxHp})");
}
private IEnumerator InvincibilityRoutine()
{
isInvincible = true;
yield return new WaitForSeconds(invincibilityDuration);
isInvincible = false;
}
private void Die()
{
if (IsDead) return;
IsDead = true;
Debug.LogError("☠️ プレイヤー死亡:GAME OVER");
OnDeath?.Invoke();
SetActionsEnabled(false);
if (WorldPauseManager.Instance != null)
{
WorldPauseManager.Instance.PauseWorld();
}
// 死亡後、2秒待って現在のシーンをリロード(再開)
StartCoroutine(GameOverRestartRoutine());
}
private IEnumerator GameOverRestartRoutine()
{
yield return new WaitForSecondsRealtime(2.5f);
if (WorldPauseManager.Instance != null)
{
WorldPauseManager.Instance.ResumeWorld();
}
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
private void TriggerDamageHaptics(float amplitude, float duration)
{
UnityEngine.XR.InputDevice left = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
if (left.isValid) left.SendHapticImpulse(0, amplitude, duration);
UnityEngine.XR.InputDevice right = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (right.isValid) right.SendHapticImpulse(0, amplitude, duration);
}
private void CheckComboInput()
@@ -131,7 +222,7 @@ public class PlayerStatusManager : MonoBehaviour
SetActionState(turnAction, false);
PuzzleBlock.ResetAllBlocksInScene();
if (WorldPauseManager.Instance != null)
{
WorldPauseManager.Instance.PauseWorld();
@@ -140,15 +231,15 @@ public class PlayerStatusManager : MonoBehaviour
if (codingModeUI != null) codingModeUI.SetActive(true);
}
public void ApplyBuffsAndResume(BuffType buff1, BuffType buff2)
// PlayerStatusManager.cs
public void ApplyBuffAndResume(BuffType buff)
{
if (successEffectPrefab != null && effectSpawnPoint != null)
{
Instantiate(successEffectPrefab, effectSpawnPoint.position, effectSpawnPoint.rotation);
}
buffHandler.ActivateBuff(buff1);
buffHandler.ActivateBuff(buff2);
buffHandler.ActivateBuff(buff);
ResumeWorldState(consumeGauge: true);
}
@@ -165,8 +256,14 @@ public class PlayerStatusManager : MonoBehaviour
SetActionState(moveAction, true);
SetActionState(turnAction, true);
PuzzleBlock.ResetAllBlocksInScene();
IsCodingMode = false;
if (codingModeUI != null) codingModeUI.SetActive(false);
if (consumeGauge) currentGauge = 0f;
if (consumeGauge)
{
currentGauge = 0f;
OnGaugeChanged?.Invoke(currentGauge, maxGauge);
}
}
}

View File

@@ -21,12 +21,16 @@ public class PuzzleBlock : MonoBehaviour
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;
@@ -35,11 +39,17 @@ public class PuzzleBlock : MonoBehaviour
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()
@@ -109,10 +119,11 @@ public class PuzzleBlock : MonoBehaviour
OnPuzzleCompleted?.Invoke(Color);
// PuzzleBlock.cs
BuffType buff = ConvertColorToBuffType(Color);
if (PlayerStatusManager.Instance != null)
{
PlayerStatusManager.Instance.ApplyBuffsAndResume(buff, buff);
PlayerStatusManager.Instance.ApplyBuffAndResume(buff);
}
}
@@ -129,32 +140,29 @@ public class PuzzleBlock : MonoBehaviour
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;
rb.isKinematic = initialIsKinematic;
rb.useGravity = initialUseGravity;
}
// 5. 掴み機能の再有効化
if (grabInteractable != null)
{
grabInteractable.enabled = true;

View File

@@ -1,30 +1,82 @@
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class TitleManager : MonoBehaviour
{
[Header("UI Buttons")]
[Header("VR入力設定")]
[Tooltip("スタート用の右手トリガー入力(例: XRI RightHand Interaction/Activate など)")]
[SerializeField] private InputActionProperty rightTriggerAction;
[Tooltip("スタート用の左手トリガー入力(任意)")]
[SerializeField] private InputActionProperty leftTriggerAction;
[Header("UI Buttons(任意)")]
[SerializeField] private Button startButton;
[SerializeField] private Button exitButton;
[Header("Scene Settings")]
[SerializeField] private string mainGameSceneName = "MainGameScene";
private bool isStarting = false;
private void Awake()
{
if (startButton != null) startButton.onClick.AddListener(OnStartButtonClicked);
if (startButton != null) startButton.onClick.AddListener(StartGame);
if (exitButton != null) exitButton.onClick.AddListener(OnExitButtonClicked);
}
private void OnStartButtonClicked()
private void OnEnable()
{
EnableAction(rightTriggerAction);
EnableAction(leftTriggerAction);
}
private void OnDisable()
{
DisableAction(rightTriggerAction);
DisableAction(leftTriggerAction);
}
private void EnableAction(InputActionProperty prop)
{
if (prop.action != null) prop.action.Enable();
}
private void DisableAction(InputActionProperty prop)
{
if (prop.action != null) prop.action.Disable();
}
private void Update()
{
if (isStarting) return;
// トリガー入力の判定(右手または左手)
if (IsTriggerPressed(rightTriggerAction) || IsTriggerPressed(leftTriggerAction))
{
StartGame();
}
}
private bool IsTriggerPressed(InputActionProperty prop)
{
if (prop.action == null) return false;
return prop.action.triggered || prop.action.ReadValue<float>() > 0.5f;
}
public void StartGame()
{
if (isStarting) return;
isStarting = true;
if (startButton != null) startButton.interactable = false;
Debug.Log("🚀 トリガー入力を検知:メインゲームシーンを読み込みます。");
StartCoroutine(LoadSceneRoutine());
}
private void OnExitButtonClicked()
public void OnExitButtonClicked()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;