У меня есть фрагмент кода, который действует как клиент Grpc в Unity.Стиль кода разработан для консольного приложения, которое можно вызывать в методе Main, блокируя его и постоянно получая данные.Теперь я хочу использовать его в Unity и, очевидно, хочу, чтобы мое приложение работало в Unity одновременно.Кроме того, моя конечная цель - иметь что-то, что работает как Udp Client.Вы вызываете его один раз, и все время будете получать данные для вас, не блокируя какую-либо часть хост-приложения.
Самая важная часть этого проекта заключается в том, что, если будет какое-либо событие, я получуобновить, если нет нового события, соответственно, я не получаю никаких данных.И все это происходит в ObserveEvents (канал) .Wait (); .Проблема в Wait (); .Что постоянно, ведите основной поток, работающий поток, слушайте обновления.В режиме воспроизведения Unity больше не отвечает!
Я могу обойти это и сказать, что мне не нужен такой дизайн, я могу получать события каждую секунду или каждые несколько кадров.Благодаря этому у меня есть приложение Unity, но я теряю очень много кадров, несмотря на тот факт, что мои данные НЕ перетекают гладко в мое хост-приложение в Unity.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Grpc.Core;
using UnityEngine;
namespace Scripts
{
public class GrpcChannel
{
public void GrpcServer(string ip, int port)
{
var channel = new Channel(ip, port, ChannelCredentials.Insecure);
ObserveEvents(channel).Wait();
channel.ShutdownAsync().Wait();
}
private async Task ObserveEvents(Channel channel)
{
Debug.Log("Observing events...");
var eventService = new EventService.EventServiceClient(channel);
var request = new RegisterOnEvent();
using (var call = eventService.OnEvent(request))
{
var responseStream = call.ResponseStream;
while (await responseStream.MoveNext())
{
//var receivedEvent = responseStream.Current;
// on change of any data, this method will be fired
GetJointPosition(channel, "Flower_id_22134");
}
}
}
private void GetJointPosition(Channel channel, string flowerName)
{
var client = new JointPositionService.JointPositionServiceClient(channel);
var request = new GetJointPositionRequest
{
FlowerName = flowerName
};
var response = client.GetJointPositionAsync(request);
SavePositions(response.ResponseAsync.Result.Positions);
}
private void SavePositions(IEnumerable<JointPosition> positions)
{
var jointPositions = positions.ToList();
for (var i = 0; i < Instance.Ref.AxesValues.Length; i++)
{
var axeValueDegree = jointPositions[i].Value * 180 / Math.PI;
Instance.Ref.AxesValues[i] = (float)axeValueDegree;
}
}
}
}
И я звонюэто как:
var grpcChannel = new GrpcChannel();
grpcChannel.GrpcServer("192.168.123.16", 30201);
в методе Update ().К сожалению, это не работает в методе Start ().И да, по-видимому, каждый кадр необходим для создания нового канала, иначе он не будет работать.
И текущая реализация выглядит следующим образом: она вызывает каждые 7 кадров без использования специального ожидания для разработки событий.:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using TMPro;
using UnityEngine;
namespace Assets.Scripts
{
public class AxisValuesService : MonoBehaviour
{
public TextMeshProUGUI[] AxesValuesTexts;
[HideInInspector] public Dictionary<uint, float> AxisValues = new Dictionary<uint, float>();
[HideInInspector] private int counter = 0;
private void Update()
{
counter++;
if (counter == 7)
{
try
{
var channel = new Channel("192.168.123.16", 30201, ChannelCredentials.Insecure);
GetJointPosition(channel, "Flower_id_22134");
//ObserveEvents(channel).Wait();
channel.ShutdownAsync().Wait();
}
catch (RpcException e)
{
Debug.LogError("Connection Error: " + e);
}
counter = 0;
}
}
private void GetJointPosition(Channel channel, string robotName)
{
// Request Axis Values
var client = new JointPositionService.JointPositionServiceClient(channel);
var request = new GetJointPositionRequest { RobotName = robotName };
var response = client.GetJointPositionAsync(request);
// Fill Dictionary
foreach (var i in response.ResponseAsync.Result.Positions)
{
double value = toDegree((double)i.Value);
AxisValues[i.Index] = (float)Math.Round(value, 2);
}
try
{
AxesValuesTexts[0].text = AxisValues[1].ToString();
AxesValuesTexts[1].text = AxisValues[2].ToString();
AxesValuesTexts[2].text = AxisValues[3].ToString();
AxesValuesTexts[3].text = AxisValues[4].ToString();
AxesValuesTexts[4].text = AxisValues[5].ToString();
AxesValuesTexts[5].text = AxisValues[6].ToString();
}
catch (Exception e)
{
Debug.Log("Dictionary problem.");
}
}
private double toDegree(double rad)
{
return (float)(180 / Math.PI) * rad;
}
}
}
Мой вопрос заключается в том, что, во-первых, если этот метод полностью асинхронный , почему он до сих пор блокирует приложение в Unity, также как я могупереработайте его, чтобы получить что-то вроде Udp или Tcp ?