(client) feat:添加基地界面到游玩界面的过程,添加存档管理,技能树变得可用 (#58)

Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com>
Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/58
This commit is contained in:
2025-10-03 00:31:34 +08:00
parent aff747be17
commit dd9d90439d
134 changed files with 10322 additions and 4872 deletions

View File

@@ -293,6 +293,7 @@ namespace Managers
var factionKey = def.attributes.defName ?? "default";
_pendingAdditions.Add(Tuple.Create(dimensionId, factionKey, entityComponent));
return entityComponent;
}
catch (Exception ex)
@@ -363,7 +364,7 @@ namespace Managers
/// <param name="dimensionId">实体所属的维度ID。</param>
/// <param name="entityDef">实体定义对象。</param>
/// <param name="pos">生成位置。</param>
public EntityPrefab GenerateEntity(string dimensionId, EntityDef entityDef, Vector3 pos)
public EntityPrefab GenerateCharacterEntity(string dimensionId, EntityDef entityDef, Vector3 pos)
{
if (!characterPrefab)
{
@@ -607,7 +608,7 @@ namespace Managers
Relation targetRelationship)
{
// 参数校验:确保输入参数有效,避免空引用异常。
if (sourceEntityPrefab == null || sourceEntityPrefab.entity == null)
if (!sourceEntityPrefab || !sourceEntityPrefab.entity)
{
Debug.LogWarning("实体管理器FindNearestEntityByRelation 方法中,源实体预制体或其内部实体为空。无法执行搜索。");
return null;
@@ -620,137 +621,111 @@ namespace Managers
return null;
}
// 初始化追踪变量:设置初始值,用于在遍历过程中追踪最近的实体及其距离。
// 使用平方距离 (SqrMagnitude) 可以避免在每次距离计算时进行昂贵的开方运算,从而提高性能。
EntityPrefab nearestTarget = null;
var minDistanceSqr = float.MaxValue;
var sourcePos = sourceEntityPrefab.transform.position;
// 关系管理器实例检查:确保 AffiliationManager 可用,它是判断实体关系的核心组件。
var affiliationManager = AffiliationManager.Instance;
if (affiliationManager == null)
foreach (var (currentFactionKey, factionEntities) in factionDict)
{
Debug.LogError("实体管理器FindNearestEntityByRelation 方法中AffiliationManager 实例为空。无法确定实体关系。");
return null;
}
var factionRelation = affiliationManager.GetRelation(sourceEntityPrefab.entity.affiliation, currentFactionKey);
// 遍历所有派系和实体_dimensionFactionEntities 按维度和派系组织,需要遍历所有派系才能找到维度内的所有实体。
foreach (var factionEntities in factionDict.Values) // factionDict.Values 是 LinkedList<EntityPrefab> 的集合
{
if (factionRelation != targetRelationship)
{
continue;
}
foreach (var currentEntityPrefab in factionEntities)
{
// 实体有效性及排除源实体自身:
// 1. 排除无效或已死亡的实体,确保只处理活跃的实体。
// 2. 在寻找“最近”实体时,通常指的是 *除了自身以外* 的实体。
// 如果需要包含自身(例如,当 targetRelationship 是 AffiliationManager.Relation.Self 时),
// 可以根据具体需求调整此逻辑,但默认行为是排除自身。
if (!currentEntityPrefab || !currentEntityPrefab.entity ||
currentEntityPrefab.entity.IsDead || currentEntityPrefab == sourceEntityPrefab)
{
continue;
}
// 关系判断:使用 AffiliationManager 提供的接口判断源实体与当前遍历实体之间的关系。
var currentRelation =
affiliationManager.GetRelation(sourceEntityPrefab.entity, currentEntityPrefab.entity);
if (currentRelation == targetRelationship)
if (currentEntityPrefab.entity is not CombatantEntity)
{
// 距离计算与最近实体更新:
// 1. 计算与源实体的距离(使用平方距离优化)。
// 2. 如果当前实体更近,则更新 nearestTarget 和 minDistanceSqr。
var distanceSqr = Vector3.SqrMagnitude(currentEntityPrefab.transform.position - sourcePos);
if (distanceSqr < minDistanceSqr)
{
minDistanceSqr = distanceSqr;
nearestTarget = currentEntityPrefab;
}
continue;
}
var distanceSqr = Vector3.SqrMagnitude(currentEntityPrefab.transform.position - sourcePos);
if (distanceSqr < minDistanceSqr)
{
minDistanceSqr = distanceSqr;
nearestTarget = currentEntityPrefab;
}
}
}
return nearestTarget; // 返回找到的最近实体
return nearestTarget;
}
/// <summary>
/// 在指定维度中,判断是否存在任何与源实体敌对的活跃实体。
/// 此版本修正了将掉落物或子弹识别为敌对派系的问题,现在只考虑可转换为 CombatantEntity 的实体。
/// 并优化了搜索逻辑,通过先判断派系关系来减少不必要的实体遍历。
/// </summary>
/// <param name="dimensionId">要搜索的维度ID。</param>
/// <param name="sourceEntityPrefab">作为参照的源实体预制体。</param>
/// <returns>如果存在敌对的 CombatantEntity 则返回 true否则返回 false。</returns>
public bool ExistsHostile(string dimensionId, EntityPrefab sourceEntityPrefab)
{
// 参数校验:确保输入参数有效,避免空引用异常。
// 使用 Unity 的 null 检查运算符 '!'
if (!sourceEntityPrefab || !sourceEntityPrefab.entity)
{
Debug.LogWarning("实体管理器ExistsHostile 方法中,源实体预制体或其内部实体为空。无法执行搜索。");
return false;
}
// 新增校验:确保源实体自身是一个 CombatantEntity。
// 因为我们现在只关注 CombatantEntity 之间的敌对关系。
var sourceCombatant = sourceEntityPrefab.entity as CombatantEntity;
if (!sourceCombatant) // 使用 Unity 的 null 检查运算符 '!'
if (!sourceCombatant)
{
Debug.LogWarning(
$"实体管理器ExistsHostile 方法中,源实体 '{sourceEntityPrefab.name}' 无法转换为 CombatantEntity 类型。无法有效判断是否存在敌对的活跃实体。");
return false;
}
if (sourceCombatant.IsDead)
{
return false; // 源 CombatantEntity 已经失效,它无法判断敌对实体。
return false;
}
// 维度数据存在性检查:验证目标维度是否在实体管理器的内部数据结构中被初始化和管理。
if (!_dimensionFactionEntities.TryGetValue(dimensionId, out var factionDict))
{
Debug.LogWarning($"实体管理器ExistsHostile 方法中,维度 '{dimensionId}' 未被初始化或未在内部管理实体。");
return false;
}
// 遍历所有实体:遍历维度内的所有派系,再遍历每个派系下的所有实体。
foreach (var factionEntities in factionDict.Values)
var affiliationManager = AffiliationManager.Instance; // 获取 AffiliationManager 实例一次
foreach (var (currentFactionKey, factionEntities) in factionDict)
{
var factionRelation = affiliationManager.GetRelation(sourceCombatant.affiliation, currentFactionKey);
if (factionRelation != Relation.Hostile)
{
continue;
}
foreach (var currentEntityPrefab in factionEntities)
{
// 实体有效性及排除源实体自身:
// 1. 排除无效的实体预制体或内部实体。
// 2. 排除已失效的 CombatantEntity。
// 3. 排除源实体自身,避免自身判断为敌对。
if (!currentEntityPrefab || !currentEntityPrefab.entity ||
currentEntityPrefab == sourceEntityPrefab) // 源实体自身已被转换为 sourceCombatant 并检查,这里只检查 prefab 引用是否相同
if (currentEntityPrefab == null || currentEntityPrefab.entity == null ||
currentEntityPrefab == sourceEntityPrefab)
{
continue;
}
// 【核心改动】新增类型检查:只有能转换为 CombatantEntity 的实体才会被进一步判断。
// 这样可以排除掉落物、子弹等非 CombatantEntity 的实体。
var currentCombatant = currentEntityPrefab.entity as CombatantEntity;
if (!currentCombatant) // 使用 Unity 的 null 检查运算符 '!'
if (currentCombatant == null || currentCombatant.IsDead)
{
continue; // 如果不是 CombatantEntity则跳过此实体。
}
// 检查目标 CombatantEntity 是否已失效(死亡或摧毁)。
// 同理,这里假设 CombatantEntity 包含 IsDead 属性。
// **重要:请确保 CombatantEntity 定义了 IsDead 属性,或者替换为更通用的失效状态属性。**
if (currentCombatant.IsDead)
{
continue; // 目标 CombatantEntity 已经失效,不是活跃的敌对实体。
}
// 关系判断:判断当前 CombatantEntity 与源 CombatantEntity 是否为“敌对”关系。
// AffiliationManager.GetRelation 应该接收 CombatantEntity 类型。
if (AffiliationManager.Instance.GetRelation(sourceCombatant, currentCombatant) == Relation.Hostile)
{
return true; // 找到第一个敌对的 CombatantEntity 即返回 true提高效率。
continue;
}
return true;
}
}
return false; // 遍历完所有实体都未找到敌对的 CombatantEntity。
return false;
}
/// <summary>
@@ -913,6 +888,7 @@ namespace Managers
$"实体管理器在场景加载初始化期间Program 为ID '{dimensionId}' 注册了一个空的 Dimension 对象。这可能表明维度注册存在问题。");
}
}
Clock.AddTick(this);
}
/// <summary>