C# 从线程更改主线程的游戏对象
我想以某种方式从异步线程更改游戏对象。我需要保留侦听器/接口架构 下面我创建了一个当前实现的简单示例 主脚本:C# 从线程更改主线程的游戏对象,c#,multithreading,unity3d,interface,listener,C#,Multithreading,Unity3d,Interface,Listener,我想以某种方式从异步线程更改游戏对象。我需要保留侦听器/接口架构 下面我创建了一个当前实现的简单示例 主脚本: using UnityEngine; public class MyScript : MonoBehaviour, IMyComponentListener { public GameObject cube; private MyComponent _myComponent; private void Start() { _myCo
using UnityEngine;
public class MyScript : MonoBehaviour, IMyComponentListener
{
public GameObject cube;
private MyComponent _myComponent;
private void Start()
{
_myComponent = new MyComponent(this);
}
public void OnThreadCompleted()
{
cube.transform.Rotate(Vector3.up, 10f);
}
}
线程脚本:
using System.Threading;
public class MyComponent
{
private readonly IMyComponentListener _listener;
public MyComponent(IMyComponentListener listener)
{
_listener = listener;
Thread myThread = new Thread(Run);
myThread.Start();
}
private void Run()
{
Thread.Sleep(1000);
_listener.OnThreadCompleted();
}
}
侦听器接口:
public interface IMyComponentListener
{
void OnThreadCompleted();
}
如果我尝试此代码,我将面临以下错误:
get_transform can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
UnityEngine.GameObject:get_transform()
MyScript:OnThreadCompleted() (at Assets/Scripts/MyScript.cs:18)
MyComponent:Run() (at Assets/Scripts/MyComponent.cs:20)
很明显,我不能从异步线程更改主线程元素,但如何解决它或正确实现支持此功能的体系结构?我已经找到了使用外部组件的解决方法 遵循以下步骤后,我已将我的调度程序更新为下面的示例,并作为charm工作 线程脚本:
using System.Threading;
public class MyComponent
{
private readonly IMyComponentListener _listener;
public MyComponent(IMyComponentListener listener)
{
_listener = listener;
Thread myThread = new Thread(Run);
myThread.Start();
}
private void Run()
{
Thread.Sleep(1000);
UnityMainThreadDispatcher.Instance().Enqueue(() => _listener.OnThreadCompleted());
}
}
我已经找到了一个使用外部组件的解决方案 遵循以下步骤后,我已将我的调度程序更新为下面的示例,并作为charm工作 线程脚本:
using System.Threading;
public class MyComponent
{
private readonly IMyComponentListener _listener;
public MyComponent(IMyComponentListener listener)
{
_listener = listener;
Thread myThread = new Thread(Run);
myThread.Start();
}
private void Run()
{
Thread.Sleep(1000);
UnityMainThreadDispatcher.Instance().Enqueue(() => _listener.OnThreadCompleted());
}
}
这只是一个例子,因为你要求它 一般来说,链接中的
UnityMainThreadDispatcher
就可以了
无论如何,它只是以Update
方法处理队列。我不想使用这种单例模式解决方案,而只是在已有的monobhavior
组件中做同样的事情(在大多数情况下,单例只是一种快速但肮脏的解决方案)
问题可能是这里的排版。。或者您可以将该方法添加到接口中
如果您有多个侦听器(由于接口的原因),我也会使用您的方式,可能仍然没有单个侦听器,而是使用适当的引用,例如通过Inspector
在我的智能手机上输入,所以没有保修,但我希望我能清楚地表明我的观点,这只是一个例子,因为你要求这样做 一般来说,链接中的
UnityMainThreadDispatcher
就可以了
无论如何,它只是以Update
方法处理队列。我不想使用这种单例模式解决方案,而只是在已有的monobhavior
组件中做同样的事情(在大多数情况下,单例只是一种快速但肮脏的解决方案)
问题可能是这里的排版。。或者您可以将该方法添加到接口中
如果您有多个侦听器(由于接口的原因),我也会使用您的方式,可能仍然没有单个侦听器,而是使用适当的引用,例如通过Inspector
在我的智能手机上输入,因此不提供保修,但我希望我能清楚地表明我的观点也许能解决您的问题。如果没有,你可以看看闪亮,新的也许会解决你的问题。如果不是的话,您可以看看shiny,new,您可以直接将它实现到您的
monobhavior
类中,而不是使用单例模式。如果您另外使用了ConcurrentQueue
,您也可以摆脱锁
@derHugo,您介意回答一个代码示例吗?不过,您可以直接将它实现到monobhavior
类中,而不是使用单例模式。如果您另外使用了ConcurrentQueue
,您也可以摆脱锁
@derHugo,您介意回答一个代码示例吗?不客气:)此设置基本上适用于我,例如TCP客户机/服务器。优点是您现在可以禁用该行为,队列操作系统不会进一步执行。不客气:)此设置基本上适用于我,例如TCP客户端/服务器。优点是您现在可以禁用该行为,并且队列操作系统不会进一步执行。
((MyScript)_listener).ThreadCompleted();