【问题标题】:Unity .net Remoting Server get_animation can only be called from the main thread [duplicate]Unity .net Remoting Server get_animation 只能从主线程调用[重复]
【发布时间】:2013-04-16 08:36:45
【问题描述】:

我正在处理一个项目,我有两个需要相互通信的 Unity 项目。我正在尝试通过使用 .net Remoting Framework 来解决这个问题。 为此,我创建了一个两个 Unity 项目都将使用的 dll。该dll包括:

MyRemotableObject.cs

public class MyRemotableObject : MarshalByRefObject
{
    public MyRemotableObject()
    {

    }
    public void NotifyStatusChange(int status)
    {
        Cache.GetInstance().Status = 0;
    }
    public int GetCreditCount()
    {
        return Cache.GetInstance().CreditCount;
    }
}

Cache.cs

public class Cache
{
    private static Cache myInstance;
    public static IObserver Observer;
    private Cache()
    {

    }
    public static void Attach(IObserver observer)
    {
        Observer = observer;
    }
    public static Cache GetInstance()
    {
        if(myInstance==null)
        {
            myInstance = new Cache();
        }
        return myInstance;
    }

    public int Status
    {
        set
        {
            Observer.NotifyFinished(value);
        }
    }
    public int CreditCount
    {
        get
        {
            return Observer.QueryCreditCount();
        }
    }
}

IObserver.cs

public interface IObserver
{
    void NotifyFinished(int status);
    int QueryCreditCount();
}

现在我有了我的 Menu - Unity 项目,充当远程服务器

MenuController.cs

public class MenuController : MonoBehaviour, IObserver
{
    private object lockObject;
    List<ControllerBase> controllers;
    private MyRemotableObject remotableObject;
    private System.ComponentModel.Container components = null;

    void Awake()
    {
        lockObject = new object();
        try
        {
            remotableObject = new MyRemotableObject();

            //für fehler:  //http://www.mycsharp.de/wbb2/thread.php?postid=199935
            //************************************* TCP *************************************//
            // using TCP protocol
            TcpChannel channel = new TcpChannel(124);
            ChannelServices.RegisterChannel(channel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyRemotableObject), "TargetShooterMenu", WellKnownObjectMode.SingleCall);
            //************************************* TCP *************************************//
            RemotableObjects.Cache.Attach(this);
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }

        controllers = new List<ControllerBase>();
        foreach (GameObject controllerObject in GameObject.FindGameObjectsWithTag(GlobalNames.Tags.CONTROLLEROBJECT))
        {
            if (controllerObject.GetComponent<ControllerBase>())
                controllers.Add(controllerObject.GetComponent<ControllerBase>());
        }
    }
    delegate void PresentNameInputControllerDelegate(int status);
    private void PresentNameInputController(int status)
    {
        if (status == (int)LevelStatusCode.OK)
            foreach (ControllerBase controller in controllers)
            {
                controller.Hide();
                if (controller.GetType() == typeof(NameInputController))
                    controller.Show();
            }
    }
    public void NotifyFinished(int status)
    {
        Debug.Log("Notify");
        lock (lockObject)
        {
            PresentNameInputControllerDelegate d = PresentNameInputController;

            d(status);
        }
    }
    public int QueryCreditCount()
    {
        Debug.Log("Query");
        return 100;
    }
}

此服务器实现 IObserver 函数 NotifyFinished 和 QueryCreditCount(暂时返回虚拟值) 从客户端调用NotifyFinished函数时,出现如下错误:

get_animation 只能从主线程调用。 加载场景时,构造函数和字段初始化程序将从加载线程中执行。 不要在构造函数或字段初始化程序中使用此函数,而是将初始化代码移至 Awake 或 Start 函数。

谁能告诉我,如何解决这个问题?

提前致谢,

霍夫曼纽尔

【问题讨论】:

    标签: c# thread-safety unity3d remoting


    【解决方案1】:

    经过大量搜索,我找到了解决方案:使用 Loom Unity 包来自: Unity Gems entry about threading 并像Unity answers entry about threading 中提到的那样使用它:

        void Start()
        {
            var tmp = Loom.Current;
            ...
        }
        //Function called from other Thread
        public void NotifyFinished(int status)
        {
            Debug.Log("Notify");
            try
            {
                if (status == (int)LevelStatusCode.OK)
                {
                    Loom.QueueOnMainThread(() =>
                    {
                        PresentNameInputController();
                    });
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e.ToString());
            }
        }
    

    【讨论】:

    • 此链接不再可用,因此我将其标记为重复链接以帮助其他人解决您的问题。
    • 只是一个小问题,但为什么我会重复比我晚几年提出的问题?
    • 原因太多。 1. 您链接的 Gems 插件包不再可用,就像我在第一条评论中所说的那样。当人们找到这个答案时,它对他们没有用处。 2. 您的回答从未真正解释过问题或提供解决方法。你的回答基本上是说“使用这个插件”。它基本上是一个链接唯一的答案。当链接的站点消失时,问题和答案将不再有用。 3. 重复不是基于日期标记,而是基于帖子的详细程度或帮助程度。在将问题标记为重复问题之前,我会考虑所有这些。
    • 好的,谢谢您的反馈,我以后会考虑这个。
    猜你喜欢
    • 2019-06-18
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多