c# - python&unity3d : Websocket stability

标签 c# python unity-game-engine websocket

我正在 Unity3d 中创建一个与 python 的 websockets 库通信的应用程序。我的Python脚本如下:

from __future__ import division
import asyncio
import websockets
import time
import os
from threading import Thread
from random import randint
from read import CustOPCLib
import socket
from jsonsocket import Client,Server

class SubHandler(object):
    def data_change(self, handle, node, val, attr):
        print("Python: New data change event", handle, node, val, attr)

    def datachange_notification(self, node, val, data):
        print("Data received: ",val)

    def event(self, handle, event):
        print("Python: New event", handle, event)


p = CustOPCLib()
async def hello(websocket, path):
    p.connect() #my own custom library
    while True:
        datastring = p.opcjson()             #this is a jsonstring
        await websocket.send(datastring)
        #print("> {}".format(datastring))
        time.sleep(1)

if __name__ == '__main__':
    start_server = websockets.serve(hello, '127.0.0.1', 8765)
    asyncio.get_event_loop().run_until_complete(start_server)
    asyncio.get_event_loop().run_forever()

我的json字符串如下:

{
    "Index": 709953575,
    "Moto": true,
    "Start": false,
    "StartWINCC": false,
    "Stop": false,
    "StopWINCC": false,
    "Tag1": true,
    "Tag2": false
}

这是我想要发送到 Unity 的字符串。在 Unity3d 中,我制作了以下使用 mono 中的 Concurrentqueue 的脚本。该脚本相应地工作,但是我遇到的问题是我从 websocket 获得很多空值。 我的 Unity3d 脚本:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading;

public class ConcurrentQueue<T> : IEnumerable<T>, ICollection, ISerializable, IDeserializationCallback
{
    class Node
    {
        public T Value;
        public Node Next;
    }

    Node _head = new Node();
    Node _tail;
    int _count;

    /// <summary>
    /// </summary>
    public ConcurrentQueue()
    {
        _tail = _head;
    }

    public ConcurrentQueue(IEnumerable<T> enumerable)
        : this()
    {
        foreach (T item in enumerable)
            Enqueue(item);
    }

    public void Enqueue(T item)
    {
        var node = new Node { Value = item };

        Node oldTail = null;

        bool update = false;
        while (!update)
        {
            oldTail = _tail;
            var oldNext = oldTail.Next;

            // Did tail was already updated ?
            if (_tail == oldTail)
            {
                if (oldNext == null)
                {
                    // The place is for us
                    update = Interlocked.CompareExchange(ref _tail.Next, node, null) == null;
                }
                else
                {
                    // another Thread already used the place so give him a hand by putting tail where it should be
                    Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
                }
            }
        }
        // At this point we added correctly our node, now we have to update tail. If it fails then it will be done by another thread
        Interlocked.CompareExchange(ref _tail, node, oldTail);

        Interlocked.Increment(ref _count);
    }


    /// <summary>
    /// </summary>
    /// <returns></returns>
    public bool TryDequeue(out T value)
    {
        value = default(T);
        bool advanced = false;
        while (!advanced)
        {
            Node oldHead = _head;
            Node oldTail = _tail;
            Node oldNext = oldHead.Next;

            if (oldHead == _head)
            {
                // Empty case ?
                if (oldHead == oldTail)
                {
                    // This should be false then
                    if (oldNext != null)
                    {
                        // If not then the linked list is mal formed, update tail
                        Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
                    }
                    value = default(T);
                    return false;
                }
                else
                {
                    value = oldNext.Value;
                    advanced = Interlocked.CompareExchange(ref _head, oldNext, oldHead) == oldHead;
                }
            }
        }

        Interlocked.Decrement(ref _count);
        return true;
    }

    /// <summary>
    /// </summary>
    /// <returns></returns>
    public bool TryPeek(out T value)
    {
        if (IsEmpty)
        {
            value = default(T);
            return false;
        }

        Node first = _head.Next;
        value = first.Value;
        return true;
    }

    public void Clear()
    {
        _count = 0;
        _tail = _head = new Node();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return InternalGetEnumerator();
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return InternalGetEnumerator();
    }

    public IEnumerator<T> GetEnumerator()
    {
        return InternalGetEnumerator();
    }

    IEnumerator<T> InternalGetEnumerator()
    {
        Node myHead = _head;
        while ((myHead = myHead.Next) != null)
        {
            yield return myHead.Value;
        }
    }

    void ICollection.CopyTo(Array array, int index)
    {
        T[] dest = array as T[];
        if (dest == null)
            return;
        CopyTo(dest, index);
    }

    public void CopyTo(T[] dest, int index)
    {
        IEnumerator<T> e = InternalGetEnumerator();
        int i = index;
        while (e.MoveNext())
        {
            dest[i++] = e.Current;
        }
    }

    public T[] ToArray()
    {
        T[] dest = new T[_count];
        CopyTo(dest, 0);
        return dest;
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        throw new NotImplementedException();
    }

    bool ICollection.IsSynchronized
    {
        get { return true; }
    }

    public void OnDeserialization(object sender)
    {
        throw new NotImplementedException();
    }

    readonly object _syncRoot = new object();
    object ICollection.SyncRoot
    {
        get { return _syncRoot; }
    }

    public int Count
    {
        get
        {
            return _count;
        }
    }

    public bool IsEmpty
    {
        get
        {
            return _count == 0;
        }
    }
}

public class test : MonoBehaviour
{
    class OpcJson
    {
        public int Index { get; set; }
        public bool Moto { get; set; }
        public bool Start { get; set; }
        public bool StartWINCC { get; set; }
        public bool Stop { get; set; }
        public bool StopWINCC { get; set; }
        public bool Tag1 { get; set; }
        public bool Tag2 { get; set; }
    }
    //variables
    static readonly ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
    public string receivedFromServer;
    WebSocket w = new WebSocket(new Uri("ws://127.0.0.1:8765"));
    public Text testert;
    public Image moto;
    public Image start;
    public Image startwincc;
    public Image stop;
    public Image stopwincc;
    public Image tag1;
    public Image tag2;
    // Use this for initialization
    IEnumerator StartWebsocket()
    {
        yield return StartCoroutine(w.Connect());
        //w.SendString("Hi there");
        //int i = 0;
        while (true)
        {
            string reply = w.RecvString();
            if (reply != null)
            {
                //Debug.Log(reply);
                queue.Enqueue(reply);
                //receivedFromServer = reply;
                //Debug.Log("Received: " + reply);
                //w.SendString("Hi there" + i++);
            }
            if (w.error != null)
            {
                Debug.LogError("Error: " + w.error);
                break;
            }
            yield return 0;
        }
        w.Close();
    }
    private void OnApplicationQuit()
    {
        StopAllCoroutines();
        w.Close();
    }
    IEnumerator JsonObjectSetter(float waitforsecods)
    {
        while (true)
        {
            queue.TryDequeue(out receivedFromServer);
            //string s = receivedFromServer;
            //Debug.Log(s);
            if(receivedFromServer == null)
            {
                Debug.Log("I'm null");
            }
            else
            {
                var results = JsonConvert.DeserializeObject<OpcJson>(receivedFromServer);
                testert.text = results.Index.ToString();
                if (results.Moto == true)
                {
                    moto.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    moto.GetComponent<Image>().color = Color.red;
                }

                if (results.Start == true)
                {
                    start.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    start.GetComponent<Image>().color = Color.red;
                }

                if (results.StartWINCC == true)
                {
                    startwincc.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    startwincc.GetComponent<Image>().color = Color.red;
                }

                if (results.Stop == true)
                {
                    stop.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    stop.GetComponent<Image>().color = Color.red;
                }

                if (results.StopWINCC == true)
                {
                    stopwincc.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    stopwincc.GetComponent<Image>().color = Color.red;
                }

                if (results.Tag1 == true)
                {
                    tag1.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    tag1.GetComponent<Image>().color = Color.red;
                }

                if (results.Tag2 == true)
                {
                    tag2.GetComponent<Image>().color = Color.green;
                }
                else
                {
                    tag2.GetComponent<Image>().color = Color.red;
                }
            }
            yield return new WaitForSeconds(waitforsecods);
        }
    }
    private void Start()
    {
        StartCoroutine(StartWebsocket());
        StartCoroutine(JsonObjectSetter(1));
    }
}

如您所见,我在 JsonObjectSetter 方法中做了一个 if/else 语句。每次出列后字符串为空时,它都会打印出“I'm null”,如果它不为空,则用于根据该值将图像设置为颜色。 我怎样才能做到这一点,这样我就不会再得到任何空值了?

编辑 1:在 7 分钟的测试中,我计算出 49 个空值。老实说,这是一个很大的问题......

最佳答案

修好了! 问题是我的python脚本有一个持续1秒的time.sleep(),将其更改为0.1,并将Unityscript中的WaitForSecods更改为0.25f。这完全解决了我的问题。有点愚蠢,我在将其发布到 Stackoverflow 之前没有想到这一点。

关于c# - python&unity3d : Websocket stability,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49979183/

相关文章:

python - 将列表保存到文件

unity-game-engine - 我无法统一缩放我的 Canvas

c# - Timer.Change 上的 NullReferenceException

c# - 如何在拥有的实体中定义关系属性的名称

python - YUYV 帧率比来自 USB 相机 OpenCV 的 MJPG 快

python:添加到字典会出错

c# - 使用数据库中的数据实例化对象会更改值

unity-game-engine - Unity 高斯模糊着色器只是使我的纹理变白 - 为什么?

c# - 从C#中的字符串中提取子字符串

c# - 在 VisualStudio 中创建 IronPython 项目时出错; "Exception has been thrown by the target of an invocation."