Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use UDP with Unity methods

Tags:

c#

unity3d

I created a Cube object and attached this script.

using UnityEngine;
using System.Collections;

public class CubeMove : MonoBehaviour {
    void Start () {
    }

    void Update () {
    }

    public void Move () {
        Vector3 moveVector = new Vector3(10, 0, 0);
        transform.Translate(moveVector);
    }
}

I wanted to use UDP to control cube move, so I created UDPManager.

using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class UDPManager : MonoBehaviour
{
    static UdpClient udp;
    Thread thread;

    public GameObject cube;
    public CubeMove cubemove;

    void Start ()
    {
        udp = new UdpClient(12345);
        cubemove = cube.GetComponent<CubeMove>();
        thread = new Thread(new ThreadStart(ThreadMethod));
        thread.Start();
    }

    void Update ()
    {
    }

    void OnApplicationQuit()
    {
        udp.Close();
        thread.Abort();
    }

    private void ThreadMethod()
    {
        while(true)
        {
            IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

            byte[] receiveBytes = udp.Receive(ref RemoteIpEndPoint); 
            string returnData = Encoding.ASCII.GetString(receiveBytes);
            Debug.Log(returnData);
            if (returnData == "1\n") {
                cube.SendMessage ("Move");
                // or
                cubemove.Move();

            }
        }
    } 
}

but these doesn't works with below errors.

- SendMessage can only be called from the main thread.
- get_transform can only be called from the main thread.

Can I call unity methods when I receive udp command?

like image 332
uzimith Avatar asked May 10 '16 07:05

uzimith


People also ask

Does unity use UDP?

Unity recommends creating your UDP client in the UDP console and linking it to your project, as described above. Alternatively, to create a UDP client from the Unity Editor: In the Unity Editor, select Services > Unity Distribution Portal > Configure. Select Create your UDP game directly from inside the Unity Editor.

What is UDP in unity?

UDP. Sign in. Unity Distribution Portal allows you to distribute your games to multiple app stores through a single hub.


2 Answers

You can't call Unity API from another Thread. How to use Thread in Unity:

1. Start Thread

2. Process Input in that new thread

3. Tell Unity that you are done processing. You can do this by setting a global boolean variable to true. Store output data in another global variable.

4. Check if the the boolean variable changed in the Update() function. Set it false if it did. Process output...

Also move udp = new UdpClient(12345); from the Start function to the ThreadMethod function.

static readonly object lockObject = new object();
string returnData = "";
bool precessData = false;

void Start ()
{
    cubemove = cube.GetComponent<CubeMove>();
    thread = new Thread(new ThreadStart(ThreadMethod));
    thread.Start();
}

void Update()
{
    if (precessData)
    {
        /*lock object to make sure there data is 
         *not being accessed from multiple threads at thesame time*/
        lock (lockObject)
        {
            precessData = false;
            cube.SendMessage("Move");
            // or
            cubemove.Move();

            //Process received data
            Debug.Log("Received: " + returnData);

            //Reset it for next read(OPTIONAL)
            returnData = "";
        }
    }
}

private void ThreadMethod()
{
    udp = new UdpClient(12345);
    while (true)
    {
        IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

        byte[] receiveBytes = udp.Receive(ref RemoteIpEndPoint);

        /*lock object to make sure there data is 
        *not being accessed from multiple threads at thesame time*/
        lock (lockObject)
        {
            returnData = Encoding.ASCII.GetString(receiveBytes);

            Debug.Log(returnData);
            if (returnData == "1\n")
            {
                //Done, notify the Update function
                precessData = true;
            }
        }
    }
}
like image 120
Programmer Avatar answered Oct 16 '22 19:10

Programmer


using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System;

public class UDPRT: ScriptableObject {
 static public string ReceivedMsg; // INPUT DATA
 static private UdpClient udpc;
 static IPEndPoint IP;
 static private object obj;
 static private AsyncCallback AC;
 static byte[] DATA;

 public static UDPRT CreateInstance(int Port) // RECEVE UDP
  {
   IP = new IPEndPoint(IPAddress.Any, Port);
   udpc = new UdpClient(Port);
   AC = new AsyncCallback(ReceiveIt);
   StartUdpReceive();
   return ScriptableObject.CreateInstance < UDPRT > ();
  }

 public static UDPRT CreateInstance(int Port, string Host, string msg) // SEND UDP
  {
   udpc = new UdpClient(Host, Port);
   AC = new AsyncCallback(SendIt);
   byte[] data = Encoding.UTF8.GetBytes(msg);
   udpc.BeginSend(data, data.Length, AC, obj);
   return ScriptableObject.CreateInstance < UDPRT > ();
  }

 static void ReceiveIt(IAsyncResult result) {
  DATA = (udpc.EndReceive(result, ref IP));
  Debug.Log(Encoding.UTF8.GetString(DATA));
  ReceivedMsg = Encoding.UTF8.GetString(DATA);
  StartUdpReceive();
 }

 static void SendIt(IAsyncResult result) {
  udpc.EndSend(result);
 }


 static void StartUdpReceive() {
  udpc.BeginReceive(AC, obj);
 }
} 
like image 26
ᑌᑎᑌᑎᑌᑎᑌᑎᑌᑎ Avatar answered Oct 16 '22 21:10

ᑌᑎᑌᑎᑌᑎᑌᑎᑌᑎ