首页 > 解决方案 > Unity 对象引用丢失

问题描述

我正在尝试为我的体素游戏设置保存系统。一切正常,除了由于 System.NullReferenceException 导致保存文件不保存的可能性很小(如 1/8)。

我已经多次查看代码并且很困惑为什么有时会抛出这个异常。在游戏中,我没有将 RegionData 引用设置为 null。我可以再次按“保存”,一切都会正常进行。

    [MessagePackObject]
    public class RegionData
    {
        [Key(0)]
        public Vector2Int Position { get; set; } = new Vector2Int(0, 0);
        [Key(1)]
        public ChunkData[][] Chunks { get; set; }
        
        // Used when opening a saved region data.
        public RegionData()
        {
            
        }

        // Used when creating a new region data.
        public RegionData(Vector2Int regionPosition)
        {
            Position = regionPosition;
            Chunks = Utilities.CreateJaggedArray<ChunkData[][]>(16, 16);
        }
    }

    public class RegionSaver
    {
        readonly List<RegionData> pendingRegions;
        readonly Queue<RegionData> regionsReady;
        static readonly int SaveDelay = 4000;
        
        public RegionSaver()
        {
            pendingRegions = new List<RegionData>(10);
            regionsReady = new Queue<RegionData>(10);
            SaveRegionsFromQueue();
        }

        public async Task AddRegionData(RegionData regionData)
        {
            if (pendingRegions.Contains(regionData))
                return;           
            
            pendingRegions.Add(regionData);

            await Task.Delay(SaveDelay).ConfigureAwait(false);
            
            if (pendingRegions.Contains(regionData))
            {
                regionsReady.Enqueue(regionData);
                pendingRegions.Remove(regionData);
            }
        }

        // Infinite loop that saves Regions that have been pushed to the queue.
        async void SaveRegionsFromQueue()
        {
            await Task.Run(async () =>
            {
                while (true)
                {
                    while (regionsReady.Count > 0)
                    {
                        var regionData = regionsReady.Dequeue();
                        // This is were 'regionData' is sometimes null.

                        try
                        {
                            await SaveRegion(regionData).ConfigureAwait(false);
                        }
                        catch (Exception e)
                        {
                            Debug.LogError($"Error whiles trying to save Region.\nException: {e}");
                        }
                    }

                    await Task.Delay(TimeSpan.FromSeconds(1f)).ConfigureAwait(false);
                }
            });
        }
        
        async Task SaveRegion(RegionData regionData)
        {                       
            using (var fileStream = File.Create(
                    string.Format(RegionLoader.RegionDataFilePath, regionData.Position.x, regionData.Position.y)))
            {
                await MessagePackSerializer.SerializeAsync(fileStream, regionData, Utilities.Lz4Options)
                    .ConfigureAwait(false);
            }  
        }
    }

如何调用 AddRegionData 方法。Task.Run(() => chunkHandler.RegionSaver.AddRegionData(regionData));

标签: c#unity3d

解决方案


我想我解决了我的问题。用ConcurrentQueueConcurrentDictionary替换我已经用 Dictionary 替换的 Queue 和 List会导致没有空引用。我不知道并发会导致如此奇怪的问题。


推荐阅读