由于线程原因,实例化无法工作
本文关键字:实例化 工作 于线程 线程 | 更新日期: 2023-09-27 18:07:30
我收到以下错误
" internal_call_internal_instantiatessingle只能从主线程调用。"当加载场景时,构造函数和字段初始化函数将从加载线程执行。"不要在构造函数或字段初始化器中使用此函数,而是将初始化代码移动到Awake或Start函数中。"
每当我尝试使用这个函数实例化一些GameObject's
时:
public void DisplayCalls () {
for (int i = 0; i < calls [0].Count; i++) {
for (int j = 0; j < impFields.Length; j++) {
GameObject textClone = Instantiate (textBox, Vector3.zero, Quaternion.Euler(Vector3.zero)) as GameObject;
textClone.transform.SetParent (canvas.transform);
Text text = textClone.GetComponent <Text> ();
text.text = calls[impFields [j]][i];
text.alignment = TextAnchor.MiddleCenter;
textClone.transform.localPosition = new Vector3 (-262.5f + (175f * j), (182f + (30f * i)), 0f);
}
}
}
这个函数是通过另一个函数调用的:
public void GetPanelInfo () {
string file = "getpanelinfo.php";
string hash = Md5Sum (mostRecentID.ToString () + SecretKey1 + SecretKey2);
string parameters = "?mostrecentid=" + mostRecentID.ToString () + "&hash=" + hash;
string fullURL = baseURL + file + parameters;
Uri fullURI = new Uri (fullURL);
WebClient client = new WebClient ();
string jsonString = string.Empty;
client.DownloadStringCompleted += (sender, e) => {
if (!e.Cancelled && e.Error == null) {
jsonString = e.Result;
JSONNode json = JSON.Parse (jsonString);
for (int i = 0; i < json["calls"].Count; i++) {
for (int j = 0; j < calls.Length; j++) {
calls[j].Add (json["calls"][i][names [j]]);
}
mostRecentID = json["calls"][i]["callID"].AsInt;
}
} else if (e.Cancelled && e.Error == null) {
Debug.Log ("Cancelled");
} else {
Debug.Log ("Error: " + e.Error);
}
loading = false;
LogCalls ();
DisplayCalls ();
};
client.DownloadStringAsync (fullURI);
}
使用按钮调用一次。
我似乎找不到问题,但如上所述,错误说这是一个线程问题,我不能从主线程以外的另一个线程调用instantiate。我不知道如何将实例化更改为另一个线程,但任何帮助解决这个问题将非常感激。
你可以尝试使用UnityEvent来通知主线程事件。代码看起来像下面这样:
using UnityEngine.Events;
public class YourClass : MonoBehaviour
{
private UnityEvent m_MyEvent = new UnityEvent();
void Start()
{
m_MyEvent.AddListener(DisplayCalls);
}
public void GetPanelInfo () {
...
// instead of this :
// DisplayCalls ();
// do this:
m_MyEvent.Invoke();
}
}
摘自我在游戏开发交流会上提出的相同问题。
查看WebClient文档,该方法描述为:
从资源下载
string
,不阻塞调用线程。
并给出错误信息:
INTERNAL_CALL_Internal_InstantiateSingle
只能从主线程调用
很明显,您需要下载数据并存储它,并且在下载完成后仅在主线程中调用DisplayCells
。这与Cocoa不同,例如,你只能在主线程上调用与ui相关的API方法。
我花了一些时间在谷歌上寻找有关这方面的合适信息(我是Unity/c#的初学者),但我认为这个可以做到:
创建一个布尔值,表示有数据要显示:
private bool _callsToDisplay = false;
数据下载完成后设置:
client.DownloadStringCompleted += (sender, e) => {
...
loading = false;
LogCalls ();
_callsToDisplay = true;
};
,然后在Update()
方法(运行在主线程上)中,如果设置了该布尔值,则调用DisplayCalls()
:
void Update()
{
if (_callsToDisplay) {
DisplayCalls();
_callsToDisplay = false;
}
}