我收到以下错误
" INTERNAL_CALL_Internal_InstantiateSingle只能从主线程调用。" "在加载场景时,将从加载线程执行构造函数和字段初始值设定项。" "不要在构造函数或字段初始值设定项中使用此函数,而是将初始化代码移动到唤醒或启动函数。"
每当我尝试使用此函数实例化某些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);
}
使用按钮调用一次。
我似乎无法找到问题,但如上所述,错误说它是一个线程问题,并且我不能从主要的另一个线程调用实例化。我不知道如何将实例化更改为另一个线程,但是非常感谢任何帮助解决这个问题。
答案 0 :(得分:0)
您可以尝试使用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();
}
}
答案 1 :(得分:0)
来自我的SAME QUESTION ON THE GAME DEVELOPMENT EXCHANGE。 答案trojanfro。
查看WebClient docs,该方法描述为:
从资源下载
string
,而不会阻止调用线程。
并给出错误消息:
INTERNAL_CALL_Internal_InstantiateSingle
只能从主线程中调用
很明显,您需要下载数据并存储它,并且只有在下载完成后才能在主线程中调用DisplayCells
。这在Cocoa中并不是唯一的,例如,您只能在主线程上调用与UI相关的API方法。
我花了一些时间在Google上寻找有关这方面的正确信息(我是初学者,当谈到Unity / C#时),但我认为会这样做:
创建一个布尔值,显示有要显示的数据:
private bool _callsToDisplay = false;
设置数据下载后的时间:
client.DownloadStringCompleted += (sender, e) => {
...
loading = false;
LogCalls ();
_callsToDisplay = true;
};
然后在Update()
方法(在主线程上运行)中,如果设置了布尔值,则调用DisplayCalls()
:
void Update()
{
if (_callsToDisplay) {
DisplayCalls();
_callsToDisplay = false;
}
}