You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中MasterFireList无法更新且删除异常问题求助

问题分析与修复方案

一、MasterFireList始终长度为1的原因及修复

核心原因

  1. 固定长度的位置数组:FireLocations被初始化为长度为1的数组,每次调用CreateFires只传入一个位置,自然只能创建1个火对象,CreatedFires长度始终为1,MasterFireList每次仅添加1个元素。
  2. 浮点数精度导致位置匹配失败:CreateFires方法中用positions.Contains(f.Position)筛选火对象时,Vector3作为值类型,浮点数精度误差会导致实际创建的火位置与传入位置无法精确匹配,最终可能只筛选到一个火。

修复代码

  1. 改用动态列表存储火位置,支持一次创建多个火:
// 替换原固定长度数组为动态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}");
}
  1. 修复位置匹配的精度问题,用距离阈值替代精确匹配:
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;
}

二、删除时仅最后一项被删除的原因及修复

核心原因

  1. 正向循环删除的索引混乱:正向for循环中,执行MasterFireList.RemoveAt(i)后,列表元素会前移,循环变量i自增会跳过下一个待删除元素。
  2. 静态数组的引用覆盖: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:04:59