如何防止添加到 List 的 类 实例在 IEnumerator 方法中被销毁?
How to prevent instances of classes that are added to a List from being destroyed in an IEnumerator method?
如果你能帮我解决这个问题,我将不胜感激。
OpponentItem 的字段 class 应该用来自 collectItems 的数据填充。
我们对手的物品将列在 opponentList 中,其数据来自 incomingData。因为我不知道 StartCoroutine 何时结束 collectData 方法设置 progressBar 和 Update 检查 opponentList 的元素。
不幸的是,方法中实例化的 OpponentItem 对象已不存在,因此列表为空。
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
public class OpponentItem {
public int item_id ;
public string item_type;
public string item_name;
public int item_star;
public int item_bonus;
public OpponentItem() : base(){
}
}
public class TestBug : MonoBehaviour {
public List<OpponentItem> opponentList;
private float barValue;
public bool isDone;
public static string[] collectItems = new string[5]{
"item_id=12",
"item_type=Weapon",
"item_name=Sword",
"item_star=2",
"item_bonus=10",
};
public string[] incomingData;
public float progressBar {
get{
return barValue;
}
set{
barValue = value;
isDone = true;
}
}
void Start () {
isDone = false;
string joined = System.String.Join("|", collectItems);
incomingData = new string[5];
incomingData[0] = joined;
incomingData[1] = joined;
incomingData[2] = joined;
incomingData[3] = joined;
incomingData[4] = joined;
opponentList = new List<OpponentItem>();
StartCoroutine(collectData<OpponentItem>(opponentList, incomingData, collectItems));
}
void Update(){
if (isDone){
isDone = false;
Debug.Log(opponentList[1].item_id);
}
}
public IEnumerator collectData<T>(List<T> list, string[] tempArray, string[] queryArray) where T : new() {
list = new List<T>(tempArray.Length);
for(int h = 0; h < tempArray.Length ; h++){
list.Add(new T());
string[] mybox = new string[queryArray.Length];
mybox = tempArray[h].Split('|');
for (int k = 0; k < queryArray.Length ; k++){
string[] inbox = new string[2];
inbox = mybox[k].Split('=');
if (list[h].GetType().GetField(inbox[0]).FieldType.FullName == "System.Int32"){
list[h].GetType().GetField(inbox[0]).SetValue(list[h], Int32.Parse(inbox[1]));
Debug.Log(list[h].GetType().GetField(inbox[0]).GetValue(list[h]));
}
else if(list[h].GetType().GetField(inbox[0]).FieldType.FullName == "System.Single"){
list[h].GetType().GetField(inbox[0]).SetValue(list[h], Single.Parse(inbox[1]));
Debug.Log(list[h].GetType().GetField(inbox[0]).GetValue(list[h]));
}
else{
list[h].GetType().GetField(inbox[0]).SetValue(list[h], inbox[1]);
Debug.Log(list[h].GetType().GetField(inbox[0]).GetValue(list[h]));
}
}
}
yield return new WaitForSeconds(0.2f);
progressBar += 0.5f;
}
}
这是一个问题。您的列表将始终为空,因为默认情况下参数是按值传递的(请参阅此 MSDN link)
opponentList = new List<OpponentItem>();
StartCoroutine(collectData<OpponentItem>(opponentList, incomingData, collectItems));
分配 list = new List<T>(tempArray.Length)
后,您会将项目添加到新的列表引用中,而不是传递到 collectData() 的列表引用中。
您有 2 个选择:
1) 清除列表而不是重新分配
public IEnumerator collectData<T>(List<T> list, string[] tempArray, string[] queryArray) where T : new() {
// list = new List<T>(tempArray.Length); // ** problem
list.Clear(); // ** try clearing the list instead
for(int h = 0; h < tempArray.Length ; h++){
2) 通过引用传递列表
opponentList = new List<OpponentItem>();
StartCoroutine(collectData<OpponentItem>(ref opponentList, incomingData, collectItems));
}
public IEnumerator collectData<T>(ref List<T> list, string[] tempArray, string[] queryArray) where T : new() {
list = new List<T>(tempArray.Length);
如果你能帮我解决这个问题,我将不胜感激。
OpponentItem 的字段 class 应该用来自 collectItems 的数据填充。
我们对手的物品将列在 opponentList 中,其数据来自 incomingData。因为我不知道 StartCoroutine 何时结束 collectData 方法设置 progressBar 和 Update 检查 opponentList 的元素。
不幸的是,方法中实例化的 OpponentItem 对象已不存在,因此列表为空。
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
public class OpponentItem {
public int item_id ;
public string item_type;
public string item_name;
public int item_star;
public int item_bonus;
public OpponentItem() : base(){
}
}
public class TestBug : MonoBehaviour {
public List<OpponentItem> opponentList;
private float barValue;
public bool isDone;
public static string[] collectItems = new string[5]{
"item_id=12",
"item_type=Weapon",
"item_name=Sword",
"item_star=2",
"item_bonus=10",
};
public string[] incomingData;
public float progressBar {
get{
return barValue;
}
set{
barValue = value;
isDone = true;
}
}
void Start () {
isDone = false;
string joined = System.String.Join("|", collectItems);
incomingData = new string[5];
incomingData[0] = joined;
incomingData[1] = joined;
incomingData[2] = joined;
incomingData[3] = joined;
incomingData[4] = joined;
opponentList = new List<OpponentItem>();
StartCoroutine(collectData<OpponentItem>(opponentList, incomingData, collectItems));
}
void Update(){
if (isDone){
isDone = false;
Debug.Log(opponentList[1].item_id);
}
}
public IEnumerator collectData<T>(List<T> list, string[] tempArray, string[] queryArray) where T : new() {
list = new List<T>(tempArray.Length);
for(int h = 0; h < tempArray.Length ; h++){
list.Add(new T());
string[] mybox = new string[queryArray.Length];
mybox = tempArray[h].Split('|');
for (int k = 0; k < queryArray.Length ; k++){
string[] inbox = new string[2];
inbox = mybox[k].Split('=');
if (list[h].GetType().GetField(inbox[0]).FieldType.FullName == "System.Int32"){
list[h].GetType().GetField(inbox[0]).SetValue(list[h], Int32.Parse(inbox[1]));
Debug.Log(list[h].GetType().GetField(inbox[0]).GetValue(list[h]));
}
else if(list[h].GetType().GetField(inbox[0]).FieldType.FullName == "System.Single"){
list[h].GetType().GetField(inbox[0]).SetValue(list[h], Single.Parse(inbox[1]));
Debug.Log(list[h].GetType().GetField(inbox[0]).GetValue(list[h]));
}
else{
list[h].GetType().GetField(inbox[0]).SetValue(list[h], inbox[1]);
Debug.Log(list[h].GetType().GetField(inbox[0]).GetValue(list[h]));
}
}
}
yield return new WaitForSeconds(0.2f);
progressBar += 0.5f;
}
}
这是一个问题。您的列表将始终为空,因为默认情况下参数是按值传递的(请参阅此 MSDN link)
opponentList = new List<OpponentItem>();
StartCoroutine(collectData<OpponentItem>(opponentList, incomingData, collectItems));
分配 list = new List<T>(tempArray.Length)
后,您会将项目添加到新的列表引用中,而不是传递到 collectData() 的列表引用中。
您有 2 个选择:
1) 清除列表而不是重新分配
public IEnumerator collectData<T>(List<T> list, string[] tempArray, string[] queryArray) where T : new() {
// list = new List<T>(tempArray.Length); // ** problem
list.Clear(); // ** try clearing the list instead
for(int h = 0; h < tempArray.Length ; h++){
2) 通过引用传递列表
opponentList = new List<OpponentItem>();
StartCoroutine(collectData<OpponentItem>(ref opponentList, incomingData, collectItems));
}
public IEnumerator collectData<T>(ref List<T> list, string[] tempArray, string[] queryArray) where T : new() {
list = new List<T>(tempArray.Length);