当我从websockets获取一些数据并试图通过协同程序显示它时,我遇到了一些麻烦。
首先,我有一个classA附加到一个对象,它打开websocket并显示我收到的数据:
public class ClassA : MonoBehaviour {
...
public IEnumerator ConnectWebSocket(url)
{
// in the websocket class, start the websocket connection, which
// will return data through a callback inside the return string
WebSocketClass.WebSocketStart(url, delegate(string result)
{
// receive websocket data and call the functions that displays it
WebSocketData(result);
});
// wait for the socket connection
while (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.CONNECTING)
{
yield return 0;
}
if (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.OPEN)
{
break;
}
...
}
// function that gets websocket data and starts couroutine to display it
public void WebSocketData(string data)
{
StartCoroutine(DisplayMessage(data));
}
}
但Unity抱怨下一个错误:
只能调用StartCoroutine_Auto 从主线程。建设者和 字段初始值设定项将被执行 从加载线程加载时 现场。不要在中使用此功能 构造函数或字段初始值设定项, 而是将初始化代码移动到 唤醒或启动功能。
我在团结论坛上搜索并找到了这个解决方案:
public class ClassA : MonoBehaviour {
...
public IEnumerator ConnectWebSocket(url)
{
// in the websocket class, start the websocket connection, which
// will return data through a callback inside the return string
WebSocketClass.WebSocketStart(url, delegate(string result)
{
// receive websocket data and call the functions that displays it
WebSocketData(result);
});
// wait for the socket connection
while (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.CONNECTING)
{
yield return 0;
}
if (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.OPEN)
{
break;
}
...
}
// function that gets websocket data and starts couroutine to display it
public void WebSocketData(string data)
{
DoOnMainThread.ExecuteOnMainThread.Enqueue(() => { StartCoroutine(DisplayMessage(data)); });
}
}
// class to manage the websocket data display inside the main thread
public class DoOnMainThread : MonoBehaviour
{
public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>();
public virtual void Update()
{
// dispatch stuff on main thread
while (ExecuteOnMainThread.Count > 0)
{
ExecuteOnMainThread.Dequeue().Invoke();
}
}
}
它有效!问题是,即使我在同一个cs文件中写了两个类并附加到一个对象,当我更改场景,返回到那个场景,并从websocket接收任何数据时,显示下一个错误:
MissingReferenceException:对象 类型&#39; ClassA&#39;已被摧毁 但你仍然试图访问它。 你的脚本应该检查它是否 是null或你不应该破坏 宾语。 UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator例程)(at C:/BuildAgent/work/d63dfc6385190b60/artifacts/EditorGenerated/UnityEngineMonoBehaviour.cs:62)
我尝试在加载新场景时不破坏对象,如文档所示:
void Awake()
{
DontDestroyOnLoad(transform.gameObject);
}
但错误仍然存在。
奇怪的是,尽管存在错误,但显示从websocket接收的数据没有任何问题。
有人知道如何避免这个问题吗?有没有使用第二个类在主线程内触发协程的方法?或其他解决方案,以避免此错误?
谢谢!
答案 0 :(得分:1)
我发现了问题:
public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>();
它是静态的,因此在实例化公共类并生成另一个ExecuteOnMainThread时会出现问题。
因此,只需删除“静态”并使其在每次由Unity创建ClassA时销毁并生成自己。
现在它就像一个魅力:)