GoodCarma.net Afforable Tools for Game Development

 

Making the connection from script to unity

Posted by Friday, July 15, 2016 1:55:00 AM Categories: basics c# Easy Freedom Script Unity Windows

The Subroutine Object

Rate this Content 1 Votes

 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   

 

  

2016