Home>

Find can only be called from the main thread
And an error will appear on the console
If you'd like, I'd like you to give me a solution why I get an error.
Debug was done. The boss in the solution
If i reference the text object in Start and change the value in Update
I said I could do it, but I didn't understand it well.
Can you tell me if you like?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine.UI;//<---- Add 1

public class UdpSocket: MonoBehaviour
{
private string _MulticastAddr ="224.0.23.0" ;;// multicast address
private string _RemoteHost ="" ;;// Sender address
private int _SendPort = 3610;// send port
private int _RecvPort = 3610;// Receive port

private UdpClient _UdpClient;// UDP
private IPEndPoint _IpEndPoint;// IPEndPoint
private Thread _RecvThread;// receive thread

// Connect
public void Connect ()
{
IPAddress grpAddr = IPAddress.Parse (_MulticastAddr);

if (_IpEndPoint! = null) _IpEndPoint = null;
_IpEndPoint = new IPEndPoint (grpAddr, _RecvPort);

// Join a multicast group
Disconnect ();
_UdpClient = new UdpClient (_RecvPort);
_UdpClient.JoinMulticastGroup (grpAddr);

// Create receive thread
_RecvThread = new Thread (ReceiveMulticastThread);
_RecvThread.Start ();

// Send node profile notification
SendNodeProfile ();
}

// Disconnect
public void Disconnect ()
{
if (_RecvThread! = null)
{
_RecvThread.Abort ();
_RecvThread = null;
}

if (_UdpClient! = null)
{
IPAddress grpAddr = IPAddress.Parse (_MulticastAddr);
_UdpClient.DropMulticastGroup (grpAddr);
_UdpClient.Close ();
_UdpClient = null;
}
}

// Send node profile notification
public void SendNodeProfile ()
{
byte [] pack = BuildNodeProfileInfo ();
SendPacket (pack, _MulticastAddr);
}

// Send
public void SendPacket (byte [] packet, string host)
{
_UdpClient.Send (packet, packet.Length, host, _SendPort);
}

// Receiving thread
public void ReceiveMulticastThread ()
{
byte [] packet;

int i = 0;

System.Text.StringBuilder s = new System.Text.StringBuilder ();

while (true)
{
packet = _UdpClient.Receive (ref _IpEndPoint);
if (packet! = null)
{
// Received!
s.Remove (0, s.Length);
for (i = 0;i<packet.Length;i ++)
{
s.Append (System.Convert.ToString (packet [i], 16) .PadLeft (2,'0'));
}

Debug.Log (s.ToString ());

Text targetText;//<---- Add 2
GameObject _Object;
_Object = GameObject.Find ("Text");

targetText = _Object.GetComponent<Text>();//<---- Add 3
targetText.text ="s.ToString ()" ;;//<---- add 4

}
}
}

// Create node profile notification packet
private byte [] BuildNodeProfileInfo ()
{
byte [] pack;
pack = new byte [17];

pack [0] = 0x10;// EHD1
pack [1] = 0x81;// EHD2
pack [2] = 0x00;//
pack [3] = 0x01;// ID

pack [4] = 0x0E;// Source "Node Profile Class"
pack [5] = 0xF0;// EOJ = 0x0E F0 01
pack [6] = 0x01;//

pack [7] = 0x0E;// Destination "node profile class"
pack [8] = 0xF0;// EOJ = 0x0E F0 01
pack [9] = 0x01;//

pack [10] = 0x73;// ESV

pack [11] = 0x01;// OPC

pack [12] = 0xD5;// EPC
pack [13] = 0x04;// PDC
pack [14] = 0x01;// EDT
pack [15] = 0x05;//
pack [16] = 0xFF;//
pack [16] = 0x01;//

return pack;
}
}

Code
`` `

  • Answer # 1

    unity cannot use the unity function from another thread.
    So instead of setting the text directly in the receiving thread
    Try to do it differently.
    I'm sorry, I don't know about unity so specific
    I can't show you how.

    The part that sets Text to targetText is not good enough.
    Make a distinction between constants and variables.

    ・ Appendix

    About your boss's plan
    1. Create a private string type variable in the UdpSocket class you are creating.
    2. In the receiving thread, instead of setting the received data directly in Text, just store it in the previous variable.
    3. Create a start method in the UdpSocket class and get a Text instance there.
    4). Create an update method in the UdpSocket class, and set the variable of 1 to the Text instance stored in 3.

    If you write simply, you will see a flow like this.

    public class UdpSocket: MonoBehaviour
    {
        // various omitted
        private string RecvData = "";
        private Text targetText;
        void Start () {
            targetText = GameObject.Find ("Text"). GetComponent<Text>();
        }
        void Update () {
            targetText.text = RecvData;
        }
        // various omitted


    The code is written appropriately, so please use it only as a reference for thinking.

  • Answer # 2

      

    targetText.text ="s.ToString ()" ;;//<---- add 4

    The GUI component display can only be changed from the main thread
    If you go around with "c # separate thread control", you can find out how to deal with that.