mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 12:37:12 +08:00
(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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user