feat(): 大量更新
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec826b79cbc40da479bcc7969404880e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,10 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Share;
|
||||
namespace Card
|
||||
{
|
||||
public class CardContext
|
||||
{
|
||||
public ICharacter Player;
|
||||
public ICharacter Target;
|
||||
}
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Card
|
||||
{
|
||||
public static class EffectHandler
|
||||
{
|
||||
public static void Execute(EffectData effect, CardContext context)
|
||||
{
|
||||
switch (effect.type)
|
||||
{
|
||||
case EffectType.Damage:
|
||||
context.Target.TakeDamage(effect.value);
|
||||
break;
|
||||
|
||||
case EffectType.Heal:
|
||||
context.Target.Heal(effect.value);
|
||||
break;
|
||||
|
||||
case EffectType.DrawCard:
|
||||
context.Player.Draw(effect.value);
|
||||
break;
|
||||
|
||||
case EffectType.AddBuff:
|
||||
//TODO:context.Target.AddBuff(effect.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.LogWarning($"未知效果类型: {effect.type}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,7 +2,6 @@
|
||||
"name": "Core",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:9e4105fe56ff4b1789a1683a3c08d507",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 656856e514875b444af5c8db9035beea
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
3
Assets/Script/Core/Interface.meta
Normal file
3
Assets/Script/Core/Interface.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f02de2f72561440b862be76a712a53a6
|
||||
timeCreated: 1760448092
|
16
Assets/Script/Core/Interface/IInputManager.cs
Normal file
16
Assets/Script/Core/Interface/IInputManager.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public interface IInputManager
|
||||
{
|
||||
public Vector2 Move { get; }
|
||||
public Vector2 Look { get; }
|
||||
public bool JumpPressed { get; }
|
||||
public bool PausePressed { get; }
|
||||
public bool InteractPressed { get; }
|
||||
public void SetCursorState(bool visible, CursorLockMode lockMode);
|
||||
public void SetInputForLook(bool enabled);
|
||||
public void SetInputForMove(bool enabled);
|
||||
}
|
||||
}
|
3
Assets/Script/Core/Interface/IInputManager.cs.meta
Normal file
3
Assets/Script/Core/Interface/IInputManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b077e0f59a474f5a981770fae92ed42f
|
||||
timeCreated: 1760447509
|
@@ -25,6 +25,13 @@ namespace Core
|
||||
|
||||
private Dictionary<UILayer, Transform> layerRoots = new Dictionary<UILayer, Transform>();
|
||||
private Dictionary<string, UIBase> openedUIs = new Dictionary<string, UIBase>();
|
||||
|
||||
private IInputManager inputManager;
|
||||
|
||||
public void RegisterInputManager(IInputManager inputMgr)
|
||||
{
|
||||
inputManager = inputMgr;
|
||||
}
|
||||
|
||||
public void RegisterLayer(UILayer layer, Transform root)
|
||||
{
|
||||
@@ -122,18 +129,19 @@ namespace Core
|
||||
|
||||
private void UpdateCursorState()
|
||||
{
|
||||
if(inputManager == null) return;
|
||||
bool shouldLockCursor = !IsHasNonBackgroundUIActive; //&& !isInMainMenu; // 仅在没有非Background UI且不在主菜单时锁定鼠标
|
||||
if (shouldLockCursor)
|
||||
{
|
||||
InputManager.Instance.SetCursorState(false, CursorLockMode.Locked);
|
||||
inputManager.SetCursorState(false, CursorLockMode.Locked);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputManager.Instance.SetCursorState(true, CursorLockMode.None);
|
||||
inputManager.SetCursorState(true, CursorLockMode.None);
|
||||
|
||||
}
|
||||
InputManager.Instance.SetInputForLook(shouldLockCursor);
|
||||
InputManager.Instance.SetInputForMove(shouldLockCursor);
|
||||
inputManager.SetInputForLook(shouldLockCursor);
|
||||
inputManager.SetInputForMove(shouldLockCursor);
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay.meta
Normal file
3
Assets/Script/Gameplay.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6da45fd756c6481b8c0cffce4915e971
|
||||
timeCreated: 1760444989
|
@@ -1,6 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Card
|
||||
namespace Gameplay
|
||||
{
|
||||
public class Card
|
||||
{
|
3
Assets/Script/Gameplay/Card/CardBook.meta
Normal file
3
Assets/Script/Gameplay/Card/CardBook.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37e71088bd934b78aa07c7a76b7e5d07
|
||||
timeCreated: 1760422523
|
48
Assets/Script/Gameplay/Card/CardBook/CardBook.cs
Normal file
48
Assets/Script/Gameplay/Card/CardBook/CardBook.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay
|
||||
{
|
||||
public class CardBook
|
||||
{
|
||||
public CardBookData Data;
|
||||
public CardSlot[] Slots;
|
||||
public CardSlot[] Spares;
|
||||
|
||||
public CardBook(CardBookData data)
|
||||
{
|
||||
Data = data;
|
||||
Slots = new CardSlot[Data.SlotCount];
|
||||
Spares = new CardSlot[Data.SpareCount];
|
||||
for (int i = 0; i < Slots.Length; i++)
|
||||
{
|
||||
Slots[i] = new CardSlot();
|
||||
}
|
||||
for (int i = 0; i < Spares.Length; i++)
|
||||
{
|
||||
Spares[i] = new CardSlot();
|
||||
}
|
||||
}
|
||||
|
||||
// Get all cards in the card book,and not Spares
|
||||
public Card[] GetCards()
|
||||
{
|
||||
var cards = new Card[Slots.Length + Spares.Length];
|
||||
for (int i = 0; i < Slots.Length; i++)
|
||||
{
|
||||
cards[i] = Slots[i].StoredCard;
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
|
||||
public Card[] GetSpareCards()
|
||||
{
|
||||
var cards = new Card[Spares.Length + Spares.Length];
|
||||
for (int i = 0; i < Spares.Length; i++)
|
||||
{
|
||||
cards[i] = Spares[i].StoredCard;
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Card/CardBook/CardBook.cs.meta
Normal file
3
Assets/Script/Gameplay/Card/CardBook/CardBook.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4bb8bfb17c6a4eaa88954871942ee72d
|
||||
timeCreated: 1760422530
|
12
Assets/Script/Gameplay/Card/CardBook/CardBookData.cs
Normal file
12
Assets/Script/Gameplay/Card/CardBook/CardBookData.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay
|
||||
{
|
||||
[CreateAssetMenu(fileName = "CardBookData", menuName = "ScriptableObject/CardBookData", order = 1)]
|
||||
public class CardBookData : ScriptableObject
|
||||
{
|
||||
public int SlotCount;
|
||||
public int SpareCount;
|
||||
public int MaxLoopCount;
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54f1f8ff48b84542962110e7a9851917
|
||||
timeCreated: 1760422573
|
12
Assets/Script/Gameplay/Card/CardBook/CardBookViewer.cs
Normal file
12
Assets/Script/Gameplay/Card/CardBook/CardBookViewer.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Gameplay
|
||||
{
|
||||
// 卡牌书的显示相关脚本
|
||||
public class CardBookViewer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform LeftHandPoint;
|
||||
private CardBook CardBook;
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68803a8f56734f22a3025f8028fc027f
|
||||
timeCreated: 1760431288
|
23
Assets/Script/Gameplay/Card/CardBook/CardSlot.cs
Normal file
23
Assets/Script/Gameplay/Card/CardBook/CardSlot.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Gameplay
|
||||
{
|
||||
public class CardSlot
|
||||
{
|
||||
public Card StoredCard;
|
||||
public bool IsEmpty => StoredCard == null;
|
||||
public int ActiveTimes = 0;
|
||||
|
||||
public void StoreCard(Card card)
|
||||
{
|
||||
StoredCard = card;
|
||||
ActiveTimes = 0;
|
||||
}
|
||||
|
||||
public Card RemoveCard()
|
||||
{
|
||||
var card = StoredCard;
|
||||
StoredCard = null;
|
||||
ActiveTimes = 0;
|
||||
return card;
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Card/CardBook/CardSlot.cs.meta
Normal file
3
Assets/Script/Gameplay/Card/CardBook/CardSlot.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5f566603b3f4286965da48bb49c018a
|
||||
timeCreated: 1760422548
|
@@ -2,11 +2,12 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Card
|
||||
namespace Gameplay
|
||||
{
|
||||
[CreateAssetMenu(fileName = "NewCard", menuName = "Card/CardData")]
|
||||
[CreateAssetMenu(fileName = "CardData", menuName = "ScriptableObject/CardData")]
|
||||
public class CardData : ScriptableObject
|
||||
{
|
||||
public int CardID;
|
||||
public string CardName;
|
||||
public string CardDescription;
|
||||
public Texture CardTexture;
|
16
Assets/Script/Gameplay/Card/CardEffect/CardContext.cs
Normal file
16
Assets/Script/Gameplay/Card/CardEffect/CardContext.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using Share;
|
||||
namespace Gameplay
|
||||
{
|
||||
public class CardContext
|
||||
{
|
||||
public ICharacter Owner;
|
||||
public ICharacter Enemy;
|
||||
|
||||
public CardContext(ICharacter owner,ICharacter enemy)
|
||||
{
|
||||
Owner = owner;
|
||||
Enemy = enemy;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Card
|
||||
namespace Gameplay
|
||||
{
|
||||
[System.Serializable]
|
||||
public class EffectData
|
||||
@@ -22,7 +22,5 @@ namespace Card
|
||||
{
|
||||
Damage,
|
||||
Heal,
|
||||
DrawCard,
|
||||
AddBuff,
|
||||
}
|
||||
}
|
24
Assets/Script/Gameplay/Card/CardEffect/EffectHandler.cs
Normal file
24
Assets/Script/Gameplay/Card/CardEffect/EffectHandler.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay
|
||||
{
|
||||
public static class EffectHandler
|
||||
{
|
||||
public static void Execute(EffectData effect, CardContext context)
|
||||
{
|
||||
switch (effect.type)
|
||||
{
|
||||
case EffectType.Damage:
|
||||
context.Enemy.TakeDamage(effect.value);
|
||||
break;
|
||||
|
||||
case EffectType.Heal:
|
||||
context.Enemy.Heal(effect.value);
|
||||
break;
|
||||
default:
|
||||
Debug.Log($"未知效果类型: {effect.type}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
Assets/Script/Gameplay/Card/CardLoader.cs
Normal file
21
Assets/Script/Gameplay/Card/CardLoader.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
namespace Gameplay
|
||||
{
|
||||
// 从Resources文件夹加载卡牌数据的静态类
|
||||
public static class CardLoader
|
||||
{
|
||||
public static CardData GetCardDataByID(int cardID)
|
||||
{
|
||||
CardData[] allCards = Resources.LoadAll<CardData>("Configs/Card");
|
||||
foreach (var card in allCards)
|
||||
{
|
||||
if (card.CardID == cardID)
|
||||
{
|
||||
return card;
|
||||
}
|
||||
}
|
||||
Debug.LogError($"Card with ID {cardID} not found!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Card/CardLoader.cs.meta
Normal file
3
Assets/Script/Gameplay/Card/CardLoader.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 447cd4a06d4a497cb301f68b51a4121a
|
||||
timeCreated: 1760518833
|
@@ -1,8 +1,7 @@
|
||||
using UnityEngine;
|
||||
using Card;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Card
|
||||
namespace Gameplay
|
||||
{
|
||||
public class CardViewer : MonoBehaviour
|
||||
{
|
3
Assets/Script/Gameplay/Combat.meta
Normal file
3
Assets/Script/Gameplay/Combat.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 649c2c30ae8a4f64ae00e35a3bf67479
|
||||
timeCreated: 1760496426
|
176
Assets/Script/Gameplay/Combat/CombatFlowManager.cs
Normal file
176
Assets/Script/Gameplay/Combat/CombatFlowManager.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Gameplay.Enemy;
|
||||
using Gameplay.Player;
|
||||
using Share;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// 战斗流程管理器(回合制、循环抽牌)
|
||||
/// 使用方法:在场景中挂载一个空物体并配置 player 与 enemy 的 Combatant 引用。
|
||||
/// 该管理器通过事件回调让 UI 或其它系统接入“双方牌都打空时”的选择(继续/逃跑)。
|
||||
/// </summary>
|
||||
public class CombatFlowManager : MonoSingleton<CombatFlowManager>
|
||||
{
|
||||
[Header("Participants")]
|
||||
public PlayerController player;
|
||||
public EnemyController enemy;
|
||||
|
||||
[Header("Flow Settings")]
|
||||
[Tooltip("玩家是否先手(true=玩家先出一张)")]
|
||||
public bool playerStarts = true;
|
||||
[Tooltip("每出一张牌后的间隔(秒)")]
|
||||
public float turnDelay = 0.8f;
|
||||
|
||||
// Events
|
||||
public event Action OnCombatStarted;
|
||||
public event Action<ICharacter, Card> OnCardPlayed;
|
||||
public event Action<ICharacter> OnCombatEnded; // 参数为胜利方(null 表示平局或逃跑)
|
||||
public event Action OnBothEmpty; // 当双方都没有卡可以出时触发,UI 需要通过 ContinueAfterBothEmpty 或 EscapeFromCombat 响应
|
||||
|
||||
// internal state
|
||||
private Coroutine runningRoutine;
|
||||
private bool waitingForDecision = false;
|
||||
private bool decisionContinue = false;
|
||||
private bool decisionEscape = false;
|
||||
|
||||
/// <summary>
|
||||
/// 启动战斗流程(也可以在 Inspector 中提前绑定 player/enemy,然后只调用 StartCombat())
|
||||
/// </summary>
|
||||
public void StartCombat(PlayerController playerController = null, EnemyController enemyController = null)
|
||||
{
|
||||
if (playerController != null) player = playerController;
|
||||
if (enemyController != null) enemy = enemyController;
|
||||
|
||||
if (player == null || enemy == null)
|
||||
{
|
||||
Debug.LogError("CombatFlowManager: player 或 enemy 未设置。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化双方状态
|
||||
player.StartCombat();
|
||||
enemy.StartCombat();
|
||||
player.InitializeDeckCycle();
|
||||
enemy.InitializeDeckCycle();
|
||||
|
||||
|
||||
runningRoutine = StartCoroutine(CombatRoutine());
|
||||
OnCombatStarted?.Invoke();
|
||||
}
|
||||
|
||||
public void StopCombat()
|
||||
{
|
||||
if (runningRoutine != null) StopCoroutine(runningRoutine);
|
||||
runningRoutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator CombatRoutine()
|
||||
{
|
||||
ICharacter current = playerStarts ? player : enemy;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 结束检查
|
||||
if (player.IsDead || enemy.IsDead)
|
||||
{
|
||||
ICharacter winner = player.IsDead ? enemy : player;
|
||||
OnCombatEnded?.Invoke(winner);
|
||||
runningRoutine = null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
bool playerHas = player.HasCardsLeft();
|
||||
bool enemyHas = enemy.HasCardsLeft();
|
||||
|
||||
if (!playerHas && !enemyHas)
|
||||
{
|
||||
// 双方都打空,等待玩家选择(由 UI 调用 ContinueAfterBothEmpty 或 EscapeFromCombat)
|
||||
waitingForDecision = true;
|
||||
decisionContinue = false;
|
||||
decisionEscape = false;
|
||||
OnBothEmpty?.Invoke();
|
||||
|
||||
// 等待选择
|
||||
while (waitingForDecision)
|
||||
yield return null;
|
||||
|
||||
if (decisionEscape)
|
||||
{
|
||||
// 玩家选择逃跑 -> 结束战斗,胜者设为 null(或按需要设成敌人/玩家)
|
||||
OnCombatEnded?.Invoke(null);
|
||||
runningRoutine = null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (decisionContinue)
|
||||
{
|
||||
// 重新从卡册读取(重置抽牌队列),保持生命与其它状态不变
|
||||
player.InitializeDeckCycle();
|
||||
enemy.InitializeDeckCycle();
|
||||
// 继续循环(当前先手不变)
|
||||
yield return null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 当前回合:如果当前方没有牌则跳过(空过)
|
||||
if (current.HasCardsLeft())
|
||||
{
|
||||
var card = current.GetNextCard();
|
||||
ICharacter target;
|
||||
if (current is PlayerController)
|
||||
{
|
||||
target = enemy;
|
||||
}
|
||||
else
|
||||
{
|
||||
target = player;
|
||||
}
|
||||
|
||||
|
||||
// 触发卡牌效果(当前仅支持直接伤害)
|
||||
if (card != null)
|
||||
{
|
||||
card.PlayCard(new CardContext(current, target));
|
||||
OnCardPlayed?.Invoke(current, card);
|
||||
}
|
||||
|
||||
// 检查死亡(将在下一循环顶部处理)
|
||||
yield return new WaitForSeconds(turnDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 跳过一轮,不延迟太久
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
}
|
||||
|
||||
// 切换行动方
|
||||
current = (current == player) ? enemy : player;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当双方都打空时,UI 调用此方法选择继续下一轮(重新从卡册读取卡牌)
|
||||
/// </summary>
|
||||
public void ContinueAfterBothEmpty()
|
||||
{
|
||||
if (!waitingForDecision) return;
|
||||
decisionContinue = true;
|
||||
waitingForDecision = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当双方都打空时,UI 调用此方法选择逃跑
|
||||
/// </summary>
|
||||
public void EscapeFromCombat()
|
||||
{
|
||||
if (!waitingForDecision) return;
|
||||
decisionEscape = true;
|
||||
waitingForDecision = false;
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Combat/CombatFlowManager.cs.meta
Normal file
3
Assets/Script/Gameplay/Combat/CombatFlowManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e8e663fe8d349bea29b9887d29db187
|
||||
timeCreated: 1760496426
|
49
Assets/Script/Gameplay/Combat/CombatTrigger.cs
Normal file
49
Assets/Script/Gameplay/Combat/CombatTrigger.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Gameplay;
|
||||
using Share;
|
||||
using Gameplay.Enemy;
|
||||
using Gameplay.Player;
|
||||
|
||||
namespace Gameplay.Combat
|
||||
{
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class CombatTrigger : MonoBehaviour
|
||||
{
|
||||
//[Tooltip("战斗管理器引用(场景中单例/对象)")]
|
||||
private CombatFlowManager combatManager;
|
||||
|
||||
[Tooltip("触发时指定的玩家 Combatant(可为空,manager 使用已配置的)")]
|
||||
public PlayerController player;
|
||||
|
||||
[Tooltip("触发时指定的敌人 Combatant(可为空,manager 使用已配置的)")]
|
||||
public EnemyController enemy;
|
||||
|
||||
[Tooltip("被触发后是否自动禁用触发器,避免重复触发")]
|
||||
public bool disableAfterTrigger = true;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
combatManager = CombatFlowManager.Instance;
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
// Collider 需要 isTrigger
|
||||
var col = GetComponent<Collider>();
|
||||
col.isTrigger = true;
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
// 简单检测:玩家层或带有 "Player" 标签的物体
|
||||
if (combatManager == null) return;
|
||||
|
||||
if (other.CompareTag("Player") || other.gameObject.layer == LayerMask.NameToLayer("Player"))
|
||||
{
|
||||
combatManager.StartCombat(player, enemy);
|
||||
if (disableAfterTrigger) gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Combat/CombatTrigger.cs.meta
Normal file
3
Assets/Script/Gameplay/Combat/CombatTrigger.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d9265c2645847c2b5197ed2ba181c98
|
||||
timeCreated: 1760496463
|
3
Assets/Script/Gameplay/Enemy.meta
Normal file
3
Assets/Script/Gameplay/Enemy.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b712b2fa4f743408e56868a21312535
|
||||
timeCreated: 1760495486
|
77
Assets/Script/Gameplay/Enemy/EnemyController.cs
Normal file
77
Assets/Script/Gameplay/Enemy/EnemyController.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Share;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay.Enemy
|
||||
{
|
||||
public class EnemyController : MonoBehaviour, ICharacter
|
||||
{
|
||||
[SerializeField] private string enemyName;
|
||||
[SerializeField] private int maxHealth = 100;
|
||||
public int MaxHealth => maxHealth;
|
||||
public int CurrentHealth { get; set; }
|
||||
|
||||
[SerializeField] private CardBookData cardBookData;
|
||||
private CardBook myCardBook;
|
||||
private List<Card> cards;
|
||||
private int currentCardIndex = 0;
|
||||
|
||||
public bool IsFlight { get; private set; }
|
||||
public bool IsDead { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
CurrentHealth = MaxHealth;
|
||||
myCardBook = new CardBook(cardBookData);
|
||||
cards = new List<Card>();
|
||||
}
|
||||
|
||||
public void TakeDamage(int damage)
|
||||
{
|
||||
CurrentHealth -= damage;
|
||||
}
|
||||
|
||||
public void Heal(int heal)
|
||||
{
|
||||
CurrentHealth += heal;
|
||||
if (CurrentHealth > MaxHealth)
|
||||
{
|
||||
CurrentHealth = MaxHealth;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartCombat()
|
||||
{
|
||||
Debug.Log($"{name} Enemy Start Combat");
|
||||
IsFlight = false;
|
||||
}
|
||||
|
||||
public void EndFlight()
|
||||
{
|
||||
Debug.Log($"{name} Enemy End Flight");
|
||||
IsFlight = true;
|
||||
}
|
||||
|
||||
public bool HasCardsLeft()
|
||||
{
|
||||
return currentCardIndex < cards.Count;
|
||||
}
|
||||
|
||||
public Card GetNextCard()
|
||||
{
|
||||
if (!HasCardsLeft())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return cards[currentCardIndex++];
|
||||
}
|
||||
|
||||
public void InitializeDeckCycle()
|
||||
{
|
||||
cards = myCardBook.GetCards().ToList();
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Enemy/EnemyController.cs.meta
Normal file
3
Assets/Script/Gameplay/Enemy/EnemyController.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5a587a681ae48d6b3a5dcd5a723fd5a
|
||||
timeCreated: 1760512105
|
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "Card",
|
||||
"name": "Gameplay",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:fd0e97c21c15497f9406b8ee23c1f67e",
|
||||
"GUID:9e4105fe56ff4b1789a1683a3c08d507"
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
3
Assets/Script/Gameplay/Gameplay.asmdef.meta
Normal file
3
Assets/Script/Gameplay/Gameplay.asmdef.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ceb6a2c14699464ca35be17af198f904
|
||||
timeCreated: 1760445049
|
3
Assets/Script/Gameplay/Input.meta
Normal file
3
Assets/Script/Gameplay/Input.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c652418c7ff4cb9be7aa23ec423c5f9
|
||||
timeCreated: 1760447326
|
@@ -1,16 +1,19 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Core;
|
||||
|
||||
namespace Core
|
||||
namespace Input
|
||||
{
|
||||
public class InputManager : MonoSingleton<InputManager>
|
||||
public class InputManager : MonoSingleton<InputManager>, IInputManager
|
||||
{
|
||||
private PlayerInputActions _input; // 自动生成的输入类
|
||||
|
||||
// 当前输入值
|
||||
public Vector2 Move { get; private set; }
|
||||
public Vector2 Look { get; private set; }
|
||||
public bool JumpPressed { get; private set; }
|
||||
public bool PausePressed { get; private set; }
|
||||
public bool InteractPressed { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -27,11 +30,15 @@ namespace Core
|
||||
|
||||
_input.Player.Look.performed += ctx => Look = ctx.ReadValue<Vector2>();
|
||||
_input.Player.Look.canceled += ctx => Look = Vector2.zero;
|
||||
//
|
||||
// _input.Player.Jump.performed += ctx => JumpPressed = true;
|
||||
// _input.Player.Jump.canceled += ctx => JumpPressed = false;
|
||||
//
|
||||
|
||||
_input.Player.Jump.performed += ctx => JumpPressed = true;
|
||||
_input.Player.Jump.canceled += ctx => JumpPressed = false;
|
||||
|
||||
// _input.Player.Pause.performed += ctx => PausePressed = true;
|
||||
// _input.Player.Pause.canceled += ctx => PausePressed = false;
|
||||
|
||||
_input.Player.Interact.performed += ctx => InteractPressed = true;
|
||||
_input.Player.Interact.canceled += ctx => InteractPressed = false;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
@@ -39,6 +46,11 @@ namespace Core
|
||||
_input.Disable();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UIManager.Instance.RegisterInputManager(this);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 在此更新一次性触发的输入,例如“按下瞬间触发”
|
@@ -15,7 +15,7 @@ using System.Collections.Generic;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace Core
|
||||
namespace Input
|
||||
{
|
||||
public partial class @PlayerInputActions: IInputActionCollection2, IDisposable
|
||||
{
|
||||
@@ -31,12 +31,12 @@ namespace Core
|
||||
""actions"": [
|
||||
{
|
||||
""name"": ""Move"",
|
||||
""type"": ""Button"",
|
||||
""type"": ""Value"",
|
||||
""id"": ""cba876cd-5594-42ac-a4b0-2f2ed0f0e120"",
|
||||
""expectedControlType"": """",
|
||||
""expectedControlType"": ""Vector2"",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
""initialStateCheck"": true
|
||||
},
|
||||
{
|
||||
""name"": ""Look"",
|
||||
@@ -46,28 +46,123 @@ namespace Core
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": true
|
||||
},
|
||||
{
|
||||
""name"": ""Jump"",
|
||||
""type"": ""Button"",
|
||||
""id"": ""850284f0-b2d8-412c-9970-c1a7256e29de"",
|
||||
""expectedControlType"": """",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
},
|
||||
{
|
||||
""name"": ""Interact"",
|
||||
""type"": ""Button"",
|
||||
""id"": ""b405cb77-699f-4558-831a-c6c12a5c0300"",
|
||||
""expectedControlType"": """",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
}
|
||||
],
|
||||
""bindings"": [
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""dab4d8f6-9492-4327-8944-76f09907ba54"",
|
||||
""id"": ""d7c34f0b-b18e-4498-8d3e-1bdec4cb355d"",
|
||||
""path"": ""<Mouse>/delta"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Look"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": ""2D Vector"",
|
||||
""id"": ""132c4a80-d02d-43c4-bf7b-8e0ff43a44de"",
|
||||
""path"": ""2DVector"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Move"",
|
||||
""isComposite"": true,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": ""up"",
|
||||
""id"": ""a4d4ec38-2560-46b0-b57b-d9ea0f35d701"",
|
||||
""path"": ""<Keyboard>/w"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Move"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": true
|
||||
},
|
||||
{
|
||||
""name"": ""down"",
|
||||
""id"": ""f1c59ea2-0648-4f49-8cfb-d566be529303"",
|
||||
""path"": ""<Keyboard>/s"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Move"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": true
|
||||
},
|
||||
{
|
||||
""name"": ""left"",
|
||||
""id"": ""529b3ae4-cbf4-412c-a783-5bf62c57de72"",
|
||||
""path"": ""<Keyboard>/a"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Move"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": true
|
||||
},
|
||||
{
|
||||
""name"": ""right"",
|
||||
""id"": ""57ddd6bd-cbf7-4cfb-98d3-5b4458a21562"",
|
||||
""path"": ""<Keyboard>/d"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Move"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": true
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""b6a61d59-edf3-4759-8791-8967ffa1e187"",
|
||||
""path"": ""<Keyboard>/space"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Jump"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""d7c34f0b-b18e-4498-8d3e-1bdec4cb355d"",
|
||||
""path"": ""<Mouse>/position"",
|
||||
""id"": ""c7bb1d3e-20de-4ff9-96fc-bfc70ca54e20"",
|
||||
""path"": ""<Keyboard>/f"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Look"",
|
||||
""action"": ""Interact"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""ab4a9194-7003-42f9-a13b-f6edf0427a6e"",
|
||||
""path"": ""<Mouse>/leftButton"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Interact"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
}
|
||||
@@ -80,6 +175,8 @@ namespace Core
|
||||
m_Player = asset.FindActionMap("Player", throwIfNotFound: true);
|
||||
m_Player_Move = m_Player.FindAction("Move", throwIfNotFound: true);
|
||||
m_Player_Look = m_Player.FindAction("Look", throwIfNotFound: true);
|
||||
m_Player_Jump = m_Player.FindAction("Jump", throwIfNotFound: true);
|
||||
m_Player_Interact = m_Player.FindAction("Interact", throwIfNotFound: true);
|
||||
}
|
||||
|
||||
~@PlayerInputActions()
|
||||
@@ -148,12 +245,16 @@ namespace Core
|
||||
private List<IPlayerActions> m_PlayerActionsCallbackInterfaces = new List<IPlayerActions>();
|
||||
private readonly InputAction m_Player_Move;
|
||||
private readonly InputAction m_Player_Look;
|
||||
private readonly InputAction m_Player_Jump;
|
||||
private readonly InputAction m_Player_Interact;
|
||||
public struct PlayerActions
|
||||
{
|
||||
private @PlayerInputActions m_Wrapper;
|
||||
public PlayerActions(@PlayerInputActions wrapper) { m_Wrapper = wrapper; }
|
||||
public InputAction @Move => m_Wrapper.m_Player_Move;
|
||||
public InputAction @Look => m_Wrapper.m_Player_Look;
|
||||
public InputAction @Jump => m_Wrapper.m_Player_Jump;
|
||||
public InputAction @Interact => m_Wrapper.m_Player_Interact;
|
||||
public InputActionMap Get() { return m_Wrapper.m_Player; }
|
||||
public void Enable() { Get().Enable(); }
|
||||
public void Disable() { Get().Disable(); }
|
||||
@@ -169,6 +270,12 @@ namespace Core
|
||||
@Look.started += instance.OnLook;
|
||||
@Look.performed += instance.OnLook;
|
||||
@Look.canceled += instance.OnLook;
|
||||
@Jump.started += instance.OnJump;
|
||||
@Jump.performed += instance.OnJump;
|
||||
@Jump.canceled += instance.OnJump;
|
||||
@Interact.started += instance.OnInteract;
|
||||
@Interact.performed += instance.OnInteract;
|
||||
@Interact.canceled += instance.OnInteract;
|
||||
}
|
||||
|
||||
private void UnregisterCallbacks(IPlayerActions instance)
|
||||
@@ -179,6 +286,12 @@ namespace Core
|
||||
@Look.started -= instance.OnLook;
|
||||
@Look.performed -= instance.OnLook;
|
||||
@Look.canceled -= instance.OnLook;
|
||||
@Jump.started -= instance.OnJump;
|
||||
@Jump.performed -= instance.OnJump;
|
||||
@Jump.canceled -= instance.OnJump;
|
||||
@Interact.started -= instance.OnInteract;
|
||||
@Interact.performed -= instance.OnInteract;
|
||||
@Interact.canceled -= instance.OnInteract;
|
||||
}
|
||||
|
||||
public void RemoveCallbacks(IPlayerActions instance)
|
||||
@@ -200,6 +313,8 @@ namespace Core
|
||||
{
|
||||
void OnMove(InputAction.CallbackContext context);
|
||||
void OnLook(InputAction.CallbackContext context);
|
||||
void OnJump(InputAction.CallbackContext context);
|
||||
void OnInteract(InputAction.CallbackContext context);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff05c86378543b94488d735aea6436d1
|
||||
guid: 3112886b43bfe4d40bf728a52f00436c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
3
Assets/Script/Gameplay/Interface.meta
Normal file
3
Assets/Script/Gameplay/Interface.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6407e403d6f34e658b36489eb9954344
|
||||
timeCreated: 1760445405
|
28
Assets/Script/Gameplay/Interface/ICharacter.cs
Normal file
28
Assets/Script/Gameplay/Interface/ICharacter.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Gameplay;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Share
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色接口,可受伤害、治疗和添加Buff、发生战斗
|
||||
/// 拥有卡牌书
|
||||
/// </summary>
|
||||
public interface ICharacter
|
||||
{
|
||||
// public int MaxHealth { get; }
|
||||
// public int CurrentHealth { get; }
|
||||
// public CardBook CardBook { get; }
|
||||
// public List<Card> Cards { get; }
|
||||
public bool IsFlight { get; }
|
||||
public bool IsDead { get; }
|
||||
public void TakeDamage(int damage);
|
||||
public void Heal(int heal);
|
||||
public void StartCombat();
|
||||
public void EndFlight();
|
||||
public bool HasCardsLeft();
|
||||
public Card GetNextCard();
|
||||
public void InitializeDeckCycle();
|
||||
}
|
||||
}
|
9
Assets/Script/Gameplay/Interface/IInteractable.cs
Normal file
9
Assets/Script/Gameplay/Interface/IInteractable.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
namespace Share
|
||||
{
|
||||
public interface IInteractable
|
||||
{
|
||||
string GetInteractPrompt(); // 返回提示文字,例如“按E打开门”
|
||||
void Interact(GameObject interactor); // 当玩家交互时触发
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Interface/IInteractable.cs.meta
Normal file
3
Assets/Script/Gameplay/Interface/IInteractable.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bb60830b6e14df78b72c49d9250fa75
|
||||
timeCreated: 1760444920
|
10
Assets/Script/Gameplay/Map/FlightTrigger.cs
Normal file
10
Assets/Script/Gameplay/Map/FlightTrigger.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using UnityEngine;
|
||||
using Share;
|
||||
namespace Map
|
||||
{
|
||||
public class FlightTrigger : MonoBehaviour
|
||||
{
|
||||
[SerializeField] public ICharacter Player;
|
||||
[SerializeField] public ICharacter Enemy;
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Map/FlightTrigger.cs.meta
Normal file
3
Assets/Script/Gameplay/Map/FlightTrigger.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e697dc78ed84a3ab2e921a57c17be95
|
||||
timeCreated: 1760495479
|
20
Assets/Script/Gameplay/Map/MapFlag.cs
Normal file
20
Assets/Script/Gameplay/Map/MapFlag.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
namespace Map
|
||||
{
|
||||
public class MapFlag : MonoBehaviour
|
||||
{
|
||||
public string FlagName;
|
||||
public Vector3 Position;
|
||||
public MapFlag ParentFlag;
|
||||
public MapFlag LeftFlag;
|
||||
public MapFlag RightFlag;
|
||||
|
||||
public event Action<MapFlag> OnPlayerEnter;
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
OnPlayerEnter?.Invoke(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Map/MapFlag.cs.meta
Normal file
3
Assets/Script/Gameplay/Map/MapFlag.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c3ea88c92cc4d0bb6098983903be7fb
|
||||
timeCreated: 1760444130
|
13
Assets/Script/Gameplay/Map/MapFlagManager.cs
Normal file
13
Assets/Script/Gameplay/Map/MapFlagManager.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Map
|
||||
{
|
||||
public class MapFlagManager : MonoSingleton<MapFlagManager>
|
||||
{
|
||||
public MapFlag StartFlag;
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Map/MapFlagManager.cs.meta
Normal file
3
Assets/Script/Gameplay/Map/MapFlagManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f13be1e244e84e3b93b0b3a4c054cb46
|
||||
timeCreated: 1760424376
|
@@ -1,13 +1,13 @@
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
using Input;
|
||||
|
||||
namespace Player
|
||||
namespace Gameplay.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家第一人称相机控制器
|
||||
/// 挂到相机或相机父物体,playerBody 指向角色的根 Transform(用于左右旋转)
|
||||
/// </summary>
|
||||
/// TODO:使用InputManager替换掉Input.GetAxis
|
||||
public class PlayerCameraController : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
9
Assets/Script/Gameplay/Player/PlayerConfig.cs
Normal file
9
Assets/Script/Gameplay/Player/PlayerConfig.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay.Player
|
||||
{
|
||||
public class PlayerConfig : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Player/PlayerConfig.cs.meta
Normal file
3
Assets/Script/Gameplay/Player/PlayerConfig.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ff9e093e80541dc93d1186499dbfd79
|
||||
timeCreated: 1760498762
|
92
Assets/Script/Gameplay/Player/PlayerController.cs
Normal file
92
Assets/Script/Gameplay/Player/PlayerController.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Gameplay;
|
||||
using Share;
|
||||
using UnityEngine;
|
||||
using Core;
|
||||
|
||||
namespace Gameplay.Player
|
||||
{
|
||||
public class PlayerController : MonoBehaviour, ICharacter
|
||||
{
|
||||
public int MaxHealth { get; set; } = 100;
|
||||
public int CurrentHealth { get; private set; }
|
||||
|
||||
[SerializeField] private CardBookData cardBookData;
|
||||
public CardBook MyCardBook { get; private set; }
|
||||
public List<Card> Cards { get; private set; }
|
||||
private int currentCardIndex = 0;
|
||||
|
||||
public bool IsFlight { get; private set; }
|
||||
public bool IsDead { get; private set; }
|
||||
|
||||
private PlayerMoveController playerMoveController;
|
||||
private PlayerCameraController playerCameraController;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
playerMoveController = GetComponent<PlayerMoveController>();
|
||||
playerCameraController = GetComponent<PlayerCameraController>();
|
||||
|
||||
CurrentHealth = MaxHealth;
|
||||
MyCardBook = new CardBook(cardBookData);
|
||||
Cards = new List<Card>();
|
||||
|
||||
UIViewerControllerLocator.Instance.Register(this);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void TakeDamage(int damage)
|
||||
{
|
||||
CurrentHealth -= damage;
|
||||
}
|
||||
|
||||
public void Heal(int heal)
|
||||
{
|
||||
CurrentHealth += heal;
|
||||
if (CurrentHealth > MaxHealth)
|
||||
{
|
||||
CurrentHealth = MaxHealth;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartCombat()
|
||||
{
|
||||
Debug.Log("Player StartCombat");
|
||||
IsFlight = true;
|
||||
playerMoveController.SetSpeed(0.5f);
|
||||
}
|
||||
|
||||
public void EndFlight()
|
||||
{
|
||||
Debug.Log("Player EndFlight");
|
||||
IsFlight = false;
|
||||
playerMoveController.ResetSpeed();
|
||||
}
|
||||
|
||||
public bool HasCardsLeft()
|
||||
{
|
||||
return currentCardIndex < Cards.Count;
|
||||
}
|
||||
|
||||
public Card GetNextCard()
|
||||
{
|
||||
if (!HasCardsLeft())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Cards[currentCardIndex++];
|
||||
}
|
||||
|
||||
public void InitializeDeckCycle()
|
||||
{
|
||||
Cards = MyCardBook.GetCards().ToList();
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/Gameplay/Player/PlayerController.cs.meta
Normal file
3
Assets/Script/Gameplay/Player/PlayerController.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7071907d14f433789ea37a8367b584a
|
||||
timeCreated: 1760495717
|
58
Assets/Script/Gameplay/Player/PlayerInteractorController.cs
Normal file
58
Assets/Script/Gameplay/Player/PlayerInteractorController.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
using Share;
|
||||
using System;
|
||||
using Input;
|
||||
|
||||
namespace Gameplay.Player
|
||||
{
|
||||
public class PlayerInteractorController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float interactRange = 15f;
|
||||
[SerializeField] private LayerMask interactableLayer;
|
||||
[SerializeField] private Camera playerCamera;
|
||||
|
||||
private IInteractable currentTarget;
|
||||
|
||||
void Start()
|
||||
{
|
||||
playerCamera = GameObject.FindWithTag("MainCamera").GetComponent<Camera>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
DetectInteractable();
|
||||
|
||||
if (currentTarget != null && InputManager.Instance.InteractPressed)
|
||||
{
|
||||
currentTarget.Interact(this.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectInteractable()
|
||||
{
|
||||
Ray ray = new Ray(playerCamera.transform.position, playerCamera.transform.forward);
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, interactRange, interactableLayer))
|
||||
{
|
||||
currentTarget = hit.collider.GetComponent<IInteractable>();
|
||||
if (currentTarget != null)
|
||||
{
|
||||
// 这里可以显示交互提示UI,例如 “E - 开门”
|
||||
Debug.Log(currentTarget.GetInteractPrompt());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (playerCamera == null) return;
|
||||
Gizmos.color = Color.green;
|
||||
Vector3 origin = playerCamera.transform.position;
|
||||
Vector3 direction = playerCamera.transform.forward * interactRange;
|
||||
Gizmos.DrawLine(origin, origin + direction);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc03712b5c254b8380471356f3bac151
|
||||
timeCreated: 1760516273
|
89
Assets/Script/Gameplay/Player/PlayerMoveController.cs
Normal file
89
Assets/Script/Gameplay/Player/PlayerMoveController.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using Core;
|
||||
using Input;
|
||||
using Map;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay.Player
|
||||
{
|
||||
public class PlayerMoveController : MonoBehaviour
|
||||
{
|
||||
[Header("Movement Settings")]
|
||||
[Tooltip("移动速度(米/秒)")]
|
||||
public float speed = 5f;
|
||||
[Tooltip("跳跃高度(米)")]
|
||||
public float jumpHeight = 2f;
|
||||
[Tooltip("重力加速度(米/秒²)")]
|
||||
public float gravity = -9.81f;
|
||||
|
||||
[Header("Ground Check")]
|
||||
[Tooltip("检测地面的位置(通常为角色脚下)")]
|
||||
public Transform groundCheck;
|
||||
[Tooltip("地面检测半径")]
|
||||
public float groundDistance = 0.4f;
|
||||
[Tooltip("地面层(LayerMask)")]
|
||||
public LayerMask groundMask;
|
||||
|
||||
private float initSpeed;
|
||||
|
||||
private CharacterController characterController;
|
||||
private Vector3 velocity;
|
||||
private bool isGrounded;
|
||||
private IInputManager inputManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
characterController = GetComponent<CharacterController>();
|
||||
if (characterController == null)
|
||||
Debug.LogError("PlayerMoveController 需要 CharacterController 组件!");
|
||||
|
||||
initSpeed = speed;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
inputManager = InputManager.Instance;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 地面检测
|
||||
if (groundCheck != null)
|
||||
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
|
||||
else
|
||||
isGrounded = characterController.isGrounded;
|
||||
|
||||
if (isGrounded && velocity.y < 0)
|
||||
velocity.y = -2f; // 保持贴地
|
||||
|
||||
Vector2 inputMove = inputManager.Move;
|
||||
// 获取输入
|
||||
float x = inputMove.x;
|
||||
float z = inputMove.y;
|
||||
|
||||
// 按玩家朝向移动
|
||||
Vector3 move = transform.right * x + transform.forward * z;
|
||||
characterController.Move(move * speed * Time.deltaTime);
|
||||
|
||||
// 跳跃
|
||||
if (isGrounded && inputManager.JumpPressed)
|
||||
{
|
||||
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
|
||||
}
|
||||
|
||||
// 重力
|
||||
velocity.y += gravity * Time.deltaTime;
|
||||
characterController.Move(velocity * Time.deltaTime);
|
||||
}
|
||||
|
||||
public void SetSpeed(float newSpeed)
|
||||
{
|
||||
speed = newSpeed;
|
||||
}
|
||||
|
||||
public void ResetSpeed()
|
||||
{
|
||||
speed = initSpeed;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14c86d6b22344680a9eba4de056d3b53
|
||||
timeCreated: 1760424128
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"name": "Map"
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccba5c55d09a415a94ff4a5e6375019a
|
||||
timeCreated: 1760362986
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"name": "Player"
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9c4db94c16f41feaa2a3b1ea6785a04
|
||||
timeCreated: 1760362801
|
@@ -1,9 +0,0 @@
|
||||
using UnityEngine;
|
||||
namespace Player
|
||||
{
|
||||
public class PlayerMoveController : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6025e0f3c5664b9c8c01a994fb1e0620
|
||||
timeCreated: 1760362812
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05474807e682482694deb13b21e1bdfb
|
||||
timeCreated: 1760361359
|
@@ -1,15 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Share
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色接口,可受伤害、治疗和添加Buff
|
||||
/// </summary>
|
||||
public interface ICharacter
|
||||
{
|
||||
public void TakeDamage(int damage);
|
||||
public void Heal(int heal);
|
||||
public void AddBuff(string buffName, int duration);
|
||||
public void Draw(int count);
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"name": "Share"
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e4105fe56ff4b1789a1683a3c08d507
|
||||
timeCreated: 1760361379
|
32
Assets/Script/UI/PlayerHpViewer.cs
Normal file
32
Assets/Script/UI/PlayerHpViewer.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using Core;
|
||||
using Gameplay.Player;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class PlayerHpViewer : UIBase
|
||||
{
|
||||
private PlayerController _playerController;
|
||||
public Text hpText;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UIViewerControllerLocator.Instance.TryGetWait<PlayerController>(OnGet);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_playerController != null)
|
||||
{
|
||||
hpText.text = "HP: " + _playerController.CurrentHealth;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGet(PlayerController playerController)
|
||||
{
|
||||
_playerController = playerController;
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/Script/UI/PlayerHpViewer.cs.meta
Normal file
3
Assets/Script/UI/PlayerHpViewer.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a450025fc367419faaf7481787bfac88
|
||||
timeCreated: 1760514338
|
@@ -2,9 +2,8 @@
|
||||
"name": "UI",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:ec826b79cbc40da479bcc7969404880e",
|
||||
"GUID:fd0e97c21c15497f9406b8ee23c1f67e",
|
||||
"GUID:9e4105fe56ff4b1789a1683a3c08d507"
|
||||
"GUID:ceb6a2c14699464ca35be17af198f904"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
Reference in New Issue
Block a user