@@ -193,8 +193,6 @@ Transform:
|
|||||||
m_CorrespondingSourceObject: {fileID: 400000, guid: d9d1fbfcf69364ffd8f9c6ade9ce90fe, type: 3}
|
m_CorrespondingSourceObject: {fileID: 400000, guid: d9d1fbfcf69364ffd8f9c6ade9ce90fe, type: 3}
|
||||||
m_PrefabInstance: {fileID: 13762580}
|
m_PrefabInstance: {fileID: 13762580}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
--- !u!1001 &48320566
|
--- !u!1001 &48320566
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -256,7 +254,6 @@ PrefabInstance:
|
|||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
m_AddedComponents: []
|
m_AddedComponents: []
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: 483f930f7cf5dca46a4974b3a5f3231a, type: 3}
|
m_SourcePrefab: {fileID: 100100000, guid: 483f930f7cf5dca46a4974b3a5f3231a, type: 3}
|
||||||
>>>>>>> 4d1dc01b620a200265bcb2d187a5e148601b69d5
|
|
||||||
--- !u!1001 &64373871
|
--- !u!1001 &64373871
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -6834,3 +6831,4 @@ SceneRoots:
|
|||||||
- {fileID: 581708908}
|
- {fileID: 581708908}
|
||||||
- {fileID: 73494051}
|
- {fileID: 73494051}
|
||||||
- {fileID: 1033763925}
|
- {fileID: 1033763925}
|
||||||
|
- {fileID: 48320566}
|
||||||
|
|||||||
@@ -5,10 +5,16 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
public class CodingModeGridManager : MonoBehaviour
|
public class CodingModeGridManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
[Header("スティック入力設定")]
|
||||||
|
[Tooltip("移動に使用するコントローラーのスティックのInputActionPropertyを指定してください")]
|
||||||
[SerializeField] private InputActionProperty thumbstickAction;
|
[SerializeField] private InputActionProperty thumbstickAction;
|
||||||
[SerializeField] private float inputThreshold = 0.5f; // スティックをどれくらい倒したら動くか
|
[Range(0.1f, 0.9f)] [SerializeField] private float inputThreshold = 0.5f; // スティックをどれくらい倒したら動くか
|
||||||
|
|
||||||
|
[Header("5x5 マス目(UI Image)の登録")]
|
||||||
|
[Tooltip("ヒエラルキー上の25個のマス目のImageコンポーネントを、左上(0)から右下(24)の順番で格納してください")]
|
||||||
[SerializeField] private List<Image> gridCells = new List<Image>();
|
[SerializeField] private List<Image> gridCells = new List<Image>();
|
||||||
|
|
||||||
|
[Header("マスの配色設定")]
|
||||||
[SerializeField] private Color colorNormal = Color.gray;
|
[SerializeField] private Color colorNormal = Color.gray;
|
||||||
[SerializeField] private Color colorPlayer = Color.green; // 自機(プレイヤー)
|
[SerializeField] private Color colorPlayer = Color.green; // 自機(プレイヤー)
|
||||||
[SerializeField] private Color colorGoal = Color.yellow; // ゴール
|
[SerializeField] private Color colorGoal = Color.yellow; // ゴール
|
||||||
@@ -46,6 +52,7 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
|
// ─── ★Time.timeScale = 0 でも動くスティック入力移動ロジック ───
|
||||||
if (thumbstickAction.action == null) return;
|
if (thumbstickAction.action == null) return;
|
||||||
|
|
||||||
Vector2 stickInput = thumbstickAction.action.ReadValue<Vector2>();
|
Vector2 stickInput = thumbstickAction.action.ReadValue<Vector2>();
|
||||||
@@ -62,36 +69,40 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
if (Mathf.Abs(stickInput.x) > Mathf.Abs(stickInput.y))
|
if (Mathf.Abs(stickInput.x) > Mathf.Abs(stickInput.y))
|
||||||
{
|
{
|
||||||
if (stickInput.x > inputThreshold) MovePlayer(1, 0);
|
// 横移動
|
||||||
else if (stickInput.x < -inputThreshold) MovePlayer(-1, 0);
|
if (stickInput.x > inputThreshold) MovePlayer(1, 0); // 右
|
||||||
|
else if (stickInput.x < -inputThreshold) MovePlayer(-1, 0); // 左
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (stickInput.y > inputThreshold) MovePlayer(0, -1);
|
// 縦移動 (UIの配列構造上、上に行くとYマイナス、下に行くとYプラスとなるよう計算)
|
||||||
else if (stickInput.y < -inputThreshold) MovePlayer(0, 1);
|
if (stickInput.y > inputThreshold) MovePlayer(0, -1); // 上
|
||||||
|
else if (stickInput.y < -inputThreshold) MovePlayer(0, 1); // 下
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 盤面を初期化し、ランダムに再配置する(PlayerStatusManagerから呼ばれる)
|
/// <summary>
|
||||||
|
/// 盤面を完全に初期化し、失敗ゾーンやチェックポイントをランダムに再配置する(PlayerStatusManagerから呼ばれる)
|
||||||
|
/// </summary>
|
||||||
public void ResetAndGenerateMinigame()
|
public void ResetAndGenerateMinigame()
|
||||||
{
|
{
|
||||||
accumulatedBuffs.Clear();
|
accumulatedBuffs.Clear();
|
||||||
|
|
||||||
// 全マスを通常マスとして初期化
|
// 1. 全マスを通常マスとして初期化
|
||||||
for (int i = 0; i < 25; i++)
|
for (int i = 0; i < 25; i++)
|
||||||
{
|
{
|
||||||
cellLogicArray[i] = CellType.Normal;
|
cellLogicArray[i] = CellType.Normal;
|
||||||
checkpointBuffTypeArray[i] = "";
|
checkpointBuffTypeArray[i] = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// スタートとゴールの固定配置、(余裕があればランダムに)
|
// 2. スタートとゴールの固定配置 (左上スタート、右下ゴール)
|
||||||
playerX = 0; playerY = 0;
|
playerX = 0; playerY = 0;
|
||||||
goalX = 4; goalY = 4;
|
goalX = 4; goalY = 4;
|
||||||
cellLogicArray[GetIndex(0, 0)] = CellType.Start;
|
cellLogicArray[GetIndex(0, 0)] = CellType.Start;
|
||||||
cellLogicArray[GetIndex(4, 4)] = CellType.Goal;
|
cellLogicArray[GetIndex(4, 4)] = CellType.Goal;
|
||||||
|
|
||||||
// 失敗ゾーンをランダムに5個配置
|
// 3. 失敗ゾーン(赤マス)をランダムに5個配置 (スタート・ゴールには被らせない)
|
||||||
int failZonesPlaced = 0;
|
int failZonesPlaced = 0;
|
||||||
while (failZonesPlaced < 5)
|
while (failZonesPlaced < 5)
|
||||||
{
|
{
|
||||||
@@ -103,7 +114,7 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// チェックポイントを3つのバフに対応させてランダムに3個配置
|
// 4. チェックポイント(青マス)を3つのバフに対応させてランダムに3個配置
|
||||||
string[] buffPool = { "AttackUp", "DefenseUp", "Heal" };
|
string[] buffPool = { "AttackUp", "DefenseUp", "Heal" };
|
||||||
int checkpointsPlaced = 0;
|
int checkpointsPlaced = 0;
|
||||||
while (checkpointsPlaced < 3)
|
while (checkpointsPlaced < 3)
|
||||||
@@ -117,10 +128,13 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. 視覚的(UIの色)に反映
|
||||||
RedrawGridGraphic();
|
RedrawGridGraphic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// プレイヤーの位置を指定された方向へ動かし、移動先のイベントを判定する
|
/// プレイヤーの位置を指定された方向へ動かし、移動先のイベントを判定する
|
||||||
|
/// </summary>
|
||||||
private void MovePlayer(int xDirection, int yDirection)
|
private void MovePlayer(int xDirection, int yDirection)
|
||||||
{
|
{
|
||||||
int nextX = Mathf.Clamp(playerX + xDirection, 0, 4);
|
int nextX = Mathf.Clamp(playerX + xDirection, 0, 4);
|
||||||
@@ -136,7 +150,7 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
int currentIndex = GetIndex(playerX, playerY);
|
int currentIndex = GetIndex(playerX, playerY);
|
||||||
CellType landedCell = cellLogicArray[currentIndex];
|
CellType landedCell = cellLogicArray[currentIndex];
|
||||||
|
|
||||||
Debug.Log("({playerX}, {playerY}) | マス属性: {landedCell}");
|
Debug.Log($"👾 カーソル移動: ({playerX}, {playerY}) | マス属性: {landedCell}");
|
||||||
|
|
||||||
// 移動先のマスに応じた処理
|
// 移動先のマスに応じた処理
|
||||||
switch (landedCell)
|
switch (landedCell)
|
||||||
@@ -150,7 +164,7 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
if (!accumulatedBuffs.Contains(buff))
|
if (!accumulatedBuffs.Contains(buff))
|
||||||
{
|
{
|
||||||
accumulatedBuffs.Add(buff);
|
accumulatedBuffs.Add(buff);
|
||||||
Debug.Log("バフコード抽出成功: [{buff}] を一時キープ中!");
|
Debug.Log($"💚 バフコード抽出成功: [{buff}] を一時キープ中!");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -158,10 +172,14 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
PlayerStatusManager.Instance.CompleteCodingMode(accumulatedBuffs); // クリア!バフ適用
|
PlayerStatusManager.Instance.CompleteCodingMode(accumulatedBuffs); // クリア!バフ適用
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 画面の色を最新状態に更新
|
||||||
RedrawGridGraphic();
|
RedrawGridGraphic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// 現在のロジック配列に基づいて、25個のUI Imageの色をまとめて上書き変更する
|
/// 現在のロジック配列に基づいて、25個のUI Imageの色をまとめて上書き変更する
|
||||||
|
/// </summary>
|
||||||
private void RedrawGridGraphic()
|
private void RedrawGridGraphic()
|
||||||
{
|
{
|
||||||
for (int y = 0; y < 5; y++)
|
for (int y = 0; y < 5; y++)
|
||||||
@@ -181,7 +199,7 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
case CellType.Goal: gridCells[index].color = colorGoal; break;
|
case CellType.Goal: gridCells[index].color = colorGoal; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// チェックポイントをすでに踏み抜いている場合は、獲得済みとして通常色に戻す演出
|
// チェックポイントをすでに踏み抜いている場合は、獲得済みとして通常色に戻す演出(任意)
|
||||||
if (cellLogicArray[index] == CellType.Checkpoint && accumulatedBuffs.Contains(checkpointBuffTypeArray[index]))
|
if (cellLogicArray[index] == CellType.Checkpoint && accumulatedBuffs.Contains(checkpointBuffTypeArray[index]))
|
||||||
{
|
{
|
||||||
gridCells[index].color = colorNormal * 0.7f; // 少し暗いグレーにして区別
|
gridCells[index].color = colorNormal * 0.7f; // 少し暗いグレーにして区別
|
||||||
@@ -189,7 +207,7 @@ public class CodingModeGridManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最後にプレイヤーのいるマスを自機の色で最優先に塗り替える
|
// 最後にプレイヤーのいるマスを「自機の色」で最優先に塗り替える
|
||||||
int playerIndex = GetIndex(playerX, playerY);
|
int playerIndex = GetIndex(playerX, playerY);
|
||||||
if (gridCells[playerIndex] != null)
|
if (gridCells[playerIndex] != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,23 +16,30 @@ public class EnemyAI : MonoBehaviour
|
|||||||
Stun // 怯み
|
Stun // 怯み
|
||||||
}
|
}
|
||||||
|
|
||||||
// 現在の状態
|
[Header("現在の状態")]
|
||||||
[SerializeField] private AIState currentState = AIState.Wander;
|
[SerializeField] private AIState currentState = AIState.Wander;
|
||||||
|
|
||||||
// 索敵設定
|
[Header("索敵設定")]
|
||||||
[SerializeField] private float detectionRange = 10f;
|
[SerializeField] private float detectionRange = 10f;
|
||||||
[SerializeField] private float loseRange = 15f;
|
[SerializeField] private float loseRange = 15f;
|
||||||
[SerializeField] private string playerTag = "Player";
|
[SerializeField] private string playerTag = "Player";
|
||||||
|
|
||||||
// 攻撃設定
|
[Header("攻撃設定")]
|
||||||
|
[Tooltip("この距離に近づいたら攻撃 (メートル)")]
|
||||||
[SerializeField] private float attackRange = 1.5f;
|
[SerializeField] private float attackRange = 1.5f;
|
||||||
|
[Tooltip("パンチの攻撃力")]
|
||||||
[SerializeField] private float attackDamage = 10f;
|
[SerializeField] private float attackDamage = 10f;
|
||||||
|
[Tooltip("一度攻撃が終了してから、次の攻撃を開始するまでの待ち時間 (秒)")]
|
||||||
[SerializeField] private float attackCooldown = 2.0f;
|
[SerializeField] private float attackCooldown = 2.0f;
|
||||||
[SerializeField] private float telegraphDuration = 0.6f; //攻撃ため時間
|
[Tooltip("攻撃の予兆時間 (秒)")]
|
||||||
|
[SerializeField] private float telegraphDuration = 0.6f;
|
||||||
[SerializeField] private Collider rightHandCollider;
|
[SerializeField] private Collider rightHandCollider;
|
||||||
[SerializeField] private float comboInterval = 0.2f; // 連続攻撃のインターバル
|
|
||||||
|
|
||||||
// 索敵設定
|
[Header("ループ攻撃の調整")]
|
||||||
|
[Tooltip("連続攻撃の間に挟む最低限のインターバル (秒)")]
|
||||||
|
[SerializeField] private float comboInterval = 0.2f;
|
||||||
|
|
||||||
|
[Header("徘徊(Wander)設定")]
|
||||||
[SerializeField] private float wanderRadius = 8f;
|
[SerializeField] private float wanderRadius = 8f;
|
||||||
[SerializeField] private float minWaitTime = 2f;
|
[SerializeField] private float minWaitTime = 2f;
|
||||||
[SerializeField] private float maxWaitTime = 4f;
|
[SerializeField] private float maxWaitTime = 4f;
|
||||||
@@ -70,7 +77,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
UpdateRotationOnAttack();
|
UpdateRotationOnAttack();
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI メインループ (思考ロジック)
|
#region AI メインループ (思考ロジック)
|
||||||
private IEnumerator AILoop()
|
private IEnumerator AILoop()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
@@ -113,8 +120,10 @@ public class EnemyAI : MonoBehaviour
|
|||||||
playerTransform = playerObj.transform;
|
playerTransform = playerObj.transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
// 徘徊状態の思考ロジック
|
#region 各ステートの固有行動
|
||||||
|
/// 【徘徊状態】の思考ロジック
|
||||||
private void WanderBehavior()
|
private void WanderBehavior()
|
||||||
{
|
{
|
||||||
if (playerTransform != null)
|
if (playerTransform != null)
|
||||||
@@ -126,7 +135,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
currentState = AIState.Chase;
|
currentState = AIState.Chase;
|
||||||
isWandering = false;
|
isWandering = false;
|
||||||
agent.ResetPath();
|
agent.ResetPath();
|
||||||
Debug.Log($"{gameObject.name}: プレイヤーを発見、追跡します。");
|
Debug.Log($"👁️ {gameObject.name}: プレイヤーを発見! 追跡します。");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,7 +147,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 追跡状態の思考ロジック
|
/// 【追跡状態】の思考ロジック
|
||||||
private void ChaseBehavior()
|
private void ChaseBehavior()
|
||||||
{
|
{
|
||||||
if (playerTransform == null)
|
if (playerTransform == null)
|
||||||
@@ -162,7 +171,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
{
|
{
|
||||||
currentState = AIState.Wander;
|
currentState = AIState.Wander;
|
||||||
agent.ResetPath();
|
agent.ResetPath();
|
||||||
Debug.Log($"{gameObject.name}: プレイヤーを見失った。");
|
Debug.Log($"❓ {gameObject.name}: プレイヤーを見失った。");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +182,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 攻撃状態の思考ロジック
|
/// 【攻撃状態】の思考ロジック
|
||||||
private void AttackBehavior()
|
private void AttackBehavior()
|
||||||
{
|
{
|
||||||
if (playerTransform == null)
|
if (playerTransform == null)
|
||||||
@@ -191,14 +200,16 @@ public class EnemyAI : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// クールダウン中でなければ攻撃コルーチンを実行(クールダウン中の場合は、Update内の処理によりプレイヤーの方向を向きながら待機)
|
// クールダウン中でなければ攻撃コルーチンを実行(クールダウン中の場合は、Update内の処理によりプレイヤーの方向を向きながら待機します)
|
||||||
if (!isCooldown)
|
if (!isCooldown)
|
||||||
{
|
{
|
||||||
StartCoroutine(PerformPunchAttack());
|
StartCoroutine(PerformPunchAttack());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
// エージェントの移動状態に応じてAnimatorのSpeedパラメータを更新する
|
#region アニメーション・回転の制御メソッド
|
||||||
|
/// エージェントの移動状態に応じてAnimatorのSpeedパラメータを更新する
|
||||||
private void UpdateAnimation()
|
private void UpdateAnimation()
|
||||||
{
|
{
|
||||||
float targetSpeed = 0f;
|
float targetSpeed = 0f;
|
||||||
@@ -213,7 +224,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
anim.SetFloat("Speed", targetSpeed, 0.1f, Time.deltaTime);
|
anim.SetFloat("Speed", targetSpeed, 0.1f, Time.deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 攻撃ステートの際、プレイヤーの方向へ滑らかに旋回させる
|
/// 攻撃ステートの際、プレイヤーの方向へ滑らかに旋回させる
|
||||||
private void UpdateRotationOnAttack()
|
private void UpdateRotationOnAttack()
|
||||||
{
|
{
|
||||||
if (currentState == AIState.Attack && playerTransform != null && !isKnockbacking && currentState != AIState.Stun)
|
if (currentState == AIState.Attack && playerTransform != null && !isKnockbacking && currentState != AIState.Stun)
|
||||||
@@ -228,6 +239,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
// ダメージを受けた際に、EnemyhHealthから呼び出されるのけぞり開始メソッド
|
// ダメージを受けた際に、EnemyhHealthから呼び出されるのけぞり開始メソッド
|
||||||
public void TriggerKnockback(float duration)
|
public void TriggerKnockback(float duration)
|
||||||
@@ -325,7 +337,8 @@ public class EnemyAI : MonoBehaviour
|
|||||||
StartCoroutine(AILoop());
|
StartCoroutine(AILoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 徘徊時のランダム移動を制御するコルーチン
|
#region 攻撃・移動のコルーチン処理
|
||||||
|
/// 徘徊時のランダム移動を制御するコルーチン
|
||||||
private IEnumerator WanderMoveRoutine()
|
private IEnumerator WanderMoveRoutine()
|
||||||
{
|
{
|
||||||
isWandering = true;
|
isWandering = true;
|
||||||
@@ -375,14 +388,14 @@ public class EnemyAI : MonoBehaviour
|
|||||||
isWandering = false;
|
isWandering = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 予兆から攻撃アニメーションのトリガーまでを制御するコルーチン
|
/// 予兆から攻撃アニメーションのトリガーまでを制御するコルーチン
|
||||||
private IEnumerator PerformPunchAttack()
|
private IEnumerator PerformPunchAttack()
|
||||||
{
|
{
|
||||||
isAttacking = true;
|
isAttacking = true;
|
||||||
isCooldown = true; // ここで攻撃フラグをロック
|
isCooldown = true; // ここで攻撃フラグをロックします
|
||||||
|
|
||||||
anim.SetTrigger("Telegraph");
|
anim.SetTrigger("Telegraph");
|
||||||
Debug.Log($"{gameObject.name}: 攻撃の溜め開始");
|
Debug.Log($"⚠️ {gameObject.name}: 攻撃の予兆(溜め)開始");
|
||||||
|
|
||||||
yield return new WaitForSeconds(telegraphDuration);
|
yield return new WaitForSeconds(telegraphDuration);
|
||||||
|
|
||||||
@@ -391,23 +404,25 @@ public class EnemyAI : MonoBehaviour
|
|||||||
anim.SetTrigger("Attack");
|
anim.SetTrigger("Attack");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 連続攻撃成功時の、クイックなクールダウン解除処理
|
/// 連続攻撃成功時の、クイックなクールダウン解除処理
|
||||||
private IEnumerator ResetCooldownQuickly()
|
private IEnumerator ResetCooldownQuickly()
|
||||||
{
|
{
|
||||||
yield return new WaitForSeconds(comboInterval);
|
yield return new WaitForSeconds(comboInterval);
|
||||||
isCooldown = false;
|
isCooldown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// コンボが途切れた際の、通常の攻撃クールダウン解除処理
|
/// コンボが途切れた際の、通常の攻撃クールダウン解除処理
|
||||||
private IEnumerator ResetCooldown()
|
private IEnumerator ResetCooldown()
|
||||||
{
|
{
|
||||||
// 指定された秒数待機する
|
// 指定された秒数待機する
|
||||||
yield return new WaitForSeconds(attackCooldown);
|
yield return new WaitForSeconds(attackCooldown);
|
||||||
isCooldown = false;
|
isCooldown = false;
|
||||||
Debug.Log($"{gameObject.name}: 攻撃クールダウンが終了しました。再攻撃可能です。");
|
Debug.Log($"✅ {gameObject.name}: 攻撃クールダウンが終了しました。再攻撃可能です。");
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
// 攻撃アニメーションのヒットフレームで実行されるヒット判定(Animation Eventから呼び出し)
|
#region アニメーションイベント(外部からのコールバック)
|
||||||
|
/// 攻撃アニメーションのヒットフレームで実行されるヒット判定(Animation Eventから呼び出し)
|
||||||
public void OnPunchHit()
|
public void OnPunchHit()
|
||||||
{
|
{
|
||||||
if (isKnockbacking || currentState == AIState.Stun) return;
|
if (isKnockbacking || currentState == AIState.Stun) return;
|
||||||
@@ -415,7 +430,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
SetFistCollider(true);
|
SetFistCollider(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recovery(硬直)アニメーションの終了時に実行される処理(Animation Eventから呼び出し)
|
/// Recovery(硬直)アニメーションの終了時に実行される処理(Animation Eventから呼び出し)
|
||||||
public void OnRecoveryEnd()
|
public void OnRecoveryEnd()
|
||||||
{
|
{
|
||||||
if(isKnockbacking || currentState == AIState.Stun) return;
|
if(isKnockbacking || currentState == AIState.Stun) return;
|
||||||
@@ -436,7 +451,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
if (distanceToPlayer <= attackRange)
|
if (distanceToPlayer <= attackRange)
|
||||||
{
|
{
|
||||||
StartCoroutine(ResetCooldownQuickly());
|
StartCoroutine(ResetCooldownQuickly());
|
||||||
Debug.Log($"{gameObject.name}: プレイヤーがまだ射程内です。連続攻撃を実行します。");
|
Debug.Log($"🔄 {gameObject.name}: プレイヤーがまだ射程内です。連続攻撃(コンボ)を実行します。");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -446,8 +461,10 @@ public class EnemyAI : MonoBehaviour
|
|||||||
Debug.Log($"🏃 {gameObject.name}: プレイヤーが離れたため追跡に戻ります。({attackCooldown}秒の攻撃クールダウンを適用)");
|
Debug.Log($"🏃 {gameObject.name}: プレイヤーが離れたため追跡に戻ります。({attackCooldown}秒の攻撃クールダウンを適用)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
// 指定された中心座標の範囲内から、NavMesh上の有効なランダム座標を取得する
|
#region ヘルパー・デバッグ用メソッド
|
||||||
|
/// 指定された中心座標の範囲内から、NavMesh上の有効なランダム座標を取得する
|
||||||
|
|
||||||
private void SetFistCollider(bool enabledState)
|
private void SetFistCollider(bool enabledState)
|
||||||
{
|
{
|
||||||
@@ -469,7 +486,7 @@ public class EnemyAI : MonoBehaviour
|
|||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
// エディタのSceneビューに索敵・攻撃範囲をギズモとして描画する
|
/// エディタのSceneビューに索敵・攻撃範囲をギズモとして描画する
|
||||||
private void OnDrawGizmosSelected()
|
private void OnDrawGizmosSelected()
|
||||||
{
|
{
|
||||||
// 索敵範囲(赤)
|
// 索敵範囲(赤)
|
||||||
@@ -484,4 +501,5 @@ public class EnemyAI : MonoBehaviour
|
|||||||
Gizmos.color = Color.blue;
|
Gizmos.color = Color.blue;
|
||||||
Gizmos.DrawWireSphere(transform.position, attackRange);
|
Gizmos.DrawWireSphere(transform.position, attackRange);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -6,18 +6,19 @@ public class PlayerStatusManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
public static PlayerStatusManager Instance { get; private set; }
|
public static PlayerStatusManager Instance { get; private set; }
|
||||||
|
|
||||||
// CodingModeスタート入力ボタン
|
[Header("Codingモード用 入力設定")]
|
||||||
[SerializeField] private InputActionProperty zlButtonAction;
|
[SerializeField] private InputActionProperty zlButtonAction;
|
||||||
[SerializeField] private InputActionProperty zrButtonAction;
|
[SerializeField] private InputActionProperty zrButtonAction;
|
||||||
|
|
||||||
// ゲージ設定
|
[Header("ゲージ設定")]
|
||||||
[SerializeField] private float maxGauge = 100f;
|
[SerializeField] private float maxGauge = 100f;
|
||||||
[SerializeField] private float currentGauge = 0f;
|
[SerializeField] private float currentGauge = 0f;
|
||||||
|
|
||||||
// 表示UI設定
|
[Header("表示UI設定")]
|
||||||
|
[Tooltip("ミニゲーム画面をまとめている親オブジェクトを指定してください")]
|
||||||
[SerializeField] private GameObject codingModeUI;
|
[SerializeField] private GameObject codingModeUI;
|
||||||
|
|
||||||
// バフパラメータ設定
|
[Header("バフパラメータ設定")]
|
||||||
[SerializeField] private float buffDuration = 10f;
|
[SerializeField] private float buffDuration = 10f;
|
||||||
[SerializeField] private float attackBuffMultiplier = 1.5f;
|
[SerializeField] private float attackBuffMultiplier = 1.5f;
|
||||||
[SerializeField] private float defenseBuffMultiplier = 0.5f;
|
[SerializeField] private float defenseBuffMultiplier = 0.5f;
|
||||||
@@ -70,7 +71,7 @@ public class PlayerStatusManager : MonoBehaviour
|
|||||||
if (isCodingMode) return;
|
if (isCodingMode) return;
|
||||||
currentGauge += amount;
|
currentGauge += amount;
|
||||||
currentGauge = Mathf.Clamp(currentGauge, 0f, maxGauge);
|
currentGauge = Mathf.Clamp(currentGauge, 0f, maxGauge);
|
||||||
Debug.Log($"共通ゲージ増加: {currentGauge} / {maxGauge}");
|
Debug.Log($"🔋 共通ゲージ増加: {currentGauge} / {maxGauge}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckComboInput()
|
private void CheckComboInput()
|
||||||
@@ -98,15 +99,18 @@ public class PlayerStatusManager : MonoBehaviour
|
|||||||
if (codingModeUI != null)
|
if (codingModeUI != null)
|
||||||
{
|
{
|
||||||
codingModeUI.SetActive(true);
|
codingModeUI.SetActive(true);
|
||||||
|
// ★新設:画面が開いた瞬間にミニゲームの盤面をランダム生成してリセットする
|
||||||
CodingModeGridManager gridManager = codingModeUI.GetComponentInChildren<CodingModeGridManager>();
|
CodingModeGridManager gridManager = codingModeUI.GetComponentInChildren<CodingModeGridManager>();
|
||||||
if (gridManager != null) gridManager.ResetAndGenerateMinigame();
|
if (gridManager != null) gridManager.ResetAndGenerateMinigame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ミニゲームクリア時:獲得したバフリストをすべて適用して現実世界を再開する
|
/// <summary>
|
||||||
|
/// ★ミニゲームクリア時:獲得したバフリストをすべて適用して現実世界を再開する
|
||||||
|
/// </summary>
|
||||||
public void CompleteCodingMode(List<string> earnedBuffs)
|
public void CompleteCodingMode(List<string> earnedBuffs)
|
||||||
{
|
{
|
||||||
Debug.Log("ハッキング成功! ミニゲームクリア!現実世界に復帰します。");
|
Debug.Log("💻 【ハッキング成功】 ミニゲームクリア!現実世界に復帰します。");
|
||||||
|
|
||||||
foreach (string buff in earnedBuffs)
|
foreach (string buff in earnedBuffs)
|
||||||
{
|
{
|
||||||
@@ -116,10 +120,12 @@ public class PlayerStatusManager : MonoBehaviour
|
|||||||
ResumeGameplay();
|
ResumeGameplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ミニゲーム失敗時:失敗ゾーン接触による強制終了処理(バフなしで復帰)
|
/// <summary>
|
||||||
|
/// ★ミニゲーム失敗時:失敗ゾーン接触による強制終了処理(バフなしで復帰)
|
||||||
|
/// </summary>
|
||||||
public void FailCodingMode()
|
public void FailCodingMode()
|
||||||
{
|
{
|
||||||
Debug.Log("ハッキング強制失敗 失敗ゾーンに接触しました。バフなしで復帰します。");
|
Debug.Log("🚨 【ハッキング強制失敗】 失敗ゾーンに接触しました。バフなしで復帰します。");
|
||||||
ResumeGameplay();
|
ResumeGameplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,14 +144,15 @@ public class PlayerStatusManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
case "AttackUp":
|
case "AttackUp":
|
||||||
attackBuffTimer = buffDuration;
|
attackBuffTimer = buffDuration;
|
||||||
Debug.Log($"攻撃力UPが適用されました。効果時間: {buffDuration}秒");
|
Debug.Log($"⚔️ 攻撃力UPが適用されました。効果時間: {buffDuration}秒");
|
||||||
break;
|
break;
|
||||||
case "DefenseUp":
|
case "DefenseUp":
|
||||||
defenseBuffTimer = buffDuration;
|
defenseBuffTimer = buffDuration;
|
||||||
Debug.Log($"防御力UPが適用されました。効果時間: {buffDuration}秒");
|
Debug.Log($"🛡️ 防御力UPが適用されました。効果時間: {buffDuration}秒");
|
||||||
break;
|
break;
|
||||||
case "Heal":
|
case "Heal":
|
||||||
Debug.Log($"HP回復が適用されました。回復量: {hpHealAmount}");
|
Debug.Log($"💚 HP回復が適用されました。回復量: {hpHealAmount}");
|
||||||
|
// ※将来の拡張:PlayerHealth.Instance.Heal(hpHealAmount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,13 +162,13 @@ public class PlayerStatusManager : MonoBehaviour
|
|||||||
if (attackBuffTimer > 0f)
|
if (attackBuffTimer > 0f)
|
||||||
{
|
{
|
||||||
attackBuffTimer -= Time.deltaTime;
|
attackBuffTimer -= Time.deltaTime;
|
||||||
if (attackBuffTimer <= 0f) Debug.Log("攻撃力UPバフの効果が終了しました。");
|
if (attackBuffTimer <= 0f) Debug.Log("⚔️ 攻撃力UPバフの効果が終了しました。");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defenseBuffTimer > 0f)
|
if (defenseBuffTimer > 0f)
|
||||||
{
|
{
|
||||||
defenseBuffTimer -= Time.deltaTime;
|
defenseBuffTimer -= Time.deltaTime;
|
||||||
if (defenseBuffTimer <= 0f) Debug.Log("防御力UPバフの効果が終了しました。");
|
if (defenseBuffTimer <= 0f) Debug.Log("🛡️ 防御力UPバフの効果が終了しました。");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,17 +10,18 @@ public class VRInputPunch : MonoBehaviour
|
|||||||
[SerializeField] private XRNode controllerNode = XRNode.RightHand;
|
[SerializeField] private XRNode controllerNode = XRNode.RightHand;
|
||||||
[SerializeField] private VRInputPoseDetector poseDetector;
|
[SerializeField] private VRInputPoseDetector poseDetector;
|
||||||
|
|
||||||
// 攻撃設定
|
[Header("攻撃(パンチ)設定")]
|
||||||
[SerializeField] private float minPunchSpeed = 2.0f; // パンチとして判定する最低速度 (m/s)
|
[SerializeField] private float minPunchSpeed = 2.0f; // パンチとして判定する最低速度 (m/s)
|
||||||
[SerializeField] private float damageMultiplier = 10.0f; // ダメージ倍率
|
[SerializeField] private float damageMultiplier = 10.0f; // ダメージ倍率
|
||||||
[SerializeField] private float hapticAmplitude = 0.5f; // 通常ヒットの振動の強さ
|
[SerializeField] private float hapticAmplitude = 0.5f; // 通常ヒットの振動の強さ
|
||||||
[SerializeField] private float hapticDuration = 0.1f; // 通常ヒットの振動の長さ
|
[SerializeField] private float hapticDuration = 0.1f; // 通常ヒットの振動の長さ
|
||||||
|
|
||||||
// パリィ設定
|
[Header("パリィ設定")]
|
||||||
[SerializeField] private float minParrySpeed = 1.0f; // パリィできるパンチとして判定する最低速度 (m/s)
|
[SerializeField] private float minParrySpeed = 1.0f; // パリィできるパンチとして判定する最低速度 (m/s)
|
||||||
[SerializeField] private float parryStunDuration = 3.0f; // スタン時間(秒)
|
[SerializeField] private float parryStunDuration = 3.0f; // スタン時間(秒)
|
||||||
[SerializeField] private float parryHapticAmplitude = 0.9f; // パリィ成功時の振動の強さ
|
[SerializeField] private float parryHapticAmplitude = 0.9f; // パリィ成功時の振動の強さ
|
||||||
[SerializeField] private float parryHapticDuration = 0.25f; // パリィ成功時の振動の長さ
|
[SerializeField] private float parryHapticDuration = 0.25f; // パリィ成功時の振動の長さ
|
||||||
|
// ─────────────────────────────────────────
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
@@ -52,29 +53,35 @@ public class VRInputPunch : MonoBehaviour
|
|||||||
Vector3 velocity = velocityAction.action.ReadValue<Vector3>();
|
Vector3 velocity = velocityAction.action.ReadValue<Vector3>();
|
||||||
float speed = velocity.magnitude;
|
float speed = velocity.magnitude;
|
||||||
|
|
||||||
// パリィ判定
|
//【パリィ判定】当たったオブジェクトが敵の拳だった場合
|
||||||
if (other.CompareTag("EnemyFist"))
|
if (other.CompareTag("EnemyFist"))
|
||||||
{
|
{
|
||||||
Debug.Log($"[パリィチェック] 敵の拳と接触。プレイヤーの手の速度: {speed:F2} m/s / 構え状態: {poseDetector.IsPosing}");
|
Debug.Log($"🛡️ [パリィチェック] 敵の拳と接触。プレイヤーの手の速度: {speed:F2} m/s / 構え状態: {poseDetector.IsPosing}");
|
||||||
|
|
||||||
|
// 条件:構え状態(IsPosing)である、もしくは、弾くための速度が一定以上出ている場合
|
||||||
if (poseDetector.IsPosing || speed >= minParrySpeed)
|
if (poseDetector.IsPosing || speed >= minParrySpeed)
|
||||||
{
|
{
|
||||||
|
// 敵の親オブジェクトからEnemyAIスクリプトを検索
|
||||||
EnemyAI enemyAI = other.GetComponentInParent<EnemyAI>();
|
EnemyAI enemyAI = other.GetComponentInParent<EnemyAI>();
|
||||||
if (enemyAI != null)
|
if (enemyAI != null)
|
||||||
{
|
{
|
||||||
|
// 敵の攻撃コンボを強制中断し、スタン状態にする
|
||||||
enemyAI.TriggerParryStun(parryStunDuration);
|
enemyAI.TriggerParryStun(parryStunDuration);
|
||||||
|
|
||||||
|
// パリィ成功用の強力な振動をプレイヤーに返す
|
||||||
TriggerHaptics(parryHapticAmplitude, parryHapticDuration);
|
TriggerHaptics(parryHapticAmplitude, parryHapticDuration);
|
||||||
|
|
||||||
Debug.Log($"ジャストパリィ成功! 敵の体勢を崩しました。スタン時間: {parryStunDuration}秒");
|
Debug.Log($"🛡️ 【ジャストパリィ成功!】 敵の体勢を崩しました。スタン時間: {parryStunDuration}秒");
|
||||||
return;
|
return; // パリィが成立した場合は以降のパンチ処理は行わない
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log("ガード(または速度不足):敵の攻撃は防いだが、弾き返せなかった。");
|
Debug.Log("🧱 ガード(または速度不足):敵の攻撃は防いだが、弾き返せなかった。");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
// パンチ攻撃の処理
|
// パンチ攻撃の処理
|
||||||
@@ -124,7 +131,7 @@ public class VRInputPunch : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 引数に応じて指定された強さと長さでコントローラーを振動させる
|
/// 引数に応じて指定された強さと長さでコントローラーを振動させる
|
||||||
private void TriggerHaptics(float amplitude, float duration)
|
private void TriggerHaptics(float amplitude, float duration)
|
||||||
{
|
{
|
||||||
UnityEngine.XR.InputDevice device = InputDevices.GetDeviceAtXRNode(controllerNode);
|
UnityEngine.XR.InputDevice device = InputDevices.GetDeviceAtXRNode(controllerNode);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
// World Space Canvas をプレイヤーの真正面に移動させ、開いている間はプレイヤーの視点に滑らかに追従させるスクリプト
|
||||||
public class VRUIDoorFaceFollow : MonoBehaviour
|
public class VRUIDoorFaceFollow : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] private Transform vrCameraTransform;
|
[SerializeField] private Transform vrCameraTransform;
|
||||||
|
|
||||||
//配置・追従のパラメータ
|
[Header("配置・追従のパラメータ")]
|
||||||
[SerializeField] private float forwardDistance = 0.5f;
|
[SerializeField] private float forwardDistance = 0.5f;
|
||||||
[SerializeField] private float heightOffset = -0.1f;
|
[SerializeField] private float heightOffset = -0.1f;
|
||||||
[SerializeField] private float followSpeed = 5.0f;
|
[SerializeField] private float followSpeed = 5.0f;
|
||||||
@@ -21,15 +22,15 @@ public class VRUIDoorFaceFollow : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time.timeScale = 0 の間でも動作させるため、カメラ移動の後に実行される LateUpdate を使用
|
// 全体の時間が止まっている(Time.timeScale = 0)間でも動作させるため、カメラ移動の後に実行される LateUpdate を使用します
|
||||||
private void LateUpdate()
|
private void LateUpdate()
|
||||||
{
|
{
|
||||||
if (vrCameraTransform == null) return;
|
if (vrCameraTransform == null) return;
|
||||||
|
|
||||||
// UI画面が有効化された最初のフレームの処理
|
// このオブジェクト(UI画面)が有効化された「最初のフレーム」の処理
|
||||||
if (!wasActiveLastFrame)
|
if (!wasActiveLastFrame)
|
||||||
{
|
{
|
||||||
// 開いた瞬間は、プレイヤーの今の向きの完全な正面に瞬間移動させる(遅れてついてくるのを防ぐため)
|
// 開いた瞬間は、プレイヤーの今の向きの「完全な正面」に瞬間移動させる(遅れてついてくるのを防ぐため)
|
||||||
SetInitialPosition();
|
SetInitialPosition();
|
||||||
wasActiveLastFrame = true;
|
wasActiveLastFrame = true;
|
||||||
return;
|
return;
|
||||||
@@ -45,7 +46,7 @@ public class VRUIDoorFaceFollow : MonoBehaviour
|
|||||||
wasActiveLastFrame = false;
|
wasActiveLastFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 画面が開いた瞬間に、プレイヤーの正面の正しい位置・向きに強制配置する
|
/// 画面が開いた瞬間に、プレイヤーの正面の正しい位置・向きに強制配置する
|
||||||
private void SetInitialPosition()
|
private void SetInitialPosition()
|
||||||
{
|
{
|
||||||
// カメラの位置から、カメラが向いている正面方向に一定距離進んだ座標を計算
|
// カメラの位置から、カメラが向いている正面方向に一定距離進んだ座標を計算
|
||||||
@@ -60,7 +61,7 @@ public class VRUIDoorFaceFollow : MonoBehaviour
|
|||||||
transform.Rotate(0, 180, 0);
|
transform.Rotate(0, 180, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// プレイヤーが首を動かしたり移動したりした際、画面を滑らかについてこさせる
|
/// プレイヤーが首を動かしたり移動したりした際、画面を滑らかについてこさせる
|
||||||
private void SmoothFollowPlayer()
|
private void SmoothFollowPlayer()
|
||||||
{
|
{
|
||||||
// 目的地(目標座標)の計算
|
// 目的地(目標座標)の計算
|
||||||
|
|||||||
Reference in New Issue
Block a user