Blockly interaction with Unity game

431 views
Skip to first unread message

Garry Gorman

unread,
Aug 23, 2022, 10:58:14 AM8/23/22
to Blockly
Hi All,

I have a game that will be controlled by blockly. I have 2 blocks currently programmed and sending code to the unity game. The code is outputing to the console correctly, however, all the commands appear to be running simultainously, e.g. if I place 3 "move forward" blocks in the workspace and click run, the gameObject only moves forward once. If I add a "turn right" block anywhere on the sequence of blocks, the turn right action and the move forward action occur together. 

When I add the "if" block and the "while" block they output correct javascript but the game appears to try to execute all lines of code at the same time.

I would like them to run in sequence with a short delay, similar to blockly games. 
Any help would be appreciated.

stack.JPGafter execution.JPG

Thanks

Garry

Adam Higerd

unread,
Aug 23, 2022, 11:38:42 AM8/23/22
to blo...@googlegroups.com
Consider making your code generator produce `yield` statements in a generator function, so you can call the generator in FixedUpdate and it'll just run the code up to the next yield.

/s/ Adam

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/38b05899-0f98-4935-8558-4c857261d6a3n%40googlegroups.com.

Neil Fraser

unread,
Aug 23, 2022, 11:44:32 AM8/23/22
to blo...@googlegroups.com
Sadly JavaScript doesn't have a "sleep()" statement, so adding delays is a bit tricky.  There are two approaches.

1) Use a log:
  * Create an empty list.
  * Change your forward() function to just push 'FORWARD' onto the list.  Same with left, right, and any other action.  Don't actually move the boat onscreen.
  * Then call the following 'animate' function:
function animate() {
  var action = LOG.shift();
  if (action === 'FORWARD') moveForward();
  if (action === 'LEFT') turnLeft();
  if (action === 'RIGHT') turnRight();
  if (log.length) setTimeout(animate, 1000);
}

This approach is simple, but doesn't handle if there's non-deterministic input (like another player is using the keyboard to move a shark around) during execution.  One advantage is since execution is run to completion before the first move is made on screen, you know whether the whole task will succeed or not.  Thus in the case of Blockly Games Maze we'll run the animation quickly if we know the user will win, but we'll slow it down if we know the user will fail.  In the former case the user is eager to get onto the next level, whereas in the latter they need to see where they went wrong for debugging.  To date no user has noticed this speed difference, but it helps.

2) Use the JS-Interpreter:
  * https://blockly-demo.appspot.com/static/demos/interpreter/step-execution.html
(View source of that page, ask any questions needed.)

This approach is a bit more complicated since exposing your custom API to the interpreter is never fun.  But it does give you full interactive control of everything.



--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/38b05899-0f98-4935-8558-4c857261d6a3n%40googlegroups.com.


--

Garry Gorman

unread,
Aug 23, 2022, 12:04:05 PM8/23/22
to Blockly
Hi Adam,

Thank you for your response. I really appreciate it.
This sounds promising. My code for the move block below is what I am currently using. I havent updated the 'moveBackward()' code yet. Will you give me an idea of what the yield statements might look like?


Blockly.JavaScript['move'] = function (block) {
    var dropdown_value = block.getFieldValue('VALUE') === "forward" ? 'unityGame.SendMessage("single boat", "StartCoroutine", "MoveForward")' : 'moveBackward()';
    // TODO: Assemble JavaScript into code variable.
    var code = dropdown_value + ';\n';
    return code;
};

I have just changed my Update function to the following and the game is behaving a bit strangely. I included an IEnumerator function to make the boat move forward for 2 seconds when the method is called. What else do you suggest might need to be updated here?

void FixedUpdate()
    {
        if (move)
        {
             elapsedTime = 0f;                      
        }        

        if (elapsedTime < duration)
        {
            transform.Translate(Vector3.forward * Time.fixedDeltaTime * speed);
            elapsedTime += Time.fixedDeltaTime;
        }

        if (Input.GetKeyDown(KeyCode.W)) // for testing purposes
        {
           StartCoroutine(MoveForward());
                                 
        }        

        if (Input.GetKeyDown(KeyCode.D)) // for testing purposes
        {
           StartCoroutine(TurnRight());                        
        }        
    }    

    IEnumerator MoveForward()
    {
        move = true;        
        yield return new WaitForSeconds(duration);              
        move = false;
    }
 

Garry Gorman

unread,
Aug 23, 2022, 1:38:06 PM8/23/22
to Blockly
Hi Neil,

That worked a charm. Thank you very much. You made my day.

Thanks

Garry

Adam Higerd

unread,
Aug 23, 2022, 2:48:52 PM8/23/22
to blo...@googlegroups.com
Yeah, Neil's solution is a lot simpler than mine. The generator trick would have made more sense if you were building C# code.

/s/ Adam

Garry Gorman

unread,
Aug 29, 2022, 8:36:32 AM8/29/22
to Blockly
Hi Again,

I now have 2 new problems.

First, I am using som of the standard Blockly blocks like "repeat 5 times" and functions (see attached pics). I cant change the values in the input boxes, eg I cant change from repeat 10 times to a different value or change the function name. 

Secondly, when I run the repeat 10 times block, the code only executes once in the unity game. 

Any help would be appreciated.

Thanks

Garry

Daniel Phyo

unread,
Sep 14, 2022, 3:45:56 PM9/14/22
to Blockly
Hi, 

Could you share the code which make it work for sequence of events? The solution by Neil. 

Thank you

Mark Friedman

unread,
Sep 14, 2022, 3:49:15 PM9/14/22
to blo...@googlegroups.com
I believe that you are looking for this previous post.

-Mark


Daniel Phyo

unread,
Sep 14, 2022, 3:58:54 PM9/14/22
to Blockly
Hi Mark,

Yeah. But i don't know how to put inside my js script. 

 * Create an empty list.
  * Change your forward() function to just push 'FORWARD' onto the list.  Same with left, right, and any other action.  Don't actually move the boat onscreen.
  * Then call the following 'animate' function:
function animate() {
  var action = LOG.shift();
  if (action === 'FORWARD') moveForward();
  if (action === 'LEFT') turnLeft();
  if (action === 'RIGHT') turnRight();
  if (log.length) setTimeout(animate, 1000);
}

I am trying to add like this. When a block is put into workspace, it will generate this code ("log.push(Right") into the list. same for other blocks they will push their own respection direction. 

I don't know where to call this animate() function from? Should I put inside my function for running the code of workspace? 

I tried to call animate function with a click of button. But it will only move for duration that I set inside setTimeout(animate,1000). Then it stop. 

I am confused by this. 

Mark Friedman

unread,
Sep 14, 2022, 4:35:58 PM9/14/22
to blo...@googlegroups.com
Phyo,

  First off, can you clarify what you mean by "it will only move for duration that I set inside setTimeout(animate,1000). Then it stop"?  Do you mean that it only executes one of the actions in your list and stops or do you mean that it executes all of the actions in the list and then stops.  If it is the former, then something is presumably going wrong in the code for the action itself (e.g. moveForward() in Neil's code).  If it is the latter, then that's the way it is supposed to work; you'll need to re-run your code generation (to put more actions in the list) and call animate() again.  If you are not sure of the answer to the question, then I would suggest putting in a call to console.log within animate() in order to see what is going on.

  It might also be worth taking a look at the documentation for the JS Interpreter (here) that Neil mentioned.  It's an alternative approach to the one where you log your actions to a list, but it might better suit your needs.

  By the way, the links that Neil put into his post appear to be obsolete.  The new ones appear to be:
  Hope this helps!

-Mark


Daniel Phyo

unread,
Sep 15, 2022, 11:57:03 AM9/15/22
to Blockly
Hi Mark,

I try to read all the code and understand it but I think I need read more to fully understand how to use it. 

For now, I perform list of actions in Unity C# script. So, I have 2 buttons for my blockly. One button is to run all codes from blocks which are inside workspace. The code for each code is as below. 

Blockly.JavaScript['movebackward'] = function(block) {
// TODO: Assemble JavaScript into code variable.
var code = 'myGameInstance.SendMessage("Robot", "moveDown", 5);\n';
return code;
};

Inside my C#, I have this function

  void moveDown(float n)
    {
        actions.Add(() => Down(n));

    }

This C# function will add down function into the list that created in C#.  So, it will queue all the instructions that I add. 

I have another button is to execute another inside C# unity. This function is to run all the items inside the list from start to end. 

I achieve the moving animation sequence that I want from the application. 

Daniel Phyo

unread,
Sep 15, 2022, 12:00:17 PM9/15/22
to Blockly
I still got other issues though. I cannot type input into block with text input. I found that it was due to my unity is getting all keyboards input from my website. I am trying to solve it. 

Another thing is. In the workspace, if I drag the block into another place instead of making connection with existing blocks. That block's code is still executed though. 

I am using below code to get all the code from blocks. 

function runCode() {
//Generate JS code and run it
window.LoopTrap = 1000;
Blockly.JavaScript.INFINITE_LOOP_TRAP =
'if(--window.LoopTrap =0) throw "Infinite loop.";\n';
var code = Blockly.JavaScript.workspaceToCode(workspace);
Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
try {
eval(code);

} catch (e) {
alert(e);
}

}


I am using below code to to start my workspace. 

var workspace = Blockly.inject('blocklyDiv',
{
media: '',
toolbox: document.getElementById('toolbox')
});

Garry Gorman

unread,
Sep 15, 2022, 12:13:10 PM9/15/22
to Blockly
Hi Daniel,

I had the same problem with unity hogging the keyboard inputs.
This helped.

Good luck with it

Garry

Daniel Phyo

unread,
Sep 15, 2022, 12:16:58 PM9/15/22
to Blockly
Hi Garry,

Thank you, I will try with that. 

For the action sequence, could you share how you do with javascript with list of actions like Neil explained?

Garry Gorman

unread,
Sep 15, 2022, 12:42:31 PM9/15/22
to Blockly
So here is my code that i am using to send move and turn comands to unity.

// gets instructions from the statement blocks and sends them to this array.
let log = [];


// cycles through the array and gives instructions to unity
function animater() {
  var action = log.shift();  
  if (action === "FORWARD") {
    unityGame.SendMessage("single boat(Clone)", "StartCoroutine", "MoveForward");
  }
  if (action === "LEFT") {
    unityGame.SendMessage("single boat(Clone)", "StartCoroutine", "TurnLeft");
  }
  if (action === "RIGHT") {
    unityGame.SendMessage("single boat(Clone)", "StartCoroutine", "TurnRight");
  }
  if (action === "BACKWARD") {
    unityGame.SendMessage("single boat(Clone)", "StartCoroutine", "MoveBackward");
  }
  if (log.length) setTimeout(animater, 2200);
}

I have a button under my workspace that calls the animater function. I had an issue when the function was called animate so I changed it to animater.
My move blocks simply create code that sends strings like "FORWARD" and "LEFT" to the log array above. When the user clicks "run", the code gets generated sending the strings to the log array. The user then clicks the "animater" button that calls the animator function.

Try that and see how you get on.

Garry

Daniel Phyo

unread,
Sep 15, 2022, 12:47:37 PM9/15/22
to Blockly
Hi Garry,

Thanks for the information. I will try it. Yeah. I also use Coroutine inside my C# to get moving like animation. 

I will try with this also. 
Reply all
Reply to author
Forward
0 new messages