我正在嘗試計算串列中的專案(int id)。這樣做:
int currentId = -1;
int count = 0;
foreach (var item in rawItemList) {
UnityEngine.Debug.LogFormat("Item {0}", item);
if (currentId != item) {
AddItem(currentId, count);
count = 0;
}
currentId = item;
count ;
UnityEngine.Debug.LogFormat("Count {0}", count);
}
這是AddItem功能:
void AddItem(int itemId, int count) {
UnityEngine.Debug.LogFormat("Add item {0} count {1}", itemId, count);
if (count == 0) return;
items.Add(itemId);
counts.Add(count);
}
rawItemList,items并且counts都是NativeList<int>.
rawItemList-中有 7 個元素{0, 0, 2, 2, 3, 4, 4}。在上述回圈之前和之后列印那些效果很好(列印所有元素)。
我遇到的問題是,在第二次AddItem呼叫之后,foreach 回圈退出,甚至沒有在rawItemList. 也許值得一提的是,這段代碼發生在建構式中。這里有我沒有看到的錯誤嗎?
控制臺日志:
Item 0
Add item -1 count 0
Count 1
Item 0
Count 2
Item 2
Add item 0 count 2
Count 1
// Loop exits here
編輯:剛剛檢查了標準 for 回圈。這種方式作業得很好。foreach 有什么問題?
編輯 2:插入完整代碼。最后一項被添加到回圈之外。
// public struct CountedItemList ...
public NativeList<int> items;
public NativeList<int> counts;
public CountedItemList(NativeList<int> rawItemList) {
items = new NativeList<int>(Allocator.Temp);
counts = new NativeList<int>(Allocator.Temp);
if (rawItemList.Length == 0) return;
rawItemList.Sort();
int currentId = -1;
int count = 0;
foreach (var item in rawItemList) {
UnityEngine.Debug.LogFormat("Item {0}", item);
if (currentId != item) {
AddItem(currentId, count);
count = 0;
}
currentId = item;
count ;
UnityEngine.Debug.LogFormat("Count {0}", count);
}
AddItem(currentId, count);
}
從另一個腳本中呼叫它是這樣的:
NativeList<int> rawItemList = new NativeList<int>(Allocator.Temp);
// Populate items
var cil = new CountedItemList(rawItemList);
rawItemList.Dispose();
編輯 3:在編輯 1 中,我已替換
foreach(var item in rawItemList) {
和
for(int i = 0; i < rawItemList.Length; i {
int item = rawItemList[i];
其余代碼保持不變,但行為發生了變化。
uj5u.com熱心網友回復:
正如所說的純邏輯明智,我無法重現這一點。
但是,我或多或少地像這樣在 Unity 中實作了你所擁有的
public class Test : MonoBehaviour
{
private CountedItemList cil;
private void Start()
{
NativeList<int> rawItemList = new NativeList<int>(Allocator.Temp);
// Populate items
rawItemList.Add(0);
rawItemList.Add(0);
rawItemList.Add(2);
rawItemList.Add(2);
rawItemList.Add(2);
rawItemList.Add(3);
rawItemList.Add(3);
rawItemList.Add(4);
cil = new CountedItemList(rawItemList);
rawItemList.Dispose();
}
private void OnDestroy()
{
cil?.Dispose();
}
}
public class CountedItemList : IDisposable
{
public NativeList<int> items;
public NativeList<int> counts;
public CountedItemList(NativeList<int> rawItemList)
{
items = new NativeList<int>(Allocator.Temp);
counts = new NativeList<int>(Allocator.Temp);
if (rawItemList.Length == 0) return;
rawItemList.Sort();
var currentId = -1;
var count = 0;
//for(var i = 0; i < rawItemList.Length; i )
//{
// var item = rawItemList[i];
foreach (var item in rawItemList)
{
UnityEngine.Debug.LogFormat("Item {0}", item);
if (currentId != item)
{
AddItem(currentId, count);
count = 0;
}
currentId = item;
count ;
UnityEngine.Debug.LogFormat("Count {0}", count);
}
AddItem(currentId, count);
}
void AddItem(int itemId, int count)
{
UnityEngine.Debug.LogFormat("Add item {0} count {1}", itemId, count);
if (count == 0) return;
items.Add(itemId);
counts.Add(count);
}
public void Dispose()
{
items.Dispose();
counts.Dispose();
}
}
這導致了一個不可忽視的例外
ObjectDisposedException: The Unity.Collections.NativeList`1[System.Int32] has been deallocated, it is not allowed to access it
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <86acb61e0d2b4b36bc20af11093be9a5>:0)
Unity.Collections.NativeArray`1[T].CheckElementReadAccess (System.Int32 index) (at <86acb61e0d2b4b36bc20af11093be9a5>:0)
Unity.Collections.NativeArray`1[T].get_Item (System.Int32 index) (at <86acb61e0d2b4b36bc20af11093be9a5>:0)
Unity.Collections.NativeArray`1 Enumerator[T].get_Current () (at <86acb61e0d2b4b36bc20af11093be9a5>:0)
CountedItemList..ctor (Unity.Collections.NativeList`1[T] rawItemList) (at Assets/Scripts/ExamplePart.cs:24)
Test.Start () (at Assets/Scripts/Test.cs:24)
指著線
foreach (var item in rawItemList)
我認為解釋類似于
使用的NativeList<int>.GetEnumeratorbyforeach似乎是異步迭代的。你馬上做
var cil = new CountedItemList(rawItemList);
rawItemList.Dispose();
所以rawItemList.Dispose();似乎在迭代通過foreach完成之前被呼叫。
另一方面,for沒有使用特殊的列舉器,而是使用同步索引訪問,所以這里確保建構式在串列被處理之前完成。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/517265.html
標籤:C#unity3d前锋
下一篇:如何在房間之間移動氧氣?
