Suggested way of receiving audio data through TCP conection and update audio clip in Unity

I’m working on a project that receives audio data through TCP communication and then plays it once received.

On the receiving side. I opened another clientReceiveThread for the TCP socket communication, And the receiving code is

    public void ListenForData()
    {
        float[] float_msg_temp;
        float[] float_ms_z;
        float[] float_try = { 3.0f, 3.5F, 4.0F, 4.5F, 5.0F };
        socketConnection = new TcpClient("xxx.xxx.xx.xx", 8010);
        NetworkStream myNetworkStream = socketConnection.GetStream();

        while (true)
        {          
            if (myNetworkStream.CanRead)
            {
                do
                {
                    byte[] myReadBuffer = new byte[1024];
                    float data_len = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
                    StringBuilder myCompleteMessage = new StringBuilder();
                    int numberOfBytesRead = 0;
                    // use to change this to float array used by audio clip
                    float_msg_temp = ConvertByteArrayToFloat(myReadBuffer);
                    if (float_msg != null)
                    {
                        float_ms_z = new float[float_msg.Length + float_msg_temp.Length];
                        float_msg.CopyTo(float_ms_z, 0);
                        float_msg_temp.CopyTo(float_ms_z, float_msg.Length);
                        float_msg = float_ms_z;
                    }

                    else
                    {
                        float_ms_z = float_msg_temp;
                        float_msg = float_ms_z;
                    }
                    if (!myNetworkStream.DataAvailable)
                        System.Threading.Thread.Sleep(1);

                } while (myNetworkStream.DataAvailable);
               
                socketConnection.Close();
                CanPlay = true;
                // original idea: play the clip
                Playonce(float_msg);
                socketConnection = new TcpClient("xxx.xxx.xx.xx", 8010);
                myNetworkStream = socketConnection.GetStream();
                Debug.Log("reconnnect ");

            }
            else
            {              
                Debug.Log("Sorry.  You cannot read from this NetworkStream.");
            }
        }
    }
static float[] ConvertByteArrayToFloat(byte[] bytes)
{
    if (bytes.Length % 4 != 0) throw new ArgumentException();

    float[] floats = new float[bytes.Length / 4];
    for (int i = 0; i < floats.Length; i++)
    {
        floats[i] = BitConverter.ToSingle(bytes, i * 4);
    }

    return floats;
}

My original idea was to call a function to play the audio clip

void Playonce(float[] float_msg)

{
    Debug.Log("Play Once");
    if(CanPlay){
        clip = AudioClip.Create("ClipName", float_msg.Length, channels, sampleRate, false);
        clip.SetData(float_msg, 0);
        audioSource.clip = clip;
        audioSource.Play();
        float_msg = null;
        whole_msg = "";
        CanPlay = false;
    }

}

However, I got this error during testing:
UnityException: Construct_Internal can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don’t use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

So I tried another way using the Update function

    void Update()
    {
        if (float_msg != null && CanPlay)
        {
   
            clip = AudioClip.Create("ClipName", float_msg.Length, channels, sampleRate, false);
            clip.SetData(float_msg, 0);
            audioSource.clip = clip;
            audioSource.Play();
            float_msg = null;
            whole_msg = "";
            CanPlay = false;
        }
    }

However, this method just doesn’t feel right to me. And sometimes I have problem of receiving only a short sentence of audio.

I would like to ask

  • Is my current TCP connection method a good way of receiving data?
  • Is there any better way of updating and playing the audio clip?

Any reason why? You can’t do anything with Unity off the main thread, so it seems reasonable to me.

Here’s my blurb about the typical marshal-to-main solution:

Delegate queue to marshal tasks from other threads to the main thread:

To debug anything related to Networking, UnityWebRequest, WWW, Postman, curl, WebAPI, etc:

And setting up a proxy can be very helpful too, in order to compare traffic: