C # / Unity - Ошибка вызова метода Unity из асинхронного метода - PullRequest
0 голосов
/ 16 января 2019

Я использую 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 голосов
/ 16 января 2019

Попробуйте это: / * Прикрепите это к любому объекту в вашей сцене, чтобы он работал * /

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 из другого потока, который не разрешен

...