Recently, the main thread resource of unity is occupied when saving a scenario, which causes the UI of unity itself (I think, or I think that the UI of the scenario to be saved cannot be used normally) to fail to display the progress bar. When this problem cannot be solved, I think of a compromise way to use the progress bar of winform to display the progress bar.
When the UI progress bar of unit itself cannot be displayed normally, use EditorUtility.DisplayProgressBar() to test that your data is transmitted normally. However, as we all know, UnityEditor can only be used under the editor, and packaging cannot be used. So it was discussed for a long time and finally decided to build another winform window and progress bar. In unity, use Process class to wake up the Process of winform program, then use Socket to transfer the progress value, and then winform program accepts the display of data update progress bar.
Process main code:
#Display and hide of region progress bar /// <summary> ///Wake up progress bar /// </summary> public void ShowProgressbar() { System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(ProgressBarExeplore); // return new WaitForSeconds(0.5f); for (int i = 0; i < process.Length; i++) { process[i].Kill(); } isSave = true; string PathBar = ProgressBarPath + "/MyClient.exe"; //string PathBar = "C:/Users/Administrator/Desktop/MyClient/MyClient/bin/Debug/MyClient.exe";//TODO address to be determined System.Diagnostics.Process.Start(PathBar); } /// <summary> ///Close progress bar /// </summary> public IEnumerator ClosePrrogressbar() { LoadBar(1); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(ProgressBarExeplore); //Debug.Log("") yield return new WaitForSeconds(0.5f); for (int i = 0; i < process.Length; i++) { process[i].Kill(); } isSave = false; } /// <summary> ///Close progress bar /// </summary> public IEnumerator CloseLoadPrrogressbar() { LoadBar(1); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(ProgressBarExeplore); //Debug.Log("") //yield return new WaitForSeconds(0.5f); for (int i = 0; i < process.Length; i++) { process[i].Kill(); } isSave = false; yield return null; } #endregion
Note that I don't know why the process can't be closed when loading the scenario when it is closed, so I wrote another method to close the progress bar. At the same time, the progress bar Explorer The string type variable is the process name of winform, and the PathBar is the EXE address of winform program. This exe will exist as long as winform program generates a solution.
Main code of Socket communication unit:
#region Socket communication /// <summary> ///Socket communication initialization is to build a server /// </summary> void InitSocket() { //Define listening port and listen to any IP ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8848); //Define socket type, defined in main thread socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //The server needs to bind ip socket.Bind(ipEnd); //Defining clients //IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); //clientEnd = (EndPoint)sender; IPEndPoint ProgressBar = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8849); ProgressBarIPEnd = (EndPoint)ProgressBar; //Debug.Log("waiting for UDP dgram"); ////Start a thread connection, required, or the main thread is stuck //connectThread = new Thread(new ThreadStart(SocketReceive)); //connectThread.Start(); } /// <summary> ///Send message /// </summary> ///< param name = "sendstr" > sent string < / param > public static void SocketSend(string sendStr) { //Clear send cache sendData = new byte[1024]; //Data type conversion sendData = Encoding.ASCII.GetBytes(sendStr); //Send to specified client socket.SendTo(sendData, sendData.Length, SocketFlags.None, ProgressBarIPEnd); } private void Update() { if (Input.GetKeyDown(KeyCode.A)) { SocketSend("0.02"); } } #region comment ///// <summary> /////The server receives the message, which is temporarily unavailable for future use ///// </summary> //void SocketReceive() //{ // //Enter receiving cycle // while (true) // { // //Clear data // recvData = new byte[1024]; // //Get the client, get the client data, and assign values to the client with references // recvLen = socket.ReceiveFrom(recvData, ref clientEnd); // Debug. Log ("message from:" + clientend. Tostring()); / / print client information // //Output received data // recvStr = Encoding.ASCII.GetString(recvData, 0, recvLen); // Debug.Log(recvStr); // //Process and send the received data // //sendStr = "From Server: " + recvStr; // // SocketSend(sendStr); // } //} #endregion /// <summary> ///Send progress message /// </summary> ///< param name = "progress" > progress value < / param > public static void LoadBar(float progress) { int num = (int)(progress * 1000); string msg = num.ToString(); SocketSend(msg); } /// <summary> ///Connection closed /// </summary> public void SocketQuit() { //Close thread if (connectThread != null) { connectThread.Interrupt(); connectThread.Abort(); } //Last close socket if (socket != null) socket.Close(); Debug.Log("disconnect"); } // Use this for initialization void OnApplicationQuit() { SocketQuit(); } private void OnDisable() { //SocketQuit(); } #endregion
The reason for using UDP here is that when I use TCP, the progress is correct due to the simultaneous arrival of data. I am lazy and use UDP directly. If there is something written by TCP, I can send a link for me to learn.
Full code:
using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine; /** *Copyright(C) 2019 by not yet *All rights reserved. *FileName: *Author: Ding ran *Version: BVP3.0 *UnityVersion: 2018.4.0 *Date: 2020-03-03 *Description: *History: */ public class SocketConnect : MonoBehaviour { public static SocketConnect Instance; /// <summary> ///Target socket /// </summary> private static Socket socket; /// <summary> //Client / client /// </summary> private static EndPoint clientEnd; /// <summary> ///Listening port /// </summary> IPEndPoint ipEnd; /// <summary> ///Received string /// </summary> public static string recvStr; /// <summary> ///Sent string /// </summary> string sendStr; /// <summary> ///Received data, must be bytes /// </summary> byte[] recvData = new byte[1024]; /// <summary> ///Data sent, must be bytes /// </summary> private static byte[] sendData = new byte[1024]; /// <summary> ///Received data length /// </summary> private int recvLen; /// <summary> ///Connection thread /// </summary> private Thread connectThread; /// <summary> ///progress port information /// </summary> private static EndPoint ProgressBarIPEnd; private string ProgressBarPath = Application.streamingAssetsPath; private string ProgressBarExeplore = "MyClient"; /// <summary> ///Saving or not /// </summary> public bool isSave = false; private void Awake() { if (Instance == null) { Instance = this; } InitSocket(); DontDestroyOnLoad(this.gameObject); } #region Socket communication /// <summary> ///Socket communication initialization is to build a server /// </summary> void InitSocket() { //Define listening port and listen to any IP ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8848); //Define socket type, defined in main thread socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //The server needs to bind ip socket.Bind(ipEnd); //Defining clients //IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); //clientEnd = (EndPoint)sender; IPEndPoint ProgressBar = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8849); ProgressBarIPEnd = (EndPoint)ProgressBar; //Debug.Log("waiting for UDP dgram"); ////Start a thread connection, required, or the main thread is stuck //connectThread = new Thread(new ThreadStart(SocketReceive)); //connectThread.Start(); } /// <summary> ///Send message /// </summary> ///< param name = "sendstr" > sent string < / param > public static void SocketSend(string sendStr) { //Clear send cache sendData = new byte[1024]; //Data type conversion sendData = Encoding.ASCII.GetBytes(sendStr); //Send to specified client socket.SendTo(sendData, sendData.Length, SocketFlags.None, ProgressBarIPEnd); } private void Update() { if (Input.GetKeyDown(KeyCode.A)) { SocketSend("0.02"); } } #region comment ///// <summary> /////The server receives the message, which is temporarily unavailable for future use ///// </summary> //void SocketReceive() //{ // //Enter receiving cycle // while (true) // { // //Clear data // recvData = new byte[1024]; // //Get the client, get the client data, and assign values to the client with references // recvLen = socket.ReceiveFrom(recvData, ref clientEnd); // Debug. Log ("message from:" + clientend. Tostring()); / / print client information // //Output received data // recvStr = Encoding.ASCII.GetString(recvData, 0, recvLen); // Debug.Log(recvStr); // //Process and send the received data // //sendStr = "From Server: " + recvStr; // // SocketSend(sendStr); // } //} #endregion /// <summary> ///Send progress message /// </summary> ///< param name = "progress" > progress value < / param > public static void LoadBar(float progress) { int num = (int)(progress * 1000); string msg = num.ToString(); SocketSend(msg); } /// <summary> ///Connection closed /// </summary> public void SocketQuit() { //Close thread if (connectThread != null) { connectThread.Interrupt(); connectThread.Abort(); } //Last close socket if (socket != null) socket.Close(); Debug.Log("disconnect"); } // Use this for initialization void OnApplicationQuit() { SocketQuit(); } private void OnDisable() { //SocketQuit(); } #endregion #Display and hide of region progress bar /// <summary> ///Wake up progress bar /// </summary> public void ShowProgressbar() { System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(ProgressBarExeplore); // return new WaitForSeconds(0.5f); for (int i = 0; i < process.Length; i++) { process[i].Kill(); } isSave = true; string PathBar = ProgressBarPath + "/MyClient.exe"; //string PathBar = "C:/Users/Administrator/Desktop/MyClient/MyClient/bin/Debug/MyClient.exe";//TODO address to be determined System.Diagnostics.Process.Start(PathBar); } /// <summary> ///Close progress bar /// </summary> public IEnumerator ClosePrrogressbar() { LoadBar(1); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(ProgressBarExeplore); //Debug.Log("") yield return new WaitForSeconds(0.5f); for (int i = 0; i < process.Length; i++) { process[i].Kill(); } isSave = false; } /// <summary> ///Close progress bar /// </summary> public IEnumerator CloseLoadPrrogressbar() { LoadBar(1); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(ProgressBarExeplore); //Debug.Log("") //yield return new WaitForSeconds(0.5f); for (int i = 0; i < process.Length; i++) { process[i].Kill(); } isSave = false; yield return null; } #endregion }
There is no call to wake-up process function here. You need to write another call to ShowProgressbar().
There is not much code in winform program, which is to establish Socket connection and display the progress bar of receiving message update
Socket code of winform program:
string recvStr; string UDPClientIP; //string editString = "hello wolrd"; Socket socket; EndPoint serverEnd; IPEndPoint ipEnd; //string sendStr; byte[] recvData = new byte[1024]; byte[] sendData = new byte[1024]; int recvLen = 0; Thread connectThread; void InitSocket() { try { ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8849); socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); serverEnd = (EndPoint)sender; socket.Bind(ipEnd); //ShowMsg("waiting to connect"); //SocketSend("hello"); //Showmsg (connect); //Open a thread connection connectThread = new Thread(new ThreadStart(SocketReceive)); connectThread.Start(); } catch (Exception) { //ShowMsg("server not turned on..."); //throw; } } void SocketSend(string sendStr) { //empty sendData = new byte[1024]; //data conversion sendData = Encoding.UTF8.GetBytes(sendStr); //Send to the specified server socket.SendTo(sendData, sendData.Length, SocketFlags.None, ipEnd); } //Server receive void SocketReceive() { while (true) { recvData = new byte[1024]; try { recvLen = socket.ReceiveFrom(recvData, ref serverEnd); } catch (Exception e) { ShowMsg(e.ToString()); //Debug.LogException(e); } if (recvLen > 0) { recvStr = Encoding.UTF8.GetString(recvData, 0, recvLen); ShowMsg(recvStr); LoadBar(recvStr); } } } //Connection closure void SocketQuit() { //Close thread if (connectThread != null) { connectThread.Interrupt(); connectThread.Abort(); } //Last close socket if (socket != null) socket.Close(); } void OnApplicationQuit() { SocketQuit(); }
Progress bar update code:
/// <summary> ///Progress bar update /// </summary> /// <param name="msg"></param> void LoadBar(string msg) { int num; if (int.TryParse(msg, out num)) { progressBar1.Maximum = 1000; progressBar1.Value = num; //textBox1.AppendText("current progress:" + ((float)num / 10)).ToString() + "%\r\n"); label1.Text = (((float)num / 10)).ToString() + "%"; this.Update(); } }
Full code:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Windows.Forms; namespace MyClient { public partial class Form1 : Form { public Form1() { InitializeComponent(); InitSocket();//Start UDPServer //InitTCPServer(); / / start TCPServer //LoadBar("500"); } /// <summary> ///Disable Alt F4 close window function /// </summary> /// <param name="e"></param> protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); //e.SuppressKeyPress = (e.Alt && e.KeyCode == Keys.F4); e.SuppressKeyPress = (e.KeyData == (Keys.Alt | Keys.F4)); // Prevents the current control from receiving keys. } /// <summary> ///Console display message, closed /// </summary> /// <param name="str"></param> void ShowMsg(string str) { //textBox1.AppendText(str + "\r\n"); } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; } /// <summary> ///Progress bar update /// </summary> /// <param name="msg"></param> void LoadBar(string msg) { int num; if (int.TryParse(msg, out num)) { progressBar1.Maximum = 1000; progressBar1.Value = num; //textBox1.AppendText("current progress:" + ((float)num / 10)).ToString() + "%\r\n"); label1.Text = (((float)num / 10)).ToString() + "%"; this.Update(); } } string recvStr; string UDPClientIP; //string editString = "hello wolrd"; Socket socket; EndPoint serverEnd; IPEndPoint ipEnd; //string sendStr; byte[] recvData = new byte[1024]; byte[] sendData = new byte[1024]; int recvLen = 0; Thread connectThread; void InitSocket() { try { ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8849); socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); serverEnd = (EndPoint)sender; socket.Bind(ipEnd); //ShowMsg("waiting to connect"); //SocketSend("hello"); //Showmsg (connect); //Open a thread connection connectThread = new Thread(new ThreadStart(SocketReceive)); connectThread.Start(); } catch (Exception) { //ShowMsg("server not turned on..."); //throw; } } void SocketSend(string sendStr) { //empty sendData = new byte[1024]; //data conversion sendData = Encoding.UTF8.GetBytes(sendStr); //Send to the specified server socket.SendTo(sendData, sendData.Length, SocketFlags.None, ipEnd); } //Server receive void SocketReceive() { while (true) { recvData = new byte[1024]; try { recvLen = socket.ReceiveFrom(recvData, ref serverEnd); } catch (Exception e) { ShowMsg(e.ToString()); //Debug.LogException(e); } if (recvLen > 0) { recvStr = Encoding.UTF8.GetString(recvData, 0, recvLen); ShowMsg(recvStr); LoadBar(recvStr); } } } //Connection closure void SocketQuit() { //Close thread if (connectThread != null) { connectThread.Interrupt(); connectThread.Abort(); } //Last close socket if (socket != null) socket.Close(); } void OnApplicationQuit() { SocketQuit(); } } }
winform program Demo: