Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by samwood9797 · Oct 01, 2020 at 10:05 PM · .netsocketsudptiming

Program stopping at UDPClient.Receive() - timing issues?

Hello, I am trying to send packets of data into unity via UDP. The goal is then to use this data for inputs to move a cube in the game. The packets are json files that follow the structure {"name": (double), "name2": (double2), etc}.

I am having trouble getting passed the UDPClient.Receive() method inside my ThreadMethod. I am wondering if this is a timing/buffer issue between unity and the data coming in (data is being sent at 50Hz if that helps). Please see attached what is returned on the console. Console

Please also see my code below this. I am very new to unity and would appreciate any help to get this .Receive() working. Thanks in advance.

 using System.Collections;
 using System.Collections.Generic;
 using System.Threading;
 using UnityEngine;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 
 
 public class Move : MonoBehaviour
 {
     // Initialise vector for the gameObject (avatar) to move on.
     Vector3 Vec;
     // Intitialisations UDP and data processing
     //static UdpClient udp;
     Thread thread;
     //public string hostName = "127.0.0.1";
     static readonly object lockObject = new object();
     string returnData = "";
     bool translateData = false;
 
     // Start is called before the first frame update and is used to inititialise the UDP thread.
     void Start()
     {
         thread = new Thread(new ThreadStart(ThreadMethod));
         thread.Start();
     }
 
     // Update is called once per frame  
     public void Update()
     {
         if (translateData)
         {
             // Lock object so that multiple threads dont access data at the same time
             lock (lockObject)
             {
                 translateData = false;
                 UnityEngine.Debug.Log("Received: " + returnData);
                 Functions();
                 returnData = "";
             }
         }
     }
 
     // Handles the UDP communication from Host PC to Game PC
     private void ThreadMethod()
     {
         //Creates a UdpClient for reading incoming data.    
         UdpClient udp = new UdpClient(36864);
         UnityEngine.Debug.Log("Entering Thread method...");
         while (true)
         {
             UnityEngine.Debug.Log("Updating byte array...");
             Byte[] receiveBytes = new byte[0];
             try
             {
                 // The IPEndPoint will allow to read datagrams sent from any source.
                 IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
                 UnityEngine.Debug.Log("Looking from any source...");
 
 
                 // Set up receiver
                 receiveBytes = udp.Receive(ref RemoteIpEndPoint);
                 UnityEngine.Debug.Log("receiving bytes...");
             }
             catch (Exception err)
             {
                 UnityEngine.Debug.Log("UDP Client Socket Exception Error: " + err);
             }
             // Lock object so that multiple threads dont access data at the same time
             lock (lockObject)
             {
                 UnityEngine.Debug.Log("locked onto package...");
                 returnData = Encoding.ASCII.GetString(receiveBytes);
                 UnityEngine.Debug.Log("data is " + returnData.ToString());
                 handInfo items = JsonUtility.FromJson<handInfo>(returnData);
                 UnityEngine.Debug.Log("Array is " + items);
                 if (items != null) { translateData = true; }
                 else { UnityEngine.Debug.Log("Cannot reach data packages..."); }
             }
         }
     }
     // Class for displacement of each finger
     [Serializable]
     public class handInfo
     {
         public static double Pinky;
         public static double Ring;
         public static double Middle;
         public static double Index;
         public static double ThumbFlexExt;
         public static double ThumbAddAbd;
         //public static PlayerInfo CreateFromJSON(string jsonString)
         //{
         //    return JsonUtility.FromJson<PlayerInfo>(jsonString);
         //}
         // Given JSON input:
         // {"name":"Dr Charles","lives":3,"health":0.8}
         // this example will return a PlayerInfo object with
         // name == "Dr Charles", lives == 3, and health == 0.8f.
     }
     // Handles the movement associated with inputs
     void Functions()
     {
         if (handInfo.Pinky >= 7)
         {
             moveUp();
         }
         if (handInfo.Pinky <= 3)
         {
             moveDown();
         }
         if (handInfo.ThumbAddAbd <= 3)
         {
             moveLeft();
         }
         if (handInfo.ThumbAddAbd >= 7)
         {
             moveRight();
         }
     }
     public void moveRight()
     {
         Vec = transform.localPosition;
         Vec.x += Time.deltaTime * 20;
         transform.localPosition = Vec;
     }
     public void moveLeft()
     {
         Vec = transform.localPosition;
         Vec.x -= Time.deltaTime * 20;
         transform.localPosition = Vec;
     }
     public void moveUp()
     {
         Vec = transform.localPosition;
         Vec.y += Time.deltaTime * 20;
         transform.localPosition = Vec;
     }
     public void moveDown()
     {
         Vec = transform.localPosition;
         Vec.y -= Time.deltaTime * 20;
         transform.localPosition = Vec;
     }
 }
 


capture.png (56.4 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Oct 02, 2020 at 01:45 AM

Your code has several issues. First of all your sloppy thread handling will most likely cause issues in the long run. You should always make sure you gracefully terminate your thread once you're done. As a fallback you usually want to call Abort on the thread when you exit your app / exit playmode. The same is true for closing the socket. Yes in when the UdpClient is garbage collected the socket would be closed automatically. However you never know when the GC runs or if it runs at all.


Your main issue is that your "handInfo" class does not contain any serializable fields. Static fields are never serialized by pretty much none serializers out there since static fields do not belong on an instance. So your FromJson does nothing.


Regardless of the fact that static fields are not serialized, the example json you mentioned in the comment wouldn't have any relation to your class or the class fields. I specifically mean

     // {"name":"Dr Charles","lives":3,"health":0.8}

Wrong comments are much worst than no comments at all.


I tried your code in my test project and send test data to this port and it arrives just fine (apart from the fact that nothing is deserialized). I modifed your example and added a simple gui for sending test data locally:

 using System.Threading;
 using UnityEngine;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System;
 
 
 [Serializable]
 public class HandInfo
 {
     public double Pinky;
     public double Ring;
     public double Middle;
     public double Index;
     public double ThumbFlexExt;
     public double ThumbAddAbd;
     public override string ToString()
     {
         return "HandInfo: P:" + Pinky + " R:" + Ring + " M:" + Middle + " I:" + Index + " TFE:" + ThumbFlexExt + " TAA:" + ThumbAddAbd;
     }
 }
 
 
 public class UDPTest : MonoBehaviour
 {
     UdpClient udp;
     Thread thread;
     static readonly object lockObject = new object();
     string returnData = "";
     HandInfo handInfo;
 
     private void Start()
     {
         thread = new Thread(new ThreadStart(UDPThreadMethod));
         thread.Start();
     }
     private void OnDestroy()
     {
         if (udp != null)
         {
             udp.Close();
             udp = null;
         }
         if (thread != null)
         {
             if (thread.Join(100))
                 Debug.Log("UDP thread has terminated successfully");
             else
             {
                 Debug.Log("UDP thread did not terminate within 100ms, forcefully aborting");
                 thread.Abort();
             }
         }
     }
 
     private void Update()
     {
         if (handInfo != null)
         {
             lock (lockObject)
             {
                 Debug.Log("Received: " + returnData);
                 HandleHandInfo();
                 handInfo = null;
             }
         }
     }
 
     private void UDPThreadMethod()
     {
         udp = new UdpClient(36864);
         Byte[] receiveBytes = new byte[0];
         string receivedText = "";
         while (udp != null)
         {
             try
             {
                 receivedText = "";
                 IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
                 receiveBytes = udp.Receive(ref RemoteIpEndPoint);
                 receivedText = Encoding.UTF8.GetString(receiveBytes);
                 lock (lockObject)
                 {
                     returnData = receivedText;
                     Debug.Log("received text: " + returnData.ToString());
                     handInfo = JsonUtility.FromJson<HandInfo>(returnData);
                     Debug.Log("parsed handinfo: " + handInfo);
                 }
             }
             catch (Exception err)
             {
                 if (udp != null)
                     Debug.Log("UDP Client Socket Exception Error: " + err);
                 else
                     Debug.Log("thread is about to terminate ...");
 
             }
         }
     }
 
     private void HandleHandInfo()
     {
         if (handInfo == null)
             return;
 
         if (handInfo.Pinky >= 7)
             Move(Vector3.up);
         else if (handInfo.Pinky <= 3)
             Move(Vector3.down);
 
         if (handInfo.ThumbAddAbd <= 3)
             Move(Vector3.left);
         else if (handInfo.ThumbAddAbd >= 7)
             Move(Vector3.right);
     }
 
     private void Move(Vector3 aMovement)
     {
         transform.localPosition += aMovement * Time.deltaTime * 20;
     }
 
 
     // testing GUI
 
     private void TestSend(string aData)
     {
         // create temporary UdpClient for sending test data to our receiving socket
         UdpClient udpSender = new UdpClient();
         var data = Encoding.UTF8.GetBytes(aData);
         udpSender.Send(data, data.Length, "127.0.0.1", 36864);
         udpSender.Close();
     }
 
     private void OnGUI()
     {
         if (GUILayout.Button("Dummy Test data"))
             TestSend("{\"Pinky\":5,\"Ring\":5,\"Middle\":5,\"Index\":5,\"ThumbFlexExt\":5,\"ThumbAddAbd\":5}");
         if (GUILayout.Button("up"))
             TestSend("{\"Pinky\":7,\"Ring\":5,\"Middle\":5,\"Index\":5,\"ThumbFlexExt\":5,\"ThumbAddAbd\":5}");
         if (GUILayout.Button("down"))
             TestSend("{\"Pinky\":3,\"Ring\":5,\"Middle\":5,\"Index\":5,\"ThumbFlexExt\":5,\"ThumbAddAbd\":5}");
         if (GUILayout.Button("left"))
             TestSend("{\"Pinky\":5,\"Ring\":5,\"Middle\":5,\"Index\":5,\"ThumbFlexExt\":5,\"ThumbAddAbd\":3}");
         if (GUILayout.Button("right"))
             TestSend("{\"Pinky\":5,\"Ring\":5,\"Middle\":5,\"Index\":5,\"ThumbFlexExt\":5,\"ThumbAddAbd\":7}");
     }
 }

I heavily modified your code, refactored the method and class names (method and class names should start with a capital letter) and added a more appropriate thread termination code. The most important change is that I turned your static fields into actual instance member fields of your "HandInfo" class. Based on the field names I created several test data sets to cause the appropriate movement. For me this works fine. I can even run this in the editor and start a build of this application in parallel and use the buttons in the build to control the object inside the editor.


In your title you said something about your "Program is stopping". I'm not sure what you meant by this. However if the data that arrives is not valid json an exception will be thrown. An unhandled exception inside a thread will terminate the thread. In my example everything that happens during the while loop is inside a try catch block, so the thread doesn't terminate unless the "udp" variable is set to null.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Oct 02, 2020 at 01:50 AM 0
Share

Of course make sure your firewall isn't blocking your Unity editor or your build game when you do the testing. I guess your "handinfo" comes from some kind of external source? You may want to use a packet analyser like Wireshark if you have trouble to identify a connection / receiving issue.

avatar image samwood9797 · Oct 03, 2020 at 03:46 AM 0
Share

Thanks so much @Bunny83 , works well

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

137 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

I cant read from the sockets properly - exception 0x80004005: An invalid argument was supplied 2 Answers

Unity Editor cant host using systems.sockets.net sockets 0 Answers

.NET Sockets in basic iOS/Android license? 1 Answer

Why breaks my Ethernet over USB (USB NCM) connection between HoloLens and PC? 0 Answers

UDP Sockets for networking, getting overloaded?? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges