C#/ Unity-无法从异步方法调用Unity方法

时间:2019-01-15 21:15:05

标签: c# unity3d asynchronous udp

我正在使用Unity3D。这是我的异步方法:

private void Receive(IAsyncResult ar)
{
    try
    {
        IPEndPoint ipEndPoint = null;
        byte[] data = udpClient.EndReceive(ar, ref ipEndPoint);
        string receivedMessage = Encoding.UTF8.GetString(data);

        JsonData json = JsonConvert.DeserializeObject<JsonData>(receivedMessage);
        string prefix = json.header.Substring(0, 2);

        Debug.Log("UDP World: " + receivedMessage);

        if (prefix != "3x")
        {
            Debug.Log("Unknown packet: " + receivedMessage + "\n");
        }
        else
        {
            string header = json.header.Substring(2);
            int conId = json.connectionId;
            switch (header)
            {
                default:
                    Debug.Log("Unknown packet: " + receivedMessage + "\n");
                    break;
                case "001":
                    Debug.Log("Data received: " + receivedMessage + "\n");
                    break;
                case "002":
                    CharacterPosition position = new CharacterPosition();
                    position.x = float.Parse(json.data["position.x"].ToString());
                    position.y = float.Parse(json.data["position.y"].ToString());
                    position.z = float.Parse(json.data["position.z"].ToString());
                    Character.updateCharacterPosition(position, Convert.ToInt32(json.data["characterId"].ToString()), conId);
                    break;
                case "003":
                    ClientWorldServer.character.updateCharacterRotation(json.data, conId);
                    break;
            }
        }
    } catch (SocketException e)
    {
        Debug.Log("UDP Socket Exception: " + e);
    }
    udpClient.BeginReceive(Receive, null);
}

这是从Receive()调用时无法正常工作的函数:

public static void updateCharacterPosition(CharacterPosition position, int characterId, int cnnId)
{
    if (Character.SceneLoaded != true)
        return;
        Debug.Log("Position 2: X: " + position.x + " Y: " + position.y + " Z: " + position.z);
        Debug.Log("GameObject FIND: " + GameObject.Find("CharactersOnline").name);

    if (cnnId != ClientWorldServer.connectionId)
    {
        GameObject startPoint = GameObject.Find("CharactersOnline/" + characterId.ToString());
        GameObject endPoint = new GameObject();
        endPoint.transform.position = new Vector3(position.x, position.y, position.z);
        GameObject.Find("CharactersOnline/" + characterId.ToString()).transform.position = Vector3.Lerp(startPoint.transform.position, endPoint.transform.position, Time.deltaTime);

        //Updating Clients ram of the character's position
        Character.characterDetails[int.Parse(characterId.ToString())].characterPosition.x = position.x;
        Character.characterDetails[int.Parse(characterId.ToString())].characterPosition.y = position.y;
        Character.characterDetails[int.Parse(characterId.ToString())].characterPosition.z = position.z;
        //Destroy(endPoint);
    }
}

我在Unity控制台中看到的全部是以下内容的输出:

Debug.Log("Position 2: X: " + position.x + " Y: " + position.y + " Z: " + position.z + " Character: " + characterId + " CnnID: " + cnnId);

使用上面显示的Debug.Log,我可以看到我具有所需的所有信息。 Debug.Log中的所有内容均已存在。 下一行:

Debug.Log("GameObject FIND: " + GameObject.Find("CharactersOnline").name);

似乎是一切刹车的地方。我从那条线都没有收到任何输出,也没有任何错误。看起来好像呆在那里,没有给出任何输出或错误。

从另一个非异步方法调用updateCharacterPosition时,updateCharacterPosition中的所有内容都按缩进方式工作。

任何想法为什么会发生这种奇怪的行为。如何解决该问题,以便可以从updateCharacterPosition调用Receive,这是异步功能?

1 个答案:

答案 0 :(得分:1)

尝试一下:   / *将其附加到场景中的任何对象上,以使其起作用* /

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MainThread : MonoBehaviour {

   class CallInfo
   {
     public Function func;
     public object parameter;
     public CallInfo(Function Func, object Parameter)
     {
       func = Func;
       parameter = Parameter;
     }
     public void Execute()
     {
       func(parameter);
     }
   }

   public delegate void Function(object parameter);
   public delegate void Func();

   static List<CallInfo> calls = new List<CallInfo>();
   static List<Func> functions = new List<Func>();

   static Object callsLock = new Object();
   static Object functionsLock = new Object();

   void Start()
   {
     calls = new List<CallInfo>();
     functions = new List<Func>();

     StartCoroutine(Executer());
   }

   public static void Call(Function Func, object Parameter)
   {
     lock(callsLock)
     {
       calls.Add(new CallInfo(Func, Parameter));
     }
   }
   public static void Call(Func func)
   {
     lock(functionsLock)
     {
       functions.Add(func);
     }
   }

   IEnumerator Executer()
   {
     while(true)
     {
       yield return new WaitForSeconds(0.01f);

       while(calls.Count > 0)
       {
         calls[0].Execute();
         lock(callsLock)
         {
           calls.RemoveAt(0);
         }
       }

       while(functions.Count > 0)
       {
         functions[0]();
         lock(functionsLock)
         {
           functions.RemoveAt(0);
         }
       }
     }
   }
}

像这样打电话

MainThread.Call(YourFunction);
MainThread.Call(YourFunction, parameters);

我认为您的问题是您正在从另一个不允许的线程中调用Unity方法