C#中MasterFireList无法更新且删除异常问题求助
问题分析与修复方案
一、MasterFireList始终长度为1的原因及修复
核心原因
- 固定长度的位置数组:
FireLocations被初始化为长度为1的数组,每次调用CreateFires只传入一个位置,自然只能创建1个火对象,CreatedFires长度始终为1,MasterFireList每次仅添加1个元素。 - 浮点数精度导致位置匹配失败:
CreateFires方法中用positions.Contains(f.Position)筛选火对象时,Vector3作为值类型,浮点数精度误差会导致实际创建的火位置与传入位置无法精确匹配,最终可能只筛选到一个火。
修复代码
- 改用动态列表存储火位置,支持一次创建多个火:
// 替换原固定长度数组为动态List internal static List<Vector3> FireLocations = new List<Vector3>(); public static void CreateFires(bool IsGasFire) { FireLocations.Clear(); // 示例:添加3个不同位置的火(玩家前方1/2/3米处) FireLocations.Add(Game.LocalPlayer.Character.GetOffsetPositionFront(1f)); FireLocations.Add(Game.LocalPlayer.Character.GetOffsetPositionFront(2f)); FireLocations.Add(Game.LocalPlayer.Character.GetOffsetPositionFront(3f)); // 补全Util.CreateFires的缺失参数(maxChildren、bigFires等) CreatedFires = Util.CreateFires(FireLocations.ToArray(), 0, IsGasFire, false); foreach (FireEx f in CreatedFires) { f.Fire.DesiredBurnDuration = 30.0f; f.Fire.SpreadRadius = 2.0f; MasterFireList.Add(f); } Game.LogTrivial($"CreatedFires Length: {CreatedFires.Length}"); }
- 修复位置匹配的精度问题,用距离阈值替代精确匹配:
public static FireEx[] CreateFires(Vector3[] positions, int maxChildren, bool isGasFire, bool bigFires, bool onGround = true) { uint[] handles = new uint[positions.Length]; List<Vector3> adjustedPositions = new List<Vector3>(); for (int i = 0; i < positions.Length; i++) { Vector3 p = positions[i]; if (onGround) { float? z = World.GetGroundZ(p, false, true); if (z.HasValue) { p.Z = z.Value; } } adjustedPositions.Add(p); handles[i] = NativeFunction.Natives.StartScriptFire<uint>(p.X, p.Y, p.Z, maxChildren, isGasFire); } // 用0.1米的距离阈值判断位置是否匹配,规避浮点数精度问题 FireEx[] fires = World.GetAllFires() .Where(f => adjustedPositions.Any(pos => Vector3.Distance(pos, f.Position) < 0.1f)) .Select(f => { int index = adjustedPositions.FindIndex(pos => Vector3.Distance(pos, f.Position) < 0.1f); return bigFires ? new BigFireEx(handles[index], f) : new FireEx(handles[index], f); }) .ToArray(); return fires; }
二、删除时仅最后一项被删除的原因及修复
核心原因
- 正向循环删除的索引混乱:正向
for循环中,执行MasterFireList.RemoveAt(i)后,列表元素会前移,循环变量i自增会跳过下一个待删除元素。 - 静态数组的引用覆盖:
CreatedFires是静态数组,每次调用CreateFires会覆盖旧引用,导致DeleteFires只能处理最后一次创建的火。
修复代码
改用反向遍历删除,直接操作MasterFireList而非依赖CreatedFires:
public static void DeleteFires() { if (MasterFireList == null) return; // 反向遍历,避免删除元素后索引偏移导致的跳过问题 for (int i = MasterFireList.Count - 1; i >= 0; i--) { FireEx fireEx = MasterFireList[i]; if (fireEx.Fire != null) { fireEx.Fire.Delete(); MasterFireList.RemoveAt(i); } } // 清空残留引用,避免内存泄漏 CreatedFires = null; FireLocations.Clear(); }
额外建议
- 静态列表
MasterFireList易引发内存泄漏,使用后务必及时清空。 - 尽量减少全局静态变量的使用,优先用实例变量管理状态。
内容的提问来源于stack exchange,提问作者John35352
相关产品推荐
相关产品推荐

