I am trying to build in unity a basic logon screen. Now I'm building on something if the connection will have delay or so... There will be a dialog, where the progress of connection to server will be written... Like Attempt 1/3, Attempt 2/3...
I have Dialog class, which is building a Dialog window from prefab:
public class Dialog
{
private const string TitleComponent = "Title";
private const string ContentComponent = "Content";
private readonly IPrefabFactory _dialogFactory = new DialogFactory(false);
private readonly GameObject _dialog;
public event ClickHandler Click;
public string Title
{
set => GetTextComponent(TitleComponent).text = value;
}
public string Content
{
set => GetTextComponent(ContentComponent).text = value;
}
public Vector3 Position
{
set
{
_dialog.transform.position = value;
_dialog.transform.localPosition = value;
}
get => _dialog.transform.position;
}
public bool Active
{
set => _dialog.SetActive(value);
get => _dialog.activeSelf;
}
public Dialog(string name)
{
_dialog = _dialogFactory.Create();
_dialog.name = name;
_dialog.GetComponent<DialogBehaviour>().Dialog = this;
SetToCanvas();
}
public void OnClick()
{
Click?.Invoke();
}
private void SetToCanvas()
{
var uiCanvas = Object.FindObjectOfType<Canvas>();
_dialog.transform.SetParent(uiCanvas.transform, false);
Position = new Vector3(0, 0, 0);
}
private TextMeshProUGUI GetTextComponent(string name)
{
foreach (Transform child in _dialog.transform)
{
if (child.name == name)
{
return child.gameObject.GetComponent<TextMeshProUGUI>();
}
}
throw new Exception($"Component with name `{name}` was not found.");
}
}
And I have some server "Manager", where the connection process is running.
private void Connect()
{
Dialog.Active = true;
var attempts = 1;
do
{
Dialog.Content = $"Connecting to server... ({attempts++}/{MaxAttempts})";
try
{
if (Client.CurrentState == ComponentState.Ready)
{
Client.Connect();
}
else
{
Client.Reconnect();
}
}
catch (ConnectionException)
{
attempts++;
}
} while (!Client.IsConnected && attempts <= MaxAttempts);
if (!Client.IsConnected)
{
Dialog.Content = "Connection with server could not be established.";
throw new ConnectionException("");
}
Dialog.Active = false;
}
private void CheckConnection()
{
if (Client.CurrentState == ComponentState.Ready)
{
Connect();
}
else
{
if (Client.CheckConnection()) return;
Connect();
}
}
protected Message SendAndReceive(Message message)
{
CheckConnection();
Message response = null;
try
{
response = Client.Send(message);
}
catch (MessageSendException)
{
Dialog.Active = true;
var attempts = 2;
do
{
Dialog.Content = $"Sending message... ({attempts}/{MaxAttempts})";
try
{
response = Client.TryReceive();
}
catch (MessageSendException)
{
attempts++;
}
} while (response == null && attempts <= MaxAttempts);
}
if (response == null)
{
Dialog.Content = "Server did not send any response. Probably connection is lost.";
throw new MessageSendException("");
}
Dialog.Active = false;
return response;
}
I want to provide some output to screen about whats hapening in that dialog class. But, where is the problem. Everything is so much fast, that the dialog can't even render on the start and during all attempts to connect to server, the main thread is just stucked to the time, when the connection ends.
I was finding something about how to make this happen like in another thread or so... Or find coroutines, but I have no idea how to make this work...
It should work like this:
- Render dialog.
- Write that the connection attempt is running.
- During another attempts update the status.
- If successful dismiss dialog.
After all this happen, something similar should happen with the sending. How to make this working without stucking the main thread and make all steps run smoothly one after another?