Tutorials for Freedom script http://goodcarma.net/home.aspx Freedom Script Tutorials 2016 http://www.rssboard.org/rss-specification mojoPortal Blog Module Info@goodcarma.net 120 Freedom Script Tutorials 2016 Freedom Script Tutorials Info@goodcarma.net no Freedom Script in a Nutshell In a nutshell

A more concise explanation of Freedom Script for programmers.

 

In the previous quick start guides I endeavored to take the point of view of a novice programmer. I tried to explain basic terms and functionality. If you are an intermediate or more advanced programmer it was a little drawn out.  In this guide I will assume you can create basic c# scripts and have a basic understanding of .net language. I do still recommend reading The BASICS first but then jumping right into this guide.

Freedom Script (FS) is a macro language. It’s functionality is folded into three main objects. The Interpreter Object loads, parses and executes scripts that exist external to your unity project. These script files are plain text. The Interpreter object provides the structure for a basic programming language. Inside a FS script there is support for variables (local and global), basic math and string handling and decision and looping constructs. FS even supports user-defined script subroutines that return values. In unity you can run your FS scripts line by line or all at once. Examples would be from the Awake() function to fire once or from its Update() firing repeatedly.  These are all common modern language elements. FS scripts could be created and run in a separate virtual space right out of the box, I am sure you are reading this because you want to connect to your unity project. Here is where the true power of Freedom Script lays.

Through FS’s Subroutine object you create c# objects that will run in unity when a keyword or function call is made from your FS script. You define the code that will execute and the keyword to trigger the code in your FS script. You are effectively extending the Freedom Script language. Each Interpreter object can have its own language definition or one common language depending on your needs. Each unity object can have a distinct Interpreter Object and thus run it’s own scripts and language or a common “gamemanager” Interpreter that fires off commands to other unity game objects. Through the Subroutine Object it is even possible to extend FS’s basic data types. FS does not override anything in unity but runs a separate scripting environment and allows communication between the two environments. Perfect for game programming!

Internally FS script is reduced to an intermediate code and then executed. All script data values are stored internally as enhanced string objects and inserted into a collection. The Value object is the wrapper for all variables in a FS script. Inside your unity c# script you can access these Value objects and create or manipulate them. You use standard C# code to interact with the collection. It would appear from the FS script’s perspective that the variables were updated.

That’s it ! It is simple and straightforward.

Let us quickly go over some code to demonstrate. I will use our move block example. In this example we will run a script from a unity cube’s FixedUpdate() function. In unity this gets called repeatedly and forever.

We want to move a cube incrementally down the X axis until it reaches a X value that we define in script, then reverse the direction and do it again. In FS script will a define a function called moverblockX() and pass it a value to modify the cubes transform thus “moving” it. we will add some IF THEN statements to our FS script to (in)reverse the X value thus the X direction so our poor cube never reaches its destination.

Here is our FS script file: (FS is not case sensitive)

targetX = 100
currentX = 0
dir = 2
WHILE currentX < targetX DO       
                   currentX = moveblockX(dir)
                   print(currentX )
                   IF currentX = 99 THEN
                             dir = -2
                   ENDIF
                   IF currentX = -99 THEN
                             dir = 2
                   ENDIF
ENDWHILE
print("all done! : FS")

 

You can see standard programming structure like While/Do, If/then and variable declarations. These are standard out of the box functionality in FS. I have also used a function called moveblockX(n) and print(), these do not exist in FS and we will define and code their implementation in our unity C# script. (Extending the FS language)

Copy and save that FS script into a project folder. I created a unity project and folders: Assets/Freedom Demo/Freedom Demo Script. You can use anything you like as long as you change the c# code that constructs the path to open the file.

In unity: ( I assume you have basic unity skills)

  • Create a unity project/scene
  • Create a scripts folders for unity C# scripts and a folder for your FS scripts described above
  • Copy the FS script DLL into your unity scripts folder ( this includes it in your unity project)
  • Create a cube and create and attach a c# script, name the script “Blockmove”

Now we are ready to do some coding, open the Blockmove c# script,

We need to add two using statements, one for FS and one to access file IO.

using System.IO;
using Interp;

we need to declare a variable of type Interpreter to hold our reference when we create the object. We do this at the class level so it won’t go out of scope until the cube is destroyed.

Create an Awake() function. Because Awake() only fires once it is a good place to create our interpreter object. We will also add some code to construct a full path name to our FS script file.

  void Awake()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "BlockmoveDemo.txt";

 

 Now we can load our FS script but do not run it yet, we do this through the Interpreter object. I use a Try/Catch block when I do it. If we load the FS script file and it finds a FS script syntax error it will throw an exception.

void Awake()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "BlockmoveDemo.txt";
        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);
    }

As you can see I have also defined a function fsprint() function. All it does is print to the unity console. Recall we used a print() in our FS script code. We will connect the two shortly. I have not shown you the FixedUpdate() yet either, we will get to that in a moment.

 

Recall in our FS script file we used two functions that were not part of the builtin FS language. I called them language extensions. They are print() and moveblockX(). Each new keyword or function you add to your FS language needs to have a corresponding Subroutine object. Take a look at the print() subroutine.

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;
         }
     }

 

There is simply a constructor and an Execute(). Notice it is derived from the Subroutine class; you cannot use the Subroutine class directly. The class name is not important. Subroutine has a base class variable (built in) called num_parameters. This indicates how many will be passed in from your FS script. In our FS print function it is only one. (what we want to print). The design pattern I like to use also stores a reference to the c# unity script that will create this object. We write the constructor to accept and store this reference. I call it _parent. We will Instantiate this Subroutine Object from our Awake() in our Blockmove script in a moment.  Remember the unity c# Blockmove script is derived from unity’s MonoBehaviour, therefore with our parent reference our Subroutine will have access to Blockmove which has access to MonoBehavior.   Simply by using c# “.” Dot notation. 

There will be many times this is not necessary and you won’t code this design pattern. An example would be if you are just preforming calculations or changing FS script variables.

Let us move on…

The next function is the Execute(). This is the meat and potatoes. This function gets called when the FS script encounters the function name. In this case it will be “print” *we have not set this keyword yet so don’t worry you did not miss it.

In this function you will first get passed an array of Value objects. As described earlier, Value objects are just wrappers for FS script variables. In this case the parameters that the FS script print() passed in. (what you want to print).  First in arg[0],second in arg[1] and so on. Use its’s “content” property to cast it into a string and you are ready to do something with it in unity. In this case, we use our parent reference to call the Fsprint() we defined in the unity c# script Blockmove. It simply prints to the unity console. We call it and pass in that parameter.

The second item passed to the Execute() is a reference to a collection holding ALL of the FS script variables.  You can create and insert Value objects into the collection, thereby creating new variables for your FS script or search the collection and modify them.

One item of note, I have included the Subroutine class definition within or “inline” with the Blockmove c# unity script. Only the Blockmove class can see the class we derived from Subroutine. Defining your class outside your unity c# script definition causes unity to treat it as global. This allows other scripts or other Interpreter objects to  use  it. I use this method to share Subroutines, therefore language extensions, between different instances of Interpreters. If two have the same class name unity will throw an error.

Here is the listing for the Subroutine class that will handle the moveblockX() FS script 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());       
        }
    }

    It has the same design pattern as printsubroutine. The Execute() manipulates the cubes transform by adding the parameter that was passed in. (how much to move)  Then we create a Value object, inserting the new X position and returning it to the FS script. The FS script returns this value from the moveblockX(). Any value you return from a Subrountine Execute() will be returned to the function call in your FS script.  

Awesome we are almost done! So how do we associate the function keyword that the Subroutine Class will handle in Execute()? Example: print or moveblockX.  A simple one liner. Really!

Return back to the Awake() where we created the Interpreter object. After you create the Interpreter just “Register” your subroutine class.

       interp.RegisterSubroutine("moveblockX",new moveblocktoXSubroutine(this));
        interp.RegisterSubroutine("print", new printSubroutine(this));

Use the Interpreter Object’s RegisterSubroutine(). Pass in first the keyword you want to use in your FS script, in this example “print” and “moveblockX”.  Secondly, create an instance of your custom subroutine class in this example “moveblockXSubroutine” and “printsubroutine”.

Insure you pass the Subroutines constructor any parameters you defined. In our example a reference to our blockmove unity class is needed. We can simply use “this”. 

We created our Interpreter, custom subroutines and registered them. We are ready to run our script with the unity scene. To do that we will start the interpreter in our unity FixedUpdate()

 

    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);
            }
        }
    }   

We use an If statement to detect the end of our script and a try/catch block to trap any error we encounter when running our FS script.

Our last item to highlight is the Run() parameters. It takes a StepbyStep enumerator. Passing in a Step_Over and FS will run a block or line of code and stop and wait for the next Run() call. That is what we did in our example.

You can also pass in Step_NO and FS will run the code to its completion before returning. This would not work with our example, but works well in the unity Awake() as a setup script.

Click back to unity to compile your code and check for errors and run the scene. If all went well you should see a cube moving along it’s X axis in one direction then reversing back in the other direction. It never gets to its destination. Try changing your FS script code and change the amount the block is moving by 4 or 10. Restart the scene and observe the change. Try adding a delay in the FS script code to see the effect.

In unity convert your cube into a prefab, then drop a few in the scene. Change the starting X position of a few of the prefabs and run the scene.

There are many ways to implement scripting into your project. The possibilities are many.  Try a project that attaches a FS script onto an empty gameobject to manage or direct the setup of your scene. You should run it from the Awake()  use the STEP_NO flag when you call Run(). This is an excellent way to allow modding in your project.

Whatever your needs are, the design of Freedom Script affords you the tool to create a solution.

Enjoy and Thank You for your support,

Bill R  

  

 

 

 

   

 

 

 


  ...
]]>
http://goodcarma.net/freedom-script-in-a-nutshell.aspx http://goodcarma.net/freedom-script-in-a-nutshell.aspx http://goodcarma.net/freedom-script-in-a-nutshell.aspx Sat, 16 Jul 2016 20:16:00 GMT
Many ways to run a script 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


  ...
]]>
http://goodcarma.net/many-ways-to-run-a-script.aspx http://goodcarma.net/many-ways-to-run-a-script.aspx http://goodcarma.net/many-ways-to-run-a-script.aspx Sat, 16 Jul 2016 03:10:00 GMT
Error checking the SimpleSubroutine project Error checking in our SimpleSubroutine project

 

In our SimpleSubroutine project we did not do any error checking. The Interpreter Object in Freedom script does support c# exceptions.  FS supports and will throw three exceptions when run or loaded.

  • Syntax error (in your FS script)
  • Internal error (error in structure or logic that could not be resolved)
  • Runtime error (something bad happened that would have crashed FS)

Freedom Script will populate the message property of the exception with as much information as it can to help handle the error. I recommend utilizing Try blocks to implement error handling. Below is a standard setup I use.

Interpreter interp = new Interpreter();
        try
        {
            interp.Load(new StreamReader("test.lang"));
            while (!interp.AtEndOfCode())
            {
                interp.Run(StepByStep.STEP_OVER);
//                Console.WriteLine("step at " + interp.LastExecutedLine());
            }
        }
        catch (SyntaxError e)
        {
            Console.WriteLine("Syntax Error:");
            Console.WriteLine(e.Message);
        }
        catch (InternalError e)
        {
            Console.WriteLine("Internal Error:");
            Console.WriteLine(e.Message);
        }
        catch (RuntimeError e)
        {
            Console.WriteLine("Runtime Error:");
            Console.WriteLine(e.Message);
        }

 

 

Bill R 


  ...
]]>
http://goodcarma.net/error-checking-the-simplesubroutine-project.aspx http://goodcarma.net/error-checking-the-simplesubroutine-project.aspx http://goodcarma.net/error-checking-the-simplesubroutine-project.aspx Fri, 15 Jul 2016 20:03:00 GMT
Wrapping up our first script setup Wrapping up our first script

I have done a lot of typing in this series to explain the basics of Freedom Script but our projects needs to be wrapped up. If you recall our goal was to create a print function in our FS script that would print to the unity console.  We have set up our FS interpreter, created a Subroutine Object that defines the function in our FS script and created the unity function that will perform the work.

Let’s review the project without all the background information.

Our FS script file should look similar to this. It is just a regular text file. (FS script is not case sensitive)  My file location was "Assets/Freedom Demo/Freedom Script Demo/”  Make your location where ever you want but then you need to reflect that in the c# code.

FS Script:

'Simple Subroutine Freedom Script
name = "Billy"

print("My name is " & name)
name = "Felicia"
print("Now my name is " & name)

 

We created an empty unity game object named “GameManager”  and attached a c# script. In our example we called the script  “SimpleSubroutine”.  In this script we created a simple function that accepts a string and prints it to the unity console. We named it FreedomPrint().

We used the Awake function of the script to create and store an FS Interpreter object. Then we pieced together the filename of our FS script. We loaded the FS script using the Interpreter’s  Load function.

Let’s  review the C# code up to this point.

public class SimpleSubroutine : MonoBehaviour {
    Interpreter interp  ;
       void Awake ()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "SimpleSubroutineDemo.txt";
 
        interp.Load(new StreamReader(_filename));
     
        print("We are printing this from regular c# scripting inside unity ");
        print("The Freedom Script Named: " + _filename + " has been loaded.");
 
public void FreedomPrint(string vtext)
    {
        print(vtext);      
    }

      ...

To create the link from the FS script, the keyword print, and the unity based function we want to call ,FreedomPrint(), when our FS script see the keyword (“print”) we created a Subroutine Object.  We define that it will accept one parameter which is the string we want to print. Then using a reference to the SimpleSubroutine Class (attached to the gamemanager game object)  we call the FreedomPrint() function passing it the string from the FS script.

Here is the complete Subroutine listing: (without comments)

 

public class PrintFromScriptSubroutine : Subroutine
    {
    private SimpleSubroutine _parent = null;  
    public PrintFromScriptSubroutine(SimpleSubroutine vparent)
        {
            _parent = vparent;
            num_parameters = 1;
        }
    public override Value Execute(Value[] args, VarCollection vars)
        {
            string whatToprint = args[0].content.ToString();
            _parent.FreedomPrint(whatToprint);
            return args[0];
        }
    }

 

Back to our unity script class, we registered our subroutine with the interpreter Object and named it for our FS script.  We used “print”. We put some test unity print statements to demonstrate what and when these are called. Then we ran the unity project thus running the FS script.

Here is the complete listing for the SimpleSubroutine class we attachted to our unity gamemanager:

using UnityEngine;
using System.Collections;
using System.IO;
using Interp;
 
public class SimpleSubroutine : MonoBehaviour {
 
    Interpreter interp  ;
 
       void Awake ()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "SimpleSubroutineDemo.txt";
     
        interp.Load(new StreamReader(_filename));
 
        print("We are printing this from regular c# scripting inside unity ");
        print("The Freedom Script Named: " + _filename + " has been loaded.");
    
        interp.RegisterSubroutine("print", new PrintFromScriptSubroutine(this));
 
        interp.Run(StepByStep.NO);
        print("Run Once");
 
    public void FreedomPrint(string vtext)
    {
        print(vtext);
       
    }
 
}

 

After we run our unity project it will print the defined messages from unity and from FS script in the console window. Since we ran this from the Awake() function, it should only run once and the FS script should run all at once.

We will talk about different ways to run FS scripts such as line by line and error checking in another post.

 

Bill R

 


  ...
]]>
http://goodcarma.net/wrapping-up-our-first-script-setup.aspx http://goodcarma.net/wrapping-up-our-first-script-setup.aspx http://goodcarma.net/wrapping-up-our-first-script-setup.aspx Fri, 15 Jul 2016 19:41:00 GMT
Keeping track of script values The Value Object

The Value Object is a simple object that for the most part functions behind the scenes. FS internally stores values in a Value Object. When you create, read or write values in your FS script a corresponding Value object is created for that value. In a FS script you will never interact directly with these objects. An author of a FS script will need no awareness of this internal object.

 For the C# author, Value objects act as a wrapper for values within a FS script. He/She can create and manipulate these objects like any other C# object. When a FS Script creates a value to store, such as a string or an integer, FS creates a Value object to hold the scripts value and then stores the Value object into a collection class. When a FS script requires the value FS retrieves the Value Object for manipulation.

On the game developers side he/she can create Value objects, set their value and insert them into the collection. (VarCollection). For the FS script author these will be seen as preexisting variables. The game developer can update or change these dynamically therefor updating these values in the FS script.

An example could be the location of a mission waypoint. The mission author could pre load a set of coordinates or mission briefing for the FS script to interact with. To go one step further, in FS script you could author a mission by setting waypoints, briefings and objectives and load them at run time as needed. These would effectively enable modding capabilities. This model also allows you the game developer the ability to add content without re compiling or patching your unity project.

Freedom Script can store values as strings, integers or doubles.(floats). The Value Object has a contains and a type property.     

As described previously, in C# Value Objects are stored in a collection class. They can be accessed in two ways. First is the preferred method. When a Subroutines “Execute” coded is triggered a reference to the VarCollection is passed to the function. This is identical to the way a C# event handles event arguments. The VarCollection is a typed collection of Value Objects

public override Value Execute(Value[] args, VarCollection vars)

 

 <Review the Subroutine Class here>

In C#  you now have access to all the script variables as C# Value Objects.

You can add, remove or update any one of the Value Objects. This is reflected back in the FS script. There are many support properties and methods to help you. Ex. Setvar,getVar..etc

The second path to changing FS script variables is directly from the interpreter object. It allows access to the same VarsCollection. The Interpreter object contains a property “vars”.  The vars property returns the reference to this collection. Design considerations will dictate which method works best for your application. The best code reusability and portability will be to access this collection from the Subroutine Object.

Bill R


  ...
]]>
http://goodcarma.net/keeping-track-of-script-values.aspx http://goodcarma.net/keeping-track-of-script-values.aspx http://goodcarma.net/keeping-track-of-script-values.aspx Fri, 15 Jul 2016 17:44:00 GMT
Making the connection from script to unity  The Subroutine Object

 The subroutine object is the bridge and the key to Freedom Script. (FS) This object holds the c# code in unity that will run when the external FS script encounters a function call. This block of code runs in unity. Because this code runs in a Unity object we can read/write  game data or execute unity functions. You could create additional gameobjects or drive animation as an example.

 The subroutine class is already defined in the Interpreter dll. (interp.dll) To add functions or keywords to our custom FS language that interacts with unity, we simply create a class based on the built in Subroutine class.

public class PrintFromScriptSubroutine : Subroutine
{
}

It is really that easy. The name of the class “PrintFromScriptsSunroutine” is not all that important and is not what the author of a FS script will use. It should reflect what work you plan on doing. I like to add  Subroutine to the end of the name to remind me that class is a Subroutine class.

For each keyword or function call you want in your FS script you will have a corresponding class built from Subroutine. we will get back to this point a little later.

In c# every class needs a ‘constructor’. This is the C# function that gets called when you create an object from a class definition. We need to create one also. There is one item we want from the other unity code. We want to have access to the unity object that created this object, the one that holds the interpreter object.  In some cases this is not required, but it in most it will be desired.  We will create a variable of type SimpleSubroutine to hold the reference to the unity script class that created the Interpreter object.  We then pass that reference into our constructor to hold it. Since this class will actually create this subroutine objects I call it the parent.

Again basic C# and simple enough.

public class PrintFromScriptSubroutine : Subroutine
{
    private SimpleSunroutine _parent = null;  
 
    public PrintFromScriptSubroutine(SimpleSubroutine vparent)
        {
            _parent = vparent;
            num_parameters = 1;  
        }

 

As you can see there is another statement in the code above. The “num_parameters” variable is built into the subroutine class so it exists automatically. This represents the number of variables the FS script plans to pass along(into) when it calls the custom function from our FS script.  An example would be “movefoward(10). This has one parameter of value 10. “Shoot(90,2)” this has two parameters separated by commas.

In our example we just are going to print to the unity console. Therefor we just want to know “what to print”. We set this value to the value of 1 to accept the one string we want to print.

Now here is where we actually write the C# code that will run when the FS script calls the custom function or in other words the custom language extension. We do this by defining or more accurately overriding the execute function.

You as the programmer will never call this function directly. When the interpreter object encounters keywords or function calls in the FS script that is running this will get called. You as the programmer define what code gets executed.

Before we look at this function, let’s jump back into our unity script object we attached to our game manager in the lesson on the Interpreter object (You review it here)

Add this function to the SimpleSubroutine unity class script. All it does it take in a string and print it to the unity console.

  public void FreedomPrint(string vtext)
    {
        print(vtext);
    }

 

Ok, this is the work we want to do when our FS script calls a specific function. We will name or define that FS script keyword shortly. Let us move back to the subroutine class we are working on. Notice we are overriding the built in Execute function. You need that keyword. Also notice two parameters will be automatically passed into this function when it gets called. The first is the args array and the second is  a  VarCollection. We will talk about the first args array in a moment. The second VarCollection represents the scripting environment. In other words all the variables the script knows about. With this object you can change all the values a script can read, write or update.    

    public override Value Execute(Value[] args, VarCollection vars)
        {
            string whatToprint = args[0].content.ToString();
            _parent.FreedomPrint(whatToprint);
 
            return args[0];
        }

 

  A simply array of Value objects is the first parameter. Value objects are explained here.

This holds any parameters the FS script passed along when it called this function. Values objects are wrappers for actual values. These actual values can be retrieved by using its ‘contains’ property.  Recall we defined how many we are expecteding when we set the num_parameters value equal to 1. So we are expecting 1 parameter from the FS. It will be located in the first array position or because the array is zero based the 0 slot. We can grab it and store it in a string with the following line.

  string whatToprint = args[0].content.ToString();

 

 So now whatever value the FS script wants to print to the unity console is stored in the c# string “whattoprint”. If they were more parameters from the FS script they would be stored in the order they were passed in. ex. args[1], args[2], args[n].

Now we have what the FS script wants to print to the unity console, it is simple to do it.

 Our Subroutine class has no knowledge of unity or any of its functions, but it does hold a reference to an object that does. Recall we passed in and stored a reference to the unity gameobject in our constructor. We called it parent. Our parent is of type SimpleSubroutine. SimpleSubroutine is derived from unity’s MonoBehavior and thus inherits access to the unity game engine and for our project the unity console window.

Remember we defined a FreedomPrint() function earlier in our gamemanger object. Let’s call it.

Take our parent variable and call its function passing it what the FS script passed us.

   _parent.FreedomPrint(whatToprint);

 

 All the freedomPrint function does is print a string using the unity print function to the unity console.  

There is one more thing we need to do. We need to define what keyword in the FS script triggers our subroutine object’s Execute function. That is done in the Interpreter object. We use it’s RegisterSubroutine function. It takes two parameters.

The first is the keyword or the name of the FS script function. The second is the Subroutine class we just coded. This Subroutine’s Execute function will get called when the Interpreter objects reads the keyword in the first parameter.

Again this is a simple one liner. Back to inside our gamemanger’s script (SimpleSubroutine) and the Interpreter object we created called “interp”.  We call its RegisterSubroutine function and pass it the keyword to look for. Let’s use “print” and create and pass in the Subroutine Object we coded. (it’s takes a reference to its parent object –  we use this)

interp.RegisterSubroutine("print", new PrintFromScriptSubroutine(this));

 

 We are just about done. Add a print()  function call to your FS script file

Here is an example of an FS script.

'Simple Subroutine Freedom Script
name = "Billy"

print("My name is " & name)
name = "Felicia"
print("Now my name is " & name)

 

The script will print the message in the unity console window.

We now have created a FS script command that when called from script, triggers an in game unity script command. Linking these together links FS and unity together. We did take the long way around so I could in explain some details.

Let me summarize the connections we made here.

Subroutine objects are the C# code that runs when an FS script calls a function that you have defined. We register the subroutine object with the Interpreter by calling the Interpreter’s RegisterSubRoutine function. Here is where we set the name or syntax that triggers the C# code. Effectively we give the function a name for FS script.

Here is a barebones code listing. First the script we attached to the unity gameobject.

public class SimpleSubroutine : MonoBehaviour {
    Interpreter interp  ;
       void Awake ()
    {
        interp = new Interpreter();
        string _filename = null;
 
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "SimpleSubroutineDemo.txt";
     
        interp.Load(new StreamReader(_filename));
        print("We are printing this from regular c# scripting inside unity ");
        interp.RegisterSubroutine("print", new PrintFromScriptSubroutine(this));
 
        interp.Run(StepByStep.NO);
       }
 
    public void FreedomPrint(string vtext)
    {
        print(vtext);
    }
}

 I did not go over how to run the script.  For now use the line above. I will go over the run command in the next tutorial.

Here is our Subroutine class:

public class PrintFromScriptSubroutine : Subroutine
    {
 
    private SimpleSubroutine _parent = null;  
 
    public PrintFromScriptSubroutine(SimpleSubroutine vparent)
        {
            _parent = vparent;
            num_parameters = 1;
        }
 
    public override Value Execute(Value[] args, VarCollection vars)
        {
            string whatToprint = args[0].content.ToString();
            _parent.FreedomPrint(whatToprint);
 
            return args[0];
          }
    }

 

The code is straightforward and demonstrates how the connection from the script file to the C# code is made.

Bill R   

 

  


  ...
]]>
http://goodcarma.net/making-the-connection-from-script-to-unity.aspx http://goodcarma.net/making-the-connection-from-script-to-unity.aspx http://goodcarma.net/making-the-connection-from-script-to-unity.aspx Fri, 15 Jul 2016 05:55:00 GMT
Creating a FS Script Setup - First Steps The Interpreter Object

We are going to simply create a gamemanager and use it to print to the Unity console. A gamemanger is a  non-visible element that could control objects in a  unity scene. Cameras, lights, scores or heath levels are examples of objects a gamemanger could control. A level setup script is another example of a function of a gamemanger and a use for an external script.

We will setup Freedom Script (FS) in unity scene. In this project it will only load a FS script and not run it. We need to make some choices on how to run the script, but we will get to that later.  We will build on this setup to a fully functioning FS instance.  Baby steps first.

  • Create a new empty unity scene.
  • Create a scripts folder under assets
  • Drag and drop the interp.dll into the scripts folder
  • Create an empty c# script in the same folder and name it SimpleSubroutine

Ok, now that all that basic unity stuff is set up, let’s get to work inside the unity scene. Right click in the Hierarchy window and create an empty game object, rename it to GameManager. Now drag the SimpleSubroutine script you created before onto the gamemanger. This attaches the script to this in game object. Notice the class name will match the script file name.

Double click on the SimpleSubroutine ,  script.  Clicking on the name opens the script up in monodevelop or visual studio. (I use visual studio)

Now we need to add the using statements to our C# script. These statments allow us to access the interp.dll or other dll(s) from our code. We always need the interp object to use FS and in this project we also need system IO also. We use this later to get the path to our data directory. You may use different methods at different times.  Let’s add them to our script.  Simple enough:

using System.IO;
using Interp;

 

we need a variable to hold our FS object. Let’s create one in our class. If we declare the variable at the class level it will stay in scope as long as our gamemanger is in scope. Notice we derive this class from MonoBehavior. This is not required but very useful.   

public class SimpleSubroutine : MonoBehaviour
{
Interpreter interp ;
}

 

There are many built in Unity functions that we have access to now.  I want to use the Awake() function.  This function is called by unity when it creates the gamemanager object. It is only called once. This is a perfect place to create the Interpreter Object for FS.

void Awake ()
       {
        interp = new Interpreter();
       }

 

Now that was simple.  In my project I created a folder called Freedom Demo and a sub folder named Freedom Script Demo. I plan on installing and keeping my FS scripts in this folder. So we need  a way for unity to find this folder. We don’t know where the user installed your program but unity does. We use the datapath function in unity to find the asset folder then we tack on the other path elements to create a string holding the file path named '_filename'. There are many ways to do this or even to hard code the path in some cases but the following code is a simple way.

Before we code the load function, lets create a simple text file to hold some FS script.

Using any text editor create a file named SimpleSubrouteDemo.txt

In the newly created text file add these lines.

Type:

name = "Billy"

print("My name is " & name)
name = "Felicia"
print("Now my name is " & name)

Then save the file and add it to that folder. (You can drag it into unity onto that folder) My folder structure looks like this:

Folder setup

 

If you want to use a different folder structure or file name, feel  free but then you will need to adjust  the path in the following code.

 

 

 

Now our script looks like this:

void Awake ()
    {
        interp = new Interpreter();
        string _filename = null;
        _filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/";
        _filename += "SimpleSubroutineDemo.txt";
        interp.Load(new StreamReader(_filename));
}

 

Now as you can see we created the FS interpreter object and constructed and passed a string containing the full path to the file containing the FS script. Using C# we created a streamreader object and passed it to the FS interpreter load function. This loads a text file named SimpleSubroutineDemo.txt.  

If you did it correct it should compile fine. Save your c# code and click back to unity. If you have no errors we are ready to move forward. I added a simple unity print statement at the end of our code to show that the awake() function did trigger once.

       print("We are printing this from regular c# scripting inside unity");

If you have no errors run the program and look at the console window. You should see your message. If you received an error it most likely is in the file path you created.

Add this code to help track down the error.

print("The Freedom Script Named: " + _filename + " has been loaded.");

 

Let us pause here. The code we wrote does not do much yet, but it should give you a good foundation on how create the interpreter object. It really just boils down to two lines of real code.

        interp = new Interpreter();
        interp.Load(new StreamReader(_filename));

Review the code to make sure you understand what we did. Get a cup of coffee and get ready to meet the Subroutine object in the next lesson.

Without comments added this is what my script looks like.

using UnityEngine;
using System.Collections;
using System.IO;
using Interp;
public class SimpleSubroutine : MonoBehaviour {

Interpreter interp ;

void Awake ()
{

interp = new Interpreter();
string _filename = null;


_filename = UnityEngine.Application.dataPath + "/Freedom Demo/Freedom Script Demo/"; // this gets the current data directory

_filename += "SimpleSubroutineDemot.txt";

interp.Load(new StreamReader(_filename));
 
print("We are printing this from regular c# scripting inside unity");
print("The Freedom Script Named: " + _filename + " has been loaded.");
  }
}

  ...
]]>
http://goodcarma.net/creating-a-fs-script-setup-first-steps.aspx http://goodcarma.net/creating-a-fs-script-setup-first-steps.aspx http://goodcarma.net/creating-a-fs-script-setup-first-steps.aspx Thu, 14 Jul 2016 04:45:00 GMT
The Interpreter, Subroutine and Value Objects The Interpreter, Subroutine and Value Objects

 

The Interpreter, Subroutine and Value Objects are the building blocks of Freedom Script (FS). This trio is simple to use. The key to effective FS usage is understanding how to set them up. Let us dive in.

The Interpreter object is the workhorse of FS.  It loads external scripts and runs them. Simply enough it has a load and run function. Basically you attach a Unity C# script to a gameobject.  Then create the Interpreter object in the script. You can use an empty gameobject such as one you may create as a gamemanager for a level or one attached to an in game entity such as a tank or space alien.  The setup is the same. Each Interpreter object you create will create a separate script instance. But you can share custom language elements between each instance. We will get to that soon enough. Though the interpreters object you can run the FS script all at once or step by step. Each technique has its place. A good example is if you are running the script from the AWAKE function possibly for a level setup or from an update function.   Let’s try not to get ahead of ourselves.

The Subroutine object is the connector or bridge from unity to your external FS script files. In theory you don’t have to ever use this object but your scripts would never be able to talk to unity. Your FS scripts would be doomed to computing numbers and strings in its own little universe.  They could never interact with in game elements.  I hope that’s not what we want. The Subroutine object is how you extend or define your custom language. This is where the real power of FS shines.  The subroutine object or more precise the class you will derive from the subroutine object is the c# code you want unity to run. The code can access FS variables (read or write) or any functions or data the gameobject it is attached has access to.  Most MonoBehavior methods and data are exposed.  This is where you extend the basic FS language and gives you endless possibilities and freedom to create your own language!

You will create a class based on the Subroutine object and “register “ it with the interpreter object. As the interpreter object is running your FS script and it encounters the function name you chose to represent this block of code it will execute it. The C# code inside the subroutine class will run. Here is where can you change FS script variables and return the processed data back to the FS script or issue a unity command. You could move an object’s transform or preform a raycast and return the result to the FS script. In this object is where the work gets done and then communicates it back to the FS script. It sounds more complicated than it really is. Once you work with the object you will fall in love with it. (well..ok maybe that’s a bit much)

The last part of the trio is the Value object.  It is the holder of information for your FS scripts. You can create these in your unity c# script and exchange or pass them to your FS script. These objects are the representation of the data on the Unity side. On the FS script side they are just data that can be stored in variables or used in expression.  They are simple C# objects and wrap actual values. They have some built in functions that make working with them easy.  Just remember data inside your FS script is stored as value objects “under the hood” on the Unity side but when the FS script views the data it behaves and you interact with it as if it was just plain old data with no wrapper. All data in Value objects are stored as text strings. In FS scripts, their value is converted based on the context they are used. In your C# code you would convert the string to a number.  Again this sounds complex when you explain it but in practice it is very natural and simple. FS supports strings, integers and floats.   

  

Well that’s it ! Just three simple objects will unlock the world of scripting. It will give you the freedom to create a custom language. True Freedom!


  ...
]]>
http://goodcarma.net/the-interpreter-subroutine-and-value-objects.aspx http://goodcarma.net/the-interpreter-subroutine-and-value-objects.aspx http://goodcarma.net/the-interpreter-subroutine-and-value-objects.aspx Thu, 14 Jul 2016 03:23:00 GMT
Overview and Script Definition Welcome to Freedom Script

What is Freedom Script ?

  • Freedom Script (FS) is language interpreter. It allows custom external language files, which you the game author or you the game player can execute and interact with objects within Unity.
  • These external language files (scripts) are plain text files and require nothing more than a text editor to create and change.
  • Because the language is interpreted and not complied these files can be loaded before or while the game is running.

What does Freedom Script do ?

  • FS provides the structure of a computing language then allows you the game developer to define and/or execute the FS language.
  •  The FS language can even be changed on the fly. This allows the scripts to expose different language elements to the script author dynamically
  • FS will take care of the heavy lifting, freeing you to focus on game development.

 

What language is FS based on?

  • FS uses basic common structure allowing you to just define “Game” functions
  • FS supported language structures
    • Global and local variables
    • User defined Functions that can return values
    • If then else decision structures
    • Looping structures such as
      • For next loops
      • While do loops
  • Common text handling and math functions

 

 

Let's start with FS built in language structures. This comes built into the language:

  • Script Definition  

  • The language is not case sensitive

  • An assignment also declares the variable global, if the variable didn't exist before and if it wasn't declared local within the same SUB.

    • Example would be name = "Bill" or age = 28
  • Values are typed (internally),but FS variables don't have a fixed type. They have the type of the value they're containing
    •  Possible types for values are int, double/real and string. All variables are internally stored as strings. If used in a "string context" an int or double is automatically converted to a string.  If used in an arithmetic context a string is automatically converted to a double (i.e. "12" + 3.5 yields 15.5)
    • simple statements are assignments: “varname = expression” or
    • calls: function name(expression1, expression2, ...)

 

  • Control flow structures
    • Decision branches  
      • IF expr THEN
      •         ...  statements ...
      •     ELSE
      •         ...  statements ...
      •     ENDIF
      • The ELSE part is optional, if there is no ELSE then the ENDIF appears directly after the THEN statements.

 

  • Looping
    • while loops
      •     WHILE expr DO
      •         ... statements ...
      •     ENDWHILE
      • for loops
        •     FOR var = start TO end DO
        •         ... statements ...
        •     ENDFOR

 

  • Special statements
    • RETURN expression -- return from a SUB
    • LOCAL var -- declares that a variable identifier refers to a local variable/visibility
    • Both special statements are only valid inside a SUB... ENDSUB

 

  • Operators:
    • The operators in expressions can be  +, -, *, /, div,mod, ^ and & for string concatenation.
    • There is  also a SUBSTR function for strings.
    • Other operators: =, <, <=, >, >=,  and, or, xor, not
  •  the last two  (xor an not) are only logical, no bitwise variants.   0 and  0.0 and "" are false values, every other value is true from a boolean point of view.

 

  • Operator precedence table (operators on same line – same precedence, lower lines in this text, lower precedence)
    • 0: unary -
    • 1: ^ (exponentiation operator)
    • 2: * / mod div
    • 3: + - & (& is for string concatenation)
    • 4: <= >= = < >
    • 5: not (logical)
    • 6: and (logical)
    • 7: or (logical)

 Of course, variables/SUBs can't use reserved words for names.

 

  • Automatic conversions:
    •  if in an arithmethic/relational operation there is a string
      • operand (and the other operand is numeric) that doesn't parse to a valid numeric value then its numeric value is considered 0
  • if both operands are strings in a relational operation then
    • the strings are compared as strings, not as numbers
    • if at least one of the operands is numeric they are compared as numbers

 

  • Primitive subroutines (build in):
  • error -- 0 arguments, just generates a RuntimeError (example for throwing an exception from a sub)
  • substr -- 3 arguments, a string, a starting position and alength - extracts a substring
  • len -- 1 argument, returns the length of the string or of the string representation of the numerical value passed as an argument

These are just regular Subroutines added to the interpreter. therefore "build in"

If the programmer doesn't use RETURN or LOCAL then the default
behaviour is to have only global variables + parameters.

 

Wow, you made it. If you are a programmer already  you should be familiar with this basic toolset. If you are new to programming do not feel overwhelmed. You most likely won’t need most of these commands. You can learn each function as you need it. I plan on posting many examples.

Google is your friend, these basic language structures are common to many languages. A few searches should provide you with many basic programming examples. As your skills grow rest assured Freedom Script will provide you with the platform to exercise your new knowledge.

 

Bill R.

 

 


  ...
]]>
http://goodcarma.net/overview-and-script-definition-.aspx http://goodcarma.net/overview-and-script-definition-.aspx http://goodcarma.net/overview-and-script-definition-.aspx Wed, 13 Jul 2016 23:42:00 GMT