16 KiB
16 KiB
Cielonos 项目架构改进建议
一、整体架构评估
当前架构优势
- 模块化设计: Submodule/Subcontroller架构将逻辑和表现分离,提供了良好的可扩展性
- 组件化思想: 大量使用字典存储子模块,便于动态增删功能
- 事件驱动: 使用UniRx实现响应式事件系统,解耦了系统间的依赖
- 系统完整性: 战斗、Buff、状态、动画等核心系统已经具备完整的基础架构
当前架构不足
- 职责边界模糊: 部分类承担了过多职责
- 代码组织混乱: 部分脚本放置位置不合理
- 抽象程度不足: 部分核心逻辑缺少接口抽象
- 文档注释缺失: 代码缺少必要的注释和说明
- 配置化程度低: 硬编码问题较多
二、具体改进建议
1. 核心架构层
1.1 建立核心接口层
问题: 当前系统之间直接依赖具体实现,缺乏抽象层
建议:
Core/Interfaces/
├── ICharacter.cs # 角色接口
├── IAttackable.cs # 可攻击对象接口
├── IBuffable.cs # 可附魔Buff对象接口
├── IItem.cs # 物品接口
├── IWeapon.cs # 武器接口
├── IDamageable.cs # 可受伤害对象接口
└── ITeamMember.cs # 阵营成员接口
示例代码:
public interface ICharacter
{
Fraction Team { get; }
bool IsDead { get; }
float Health { get; }
float MaxHealth { get; }
void TakeDamage(DamageInfo damageInfo);
void ApplyBuff(IBuff buff);
void Heal(float amount);
}
public interface IDamageSource
{
DamageInfo CreateDamage();
AttackType DamageType { get; }
float DamageValue { get; }
}
1.2 引入服务定位器模式
问题: Manager类直接持有引用,系统间耦合度高
建议:
public static class GameServices
{
private static readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
public static void Register<T>(T service) where T : class
{
services[typeof(T)] = service;
}
public static T Get<T>() where T : class
{
if (services.TryGetValue(typeof(T), out var service))
{
return service as T;
}
Debug.LogError($"Service {typeof(T)} not found!");
return null;
}
public static void Clear()
{
services.Clear();
}
}
// 使用示例
public class BattleManager : MonoBehaviour
{
public void Initialize()
{
GameServices.Register<IBattleService>(this);
GameServices.Register<ICharacterService>(new CharacterService());
GameServices.Register<IBuffService>(new BuffService());
}
}
// 在其他类中使用
var battleService = GameServices.Get<IBattleService>();
1.3 建立消息总线系统
问题: 当前事件系统分散在各个类中,难以追踪和调试
建议:
public enum GameEvent
{
// 角色事件
CharacterDied,
CharacterSpawned,
CharacterRevived,
// 战斗事件
DamageDealt,
DamageTaken,
AttackBlocked,
AttackDodged,
CriticalHit,
// 物品事件
ItemAcquired,
ItemUsed,
ItemDiscarded,
WeaponSwitched,
// Buff事件
BuffApplied,
BuffRemoved,
BuffExpired,
// 游戏状态事件
WaveStarted,
WaveCleared,
BossAppeared,
BossDefeated,
// 系统事件
GamePaused,
GameResumed,
CheckpointReached
}
public class GameEventBus
{
private static readonly Dictionary<GameEvent, Action<GameEventArgs>>
eventHandlers = new Dictionary<GameEvent, Action<GameEventArgs>>();
public static void Subscribe(GameEvent eventType, Action<GameEventArgs> handler)
{
if (!eventHandlers.ContainsKey(eventType))
{
eventHandlers[eventType] = handler;
}
else
{
eventHandlers[eventType] += handler;
}
}
public static void Unsubscribe(GameEvent eventType, Action<GameEventArgs> handler)
{
if (eventHandlers.ContainsKey(eventType))
{
eventHandlers[eventType] -= handler;
}
}
public static void Publish(GameEvent eventType, GameEventArgs args = null)
{
if (eventHandlers.TryGetValue(eventType, out var handler))
{
handler?.Invoke(args);
}
}
}
public class GameEventArgs
{
public object Sender { get; set; }
public Dictionary<string, object> Data { get; set; } = new Dictionary<string, object>();
}
2. 角色系统改进
2.1 拆分CharacterBase
问题: CharacterBase类过于庞大,承担了太多职责
建议: 将其拆分为多个专门类
// 核心角色数据
public class CharacterData : ScriptableObject
{
public string characterId;
public string characterName;
public Fraction defaultFaction;
public AttributeData baseAttributes;
public VFXData vfxData;
public AudioContainer audioData;
public List<SerializableType> availableBuffs;
}
// 角色配置器
public class CharacterBuilder
{
private CharacterData data;
private List<ICharacterComponent> components = new List<ICharacterComponent>();
public CharacterBuilder SetData(CharacterData data) { ... }
public CharacterBuilder AddComponent<T>() where T : ICharacterComponent { ... }
public ICharacter Build() { ... }
}
// 组件接口
public interface ICharacterComponent
{
void Initialize(ICharacter character);
void Update(float deltaTime);
void Cleanup();
}
2.2 改进属性系统
问题: 当前属性使用字符串字典,缺少类型安全和IDE支持
建议:
// 属性ID枚举
public enum AttributeId
{
// 基础属性
MaxHealth,
CurrentHealth,
MaxEnergy,
CurrentEnergy,
MovementSpeed,
AttackSpeed,
// 战斗属性
PhysicalAttack,
PhysicalDefense,
EnergyAttack,
EnergyDefense,
CriticalRate,
CriticalDamage,
// 抗性
FireResistance,
IceResistance,
LightningResistance,
// 特殊属性
LifeSteal,
CooldownReduction,
}
// 属性修饰器
public interface IAttributeModifier
{
int Priority { get; }
AttributeId TargetAttribute { get; }
float Modify(float originalValue);
}
// 属性计算器
public class AttributeCalculator
{
private List<IAttributeModifier> modifiers = new List<IAttributeModifier>();
public float Calculate(AttributeId attributeId, float baseValue)
{
var applicableModifiers = modifiers
.Where(m => m.TargetAttribute == attributeId)
.OrderBy(m => m.Priority);
float result = baseValue;
foreach (var modifier in applicableModifiers)
{
result = modifier.Modify(result);
}
return result;
}
}
3. 战斗系统改进
3.1 建立战斗配置系统
问题: 战斗参数硬编码,难以平衡调整
建议:
[CreateAssetMenu(fileName = "BattleConfig", menuName = "Cielonos/Config/BattleConfig")]
public class BattleConfig : ScriptableObject
{
[Header("Damage Calculation")]
public float baseCriticalMultiplier = 1.5f;
public float maxCriticalMultiplier = 3.0f;
public float levelDamageBonus = 0.1f;
[Header("Breakthrough Thresholds")]
public float weakBreakthroughThreshold = 0.5f;
public float mediumBreakthroughThreshold = 0.75f;
public float heavyBreakthroughThreshold = 1.0f;
[Header("Hit Detection")]
public float hitstopDuration = 0.05f;
public float screenShakeIntensity = 0.1f;
[Header("Damage Numbers")]
public float damageNumberScale = 1.0f;
public float criticalScale = 1.5f;
public float damageNumberLifetime = 1.0f;
}
public class BattleConfigProvider
{
public static BattleConfig Config =>
Resources.Load<BattleConfig>("Config/BattleConfig");
}
3.2 改进攻击判定系统
问题: AttackArea承担了过多职责
建议:
// 攻击配置
[CreateAssetMenu(fileName = "AttackConfig", menuName = "Cielonos/Attack/AttackConfig")]
public class AttackConfig : ScriptableObject
{
public LayerMask targetLayers;
public float hitboxActiveDuration;
public Vector3 hitboxSize;
public Vector3 hitboxOffset;
public bool useRaycast;
public float raycastDistance;
}
// 命中结果
public struct HitResult
{
public ICharacter Target;
public Vector3 HitPoint;
public Vector3 HitNormal;
public bool IsCritical;
public float FinalDamage;
public DamageType DamageType;
}
// 命中事件
public class HitEventArgs : GameEventArgs
{
public HitResult HitResult { get; set; }
public ICharacter Attacker { get; set; }
}
4. 物品系统改进
4.1 建立物品数据库
问题: 物品管理分散在各处
建议:
[CreateAssetMenu(fileName = "ItemDatabase", menuName = "Cielonos/Items/Database")]
public class ItemDatabase : ScriptableObject
{
[SerializeField] private List<WeaponData> weapons = new List<WeaponData>();
[SerializeField] private List<ArmorData> armors = new List<ArmorData>();
[SerializeField] private List<ConsumableData> consumables = new List<ConsumableData>>();
public WeaponData GetWeapon(string id) => weapons.FirstOrDefault(w => w.Id == id);
public T GetItem<T>(string id) where T : ItemData
{
var field = typeof(ItemDatabase).GetField(typeof(T).Name.ToLower() + "s",
BindingFlags.NonPublic | BindingFlags.Instance);
var list = field?.GetValue(this) as IEnumerable<ItemData>;
return list?.FirstOrDefault(i => i.Id == id) as T;
}
}
// 物品生成器
public static class ItemFactory
{
public static IItem Create(ItemData data, int level = 1)
{
return data switch
{
WeaponData weaponData => CreateWeapon(weaponData, level),
ArmorData armorData => CreateArmor(armorData, level),
ConsumableData consumableData => CreateConsumable(consumableData),
_ => throw new ArgumentException($"Unknown item type: {data.GetType()}")
};
}
private static Weapon CreateWeapon(WeaponData data, int level)
{
var weapon = new Weapon();
weapon.Initialize(data, level);
return weapon;
}
}
5. AI系统改进
5.1 建立AI配置系统
问题: AI行为硬编码,缺乏配置化
建议:
[CreateAssetMenu(fileName = "AIConfig", menuName = "Cielonos/AI/AIConfig")]
public class AIConfig : ScriptableObject
{
[Header("Detection")]
public float detectionRange = 10f;
public float attackRange = 2f;
public float loseInterestRange = 20f;
[Header("Movement")]
public float preferredDistance = 5f;
public float strafeSpeed = 2f;
[Header("Decision Making")]
public float decisionInterval = 0.5f;
public float healthThresholdForRetreat = 0.3f;
public float energyThresholdForSpecial = 0.7f;
[Header("Behavior Weights")]
public float attackWeight = 1.0f;
public float defendWeight = 0.5f;
public float retreatWeight = 0.3f;
public float supportWeight = 0.4f;
}
[Serializable]
public class BehaviorState
{
public string stateName;
public BehaviorTree tree;
public List<Transition> transitions = new List<Transition>();
public float enterDelay;
}
[Serializable]
public class Transition
{
public string targetState;
public List<Condition> conditions = new List<Condition>();
}
[Serializable]
public abstract class Condition
{
public abstract bool Evaluate(IAIController controller);
}
6. 数据持久化改进
6.1 建立游戏存档系统
问题: 缺乏统一的存档管理
建议:
[System.Serializable]
public class GameSaveData
{
public string saveId;
public DateTime saveTime;
public int playerLevel;
public Vector3 playerPosition;
public List<ItemSaveData> inventory;
public List<string> unlockedAbilities;
public int currentZoneIndex;
public int currentScore;
public List<AchievementSaveData> achievements;
}
public interface ISaveSystem
{
void Save(GameSaveData data);
GameSaveData Load(string saveId);
List<string> GetAllSaves();
void DeleteSave(string saveId);
}
public class EasySaveAdapter : ISaveSystem
{
public void Save(GameSaveData data)
{
ES3.Save("save_" + data.saveId, data);
}
public GameSaveData Load(string saveId)
{
return ES3.Load<GameSaveData>("save_" + saveId);
}
public List<string> GetAllSaves()
{
// 实现保存文件列表获取
}
public void DeleteSave(string saveId)
{
ES3.DeleteKey("save_" + saveId);
}
}
7. UI系统改进
7.1 建立UI框架
问题: UI组件耦合度高,难以复用
建议:
public abstract class UIScreen : MonoBehaviour
{
protected bool isVisible;
public virtual void Show()
{
gameObject.SetActive(true);
OnShow();
isVisible = true;
}
public virtual void Hide()
{
OnHide();
gameObject.SetActive(false);
isVisible = false;
}
protected abstract void OnShow();
protected abstract void OnHide();
}
public class UIManager
{
private Stack<UIScreen> screenStack = new Stack<UIScreen>();
public void ShowScreen<T>() where T : UIScreen
{
var screen = GetScreen<T>();
if (screen != null)
{
screen.Show();
screenStack.Push(screen);
}
}
public void CloseCurrentScreen()
{
if (screenStack.Count > 0)
{
var screen = screenStack.Pop();
screen.Hide();
}
}
}
8. 代码规范与工具
8.1 增加代码注释
建议: 在关键类和方法添加XML文档注释
/// <summary>
/// 伤害信息结构体,包含所有与伤害计算相关的参数
/// </summary>
public struct DamageInfo
{
/// <summary>
/// 伤害来源
/// </summary>
public IDamageSource Source;
/// <summary>
/// 伤害值基数
/// </summary>
public float BaseDamage;
/// <summary>
/// 伤害类型
/// </summary>
public DamageType Type;
}
8.2 建立自定义编辑器工具
建议: 为复杂系统创建编辑器窗口
#if UNITY_EDITOR
public class CharacterEditorWindow : EditorWindow
{
[MenuItem("Cielonos/Character Editor")]
public static void OpenWindow()
{
GetWindow<CharacterEditorWindow>("Character Editor");
}
private void OnGUI()
{
// 创建角色编辑器UI
}
}
public class BuffEditorWindow : EditorWindow
{
[MenuItem("Cielonos/Buff Editor")]
public static void OpenWindow()
{
GetWindow<BuffEditorWindow>("Buff Editor");
}
}
#endif
三、改进优先级
P0 - 必须改进(阻塞性问题)
- 建立核心接口层
- 改进属性系统类型安全
- 建立消息总线
P1 - 重要改进(核心功能)
- 拆分CharacterBase
- 建立战斗配置系统
- 建立物品数据库
- 建立AI配置系统
P2 - 优化改进(提升开发效率)
- 建立存档系统
- 建立UI框架
- 增加代码注释
- 创建编辑器工具
P3 - 长期改进(架构优化)
- 服务定位器模式
- 组件化重构
- 配置化完善
四、总结
当前项目在架构上已经奠定了良好的基础,核心系统基本完备。要构建完善的Roguelike ARPG框架,重点需要:
- 抽象接口层: 建立清晰的接口边界,提高系统可测试性和可替换性
- 配置驱动: 将硬编码转为配置化,提高设计迭代效率
- 数据管理: 建立统一的数据管理系统,包括物品、敌人、AI等
- 代码规范: 增加注释和文档,提高代码可维护性
- 工具支持: 开发自定义编辑器工具,提高开发效率
文档生成日期: 2026-04-17
生成者: Game Designer Agent