Hello.
I am making a game in which a player has to write a code in order to move the tank (shoot, drive, etc.).
I am using Roslyn Compiler to run an Interpreter (How to Write Your Own Programming Language in C#) which interprets the code written by player and run functions written in Unity. I am facing a problem where i need the interpreter to wait before continuing its execution.
For example:
I have a function “ruch(number)” which stands for “move(number)” and it calls prepared in unity function which moves a tank based on the number (0-5 => which represents NE, E, SE, SW, W, NW). So I write the script
ruch(1); and run it with CSharpScript.RunAsync(code, ScriptOptions.Default.WithImports("System", "UnityEngine", "SplitAndMerge").AddReferences(typeof(UnityEngine.Transform).Assembly, typeof(SplitAndMerge.Program).Assembly));
Then the interpreter “plays” ruch(1); method which is implemented:
protected override Variable EvaluateAsync(string data, ref int from)
{
//Variable is defined as static in the class where this method is placed in.
ifMovementFinished = false;
Debug.LogWarning("Interpreter Thread: " + Thread.CurrentThread.ManagedThreadId);
Variable arg1 = Parser.LoadAndCalculate(data, ref from, Constants.END_ARG_ARRAY);
GameObject gameOb = GameObject.FindWithTag("PlayersScriptHandler");
Dictionary<int, bool> param = new Dictionary<int, bool>();
param.Add((int)arg1.Value, false);
gameOb.SendMessage("makeMovementAsync", param);
if (!param[0])
{
Debug.LogError("You can not go through the wall.");
}
else
{
//Here it should be waiting for the ifMovementFinished variable to become true;
}
ifMovementFinished = false;
return Variable.EmptyInstance;
}
As you can see this function calls makeMovementAsync on a gameobject with tag. It is implemented:
public void makeMovementAsync(Dictionary<int, bool> param)
{
Debug.LogWarning("Main Thread: " + Thread.CurrentThread.ManagedThreadId);
param[0] = GameObject.Find("GameUI").GetComponent<HexGameUI>().setCurrentCell(param.FirstOrDefault(entry => EqualityComparer<bool>.Default.Equals(entry.Value, false)).Key);
if (param[0]) // it means that setCurrentCell has determined the tank can move to this place and it started moving it;
{
StartCoroutine(CR_GetMove());
}
}
IEnumerator CR_GetMove()
{
Thread thread = new Thread(new ThreadStart(async () =>
{
Debug.LogWarning("Thread waiting for movFinish: " + Thread.CurrentThread.ManagedThreadId);
while (!checkIfMovementFinished())
{
await Task.Delay(1);
}
UnRuch.setMovementFinished(true); // it calls Interpreter's function to change ifMovementFinished to true;
}));
thread.IsBackground = true;
thread.Start();
while (thread.IsAlive) yield return null;
yield break;
}
I need it to wait till the bool to come true, because it is when the tank “stops” moving. Not waiting for it to finish causes that if my script was ruch(1); ruch(1); there would be an effect like only one instruction was called because when the second one would be in “progress” the position of tank still wouldn’t be changed by first instruction. Same would happen if i wrote ruch(1); shoot(2); ~ in the future.
As you can see i really need to wait for the change of bool variable. I tried many things - semaphores, creating new threads, but each time it was a failure - it either didn’t wait for the change or i got deadlock - since both main unity thread and interpreter ran by CSharpScript.RunAsync() works on the same thread. Trying to run it on seperate one causes that interpreter can’t find objects from the game. Moreover i can’t try await instruction in interpreter’s function because it is overriding a method and I can’t change method signature.
You guys are my last hope to get that work. ![]()
Edit:
Simply (I really doubt it is possible) I’d like to tell the thread of interpreter and unity that he shouldn’t proceed with interpreter unless the corutine has set the bool to true.