Many ways to run a script

Posted by Friday, July 15, 2016 11:10:00 PM Categories: basics c# Easy Freedom Script Unity Windows
Rate this Content 1 Votes

Many ways to run

In the earlier quick start guides I stated there are many different ways to run a FS script. Freedom Script (FS) lets you choose how based on your application. FS won’t lock you into a design model but instead gives you options. If your FS script will be loading game level assets or layout you would want the entire script to execute and finish. The same would apply if you wanted to load unit values like heath or starting positions. A different run model would be needed if the script monitored input or other game variables like enemy positions for AI. This type of script would need to be continuously running and doing its job.   Freedom script gives you the freedom to do both.

In our quick start guides we created a “run once” script such as for level loading. In this guide we will build on the lessons learned and demonstrate how to run a FS script continuously.   I will not go back through all the steps to on setup and how to define FS functions. Please review the quick start guides if you need a review.

In our project will we create a FS script that loops and increments the X position of a cube.  We start it at x position 0 and loop until it reaches 100. If we run this script all at once such as in the Awake() function it would not work. We would see the cube at X = 0 it would pause then appear at x = 100.  A different approach is required.

Let us do some set up.

Create an empty scene  and then a cube at position X:0 Y:0 Z:0.

Create a C# script called Blockmove and attach it to the cube.

Confirm you placed the FS dll (interp.dll) in the scripts folder

Position the camera to keep an eye on the cube it will move in the X direction.

Here is the code from our FS script:

targetX = 100
currentX = 0
while currentX < targetX DO
                        'for counter = 1 to 100 DO
                        '           counter = counter + 1
                        'endfor
                       
                        currentX = moveblockX(1)
                        print(currentX )     
endwhile
print("all done! : FS")

 

we have some lines commented out at this stage, we will remove it later.  You may recall the ‘ (quote) symbol marks the line as a comment and will not execute.  FS will just skip over anything after  ‘

Create a text file with this FS code and save it under assets/Freedom Demo/Freedom Script Demo/ and I call mine moveblockscript.txt  You can change the folders and name of the script, just do not forget to  adjust the code to point to it.

In unity click on the Blockmove c# script you created, and add the two using statements we need.

using System.IO;
using Interp;

We need to create and store an Interpreter object as well as load our FS script in the unity Awake() function. This should be familiar as we followed the same design pattern in our earlier guide.

public class Blockmove : MonoBehaviour {
    Interpreter interp;
    void Awake()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "BlockmoveDemo.txt";
 
        interp.RegisterSubroutine("moveblockX",new moveblocktoXSubroutine(this));
        interp.RegisterSubroutine("print", new printSubroutine(this));
        try
           {         
             interp.Load(new StreamReader(_filename));
             print("File Loaded");
        }
           catch (SyntaxError ex)
           {
                  print(ex.Message);   
           }
        catch(InternalError ex)
        {
            print(ex.Message);
        }
        catch(System.Exception ex)
        {
            print(ex.Message);
        }
    }
   
    void fsPrint(string what)
    {
        print(what);
    }    

We made the example a bit more verbose.  Don’t forget to adjust the path name if you used your own.  We can work down the code. 

Create and store an Interpreter object

Construct a filename with the path to the FS script file

Next we register two keywords or subroutines. (we will look at that code in a moment) They are called “moveblockX” and “print”, Recall by doing this we added new commands which we can call from our FS script using the same name.

The next section I demonstrate FS’s support for standard c# error handling. By using a try/catch block. We will trap FS script syntax and runtime errors. We print the errors to the unity console if we get one.  Otherwise we load the FS script.

Next you may notice like our other examples a function that calls unity’s print function called FsPrint().  It accepts a string and prints it to the console. We defined this function to show how we can call back from our Subroutine Objects to unity.

Now let’s look at the two subroutines we added to our language.

public class printSubroutine : Subroutine
     {
          private Blockmove _parent = null;
          public printSubroutine(Blockmove vparent)
         {
              _parent = vparent;
             num_parameters = 1;
          }
          public override Value Execute(Value[] args, VarCollection vars)
         {
              _parent.fsPrint(args[0].content.ToString());
            return null;
          }
      }

   The print routine is very basic and should be familiar by now. It takes one parameter that was passed from our FS script, the string to print. Using the reference to it’s parent we call the FsPrint() we defined earlier. The string to print is stored in arg[0] (the first) and we only expect one parameter from our script.

Next is the moveblockX() function. 

public class moveblocktoXSubroutine : Subroutine
    {
        private Blockmove _parent = null;
         public moveblocktoXSubroutine(Blockmove vparent)
        {
            _parent = vparent;      
            num_parameters = 1;
         }
             public override Value Execute(Value[] args, VarCollection vars)
        {
           Vector3 currentpos = new Vector3(_parent.transform.position.x,_parent.transform.position.y,_parent.transform.position.z);
            int temp = int.Parse( args[0].content);
            currentpos.x += temp;
 
            _parent.transform.position = currentpos;
            return new Value(Interp.Types.DOUBLE, currentpos.x.ToString());
        }
    }

 

 Like before it accepts one parameter stored in arg[0], this is the number of units to move the block in the x direction. As you recall, internally all FS values are strings so we need to convert it to an int with int.Parse().

We create a new Vector3 and using the reference to its unity parent we get the cubes transform values and store them in currentpos (The Vector3).

We add the number the FS script passed in as the number of X units to move the cube. We stored it in temp. We then add that value to the X position of our currentpos vector3.  

Now all we do is set the cubes transform.position to our currentpos. This effectively moves the cube to the new ‘offset position’ We want to return the new X value to the FS script so we can update our FS script variables and show off our FS script print command.  As described in the guides on the Value Object, values in FS script are stored internally as strings and with a type marker (string/int/double) So we create a new Value object, mark it as a double and insert a string representation of the current X position. Then we return it to the FS script. Again most of this should be a review, but now to the new stuff.

In our previous examples, the one shot ‘setup type’ FS scripts we ran the FS script in the Awake().  Awake() only runs one so we run the Interpreter with StepbyStep.No flag

interp.Run(StepByStep.NO);

 This runs the entire script and will not return until an exit condition is read.

Using the StepbyStep.STEPOVER flag it will run or evaluate one block of code at a time. Most of the time it is one line but in the case loops and if/then it may be more.

interp.Run(StepByStep.STEP_OVER);

 

we want to keep running script code until we reach the end of the FS script, but return after each line. The FixedUpdate() function in unity is perfect. We add a loop to detect when the end of the script is reached and some error checking and we are done.

void FixedUpdate()
    { 
        if (!interp.AtEndOfCode())
        {
            try
            {
                interp.Run(StepByStep.STEP_OVER);
                print(interp.LastExecutedLine().ToString());
            }
            catch (RuntimeError ex)
            {
                print(ex.Message);     
            }
            catch (InternalError ex)
            {
                print(ex.Message);
            }
        }

I will list the entire unity class for review.

using UnityEngine;
using System.Collections;
using System.IO;
using Interp;
public class Blockmove : MonoBehaviour {
    Interpreter interp;
    void Awake()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "BlockmoveDemo.txt";
 
        interp.RegisterSubroutine("moveblockX",new moveblocktoXSubroutine(this));
        interp.RegisterSubroutine("print", new printSubroutine(this));    
        try
           {         
                   interp.Load(new StreamReader(_filename));
             print("File Loaded");
        }
           catch (SyntaxError ex)
           {
                  print(ex.Message);    
           }
        catch(InternalError ex)
        {
            print(ex.Message);
        }
        catch(System.Exception ex)
        {
            print(ex.Message);
        }
    }
 
    void fsPrint(string what)
    {
        print(what);
    }
      
    void FixedUpdate()
    {
        if (!interp.AtEndOfCode())
        {
            try
            {
                interp.Run(StepByStep.STEP_OVER);
                print(interp.LastExecutedLine().ToString());
            }
            catch (RuntimeError ex)
            {
                print(ex.Message);
            }
            catch (InternalError ex)
            {
                print(ex.Message);
            }
        }
    }

 

Click back into unity to check for errors then let’s take a closer look at the FS script.

targetX = 100
currentX = 0
WHILE currentX < targetX DO
           
                        'FOR counter = 1 to 100 DO
                        '           counter = counter + 1
                        'ENDFOR
                       
                        currentX = moveblockX(1)
                        print(currentX )
ENDWHILE
print("all done! : FS")

 

As you may understand now, we loop from 0 to 100 then print that we are done. In each loop we call moveblockX(n) witch moves the cube some amount on the x axis and returns that value, which we use as our stop condition (targetX)  

Run the code and watch the block move, now change the value we passed to moveblockX() and run the code again. See it move faster or slower.

Remove the ‘ from the script, uncommenting them . Enabling these lines introduces a delay loop. Run the script and see what happens in unity.

Hope you had fun,

Bill R

2016

Site Map | Printable View | © 2008 - 2020 GoodCarma.net | GoodCarma.net | Community Tools since 2008 | SmithTown New York