Lesson 1: Introduction to Lua and Sinespace API

  1. What is Lua?: Short and sweet: Lua is a lightweight, high-level programming language designed for embedded use in applications. In the case of Sinespace, it is used to interact with Unity based gameobjects and components through the Sinespace API (Application Programming Interface). Sinespace is using Lua version 5.2.
  2. What is the Sinespace API?: This is the Application Programming Interface we use with Lua as both a go-between to standard Unity scripting APIs, as well as Sinespace specific objects and function. There are three sources of information on the Sinespace API: Sinespace Docs website, the autogenerated reference website, and the VS Code/LuaCodeAssist autocomplete.
    • Sinespace Docs Website: https://docs.sine.space/scripting . This is a good place to go to look for examples and explanations of the more thoroughly documented pieces of the API. It’s not 100% complete though.
    • Autogenerated reference website: https://space-files.s3.amazonaws.com/docs/client-scripting/annotated.html . This is a 100% complete reference to all of the Sinespace API. There are not very many script examples or explanation of usage though.
    • VS Code/LuaCoderAssist autocomplete: In VS Code, if you type “Space.”, the autocomplete function should show a list of all the functions, classes, and variables available. If you see a class you want to know the contents of, click or type it and follow it with another “.” To drill down further. It can be a useful way to poke around in the API, and it helps to avoid needing to look at the reference website constantly.
  3. Setting Up Unity and VS Code for Sinespace Scripting
  4. Create a test scene in Unity: Create a new scene. Delete the camera. Add a Plane. Add a Landmark – Landing Zone. Save the scene somewhere in your assets.
  5. How a script is added: A Scripting Runtime component can be added to any gameobject within a clothing, vehicle, gesture, furniture item, region, or pet. For now, let’s create a new gameobject within the scene, then in the inspector panel, click Add Component. Search for Scripting Runtime and select it. There are a lot of configuration options within this component, but we’ll go over most of those later. For now, the ones we are interested in are the Source Code “Script Contents” and “Script” inputs, and the “Wait For Player” and “Wait For Network” checkboxes.
    • Script Contents: This multi-line text box will let you input a script directly within the scripting runtime component, without reliance on external files. It can be a little janky in usage, so proceed with caution. The big “Open in External Editor” button, if VS Code is set up correctly with Unity, should open the contents of this input box within VS Code for editing, and update the input box upon closing VS Code. Scripting within this input also has the advantage that, if the “Allow Runtime Script Editing” box is checked, and the virtual good is set to full source access, and the item is something that can be accessed via the in-game room editor (furniture item or region), you can edit the script on the preview server without re-uploading the item.
    • Script: Instead of using the Script Contents box, you can instead create and edit a .Lua file within your assets and drop that file here.
    • Wait For Player: If your script ever needs to interact with the player avatar in any way, make sure this box is checked.
    • Wait For Network: If your script is doing any kind of networking related actions, check this box.
  6. Create your first Lua file: In the Project pane in Unity, right click on Assets and Create > Folder. Name the folder scripts. Right click the newly created Scripts folder and select “Show In Explorer”. Open the scripts folder in windows explorer. Right click within the folder and select New > Text Document. Rename the file to Day1.lua or something similar. If you don’t have file extensions visible in windows explorer, you will want to enable that so that you can properly change the extension from .txt to .lua. Close windows explorer.
  7. Add the Lua file: Drag the script from your assets in the Project pane to the Script slot within your Scripting Runtime. Double click the script you just dropped in there, and VS Code should open.
  8. One bit of Sinespace API before we continue: Lets write a quick script to make sure things are working as intended. In your open script in VS Code, type in the following:
    Space.Log("Hello World!")
    • Let’s digest this a bit. “Space” is the main Sinespace API table from which we can access the majority of the API. One such function within the Space table is “Log”. This function takes a string argument and outputs it to the console.
    • Now let’s save the lua file (ctrl+s) and go back to Unity. When you first run your scene in unity, the console will get filled up with a lot of warning and errors (hopefully someday this will be fixed), which can make it difficult to see the output of your scripts without digging for it. Click over to the console tab in the bottom pane and you’ll probably see some of this in there already. So, for now, let’s disable the game object that contains our Scripting Runtime so that we can delay the running of our script until we toggle it on.
    • To test out our Hello World script, lets press the play button. Once our avatar lands and is fully loaded and the warnings and errors stop appearing in the console, click the clear button in the console pane. Now enable the gameobject with our scripting runtime and you should see “Hello World” pop up in your console.
    • Stop running the scene by clicking the play button again.
  9. Basic Syntax and Structure: Lua scripts in Sinespace are processed from top to bottom. Before we get into more Sinespace specific things, lets go over some general Lua/scripting knowledge.
    • Comments: Often when you are writing a script, you’ll want to document what certain parts of your code is doing, or to leave yourself reminders. You can do this with single-line or multi-line comments. When the script is executed, the processor will skip over these lines as if they didn’t exist.
      -- This is a single-line comment
      --[[
      This is a
      multi-line comment
      ]]
  10. Variables: In all programming languages, there are named units of data that can be assigned a value and can later be modified. These are known as variables. Variables can have different types of data. In many programming languages, once a variable is defined as a specific type, it can only contain that one type of data. Lua on the other hand is a dynamically typed language. This means that variables do not have types; only values do. There are no type definitions in the language. All values carry their own type.
    • All values in Lua are first-class values. This means that all values can be stored in variables, passed as arguments to other functions, and returned as results.
    • There are eight basic types in Lua: nil, boolean, number, string, function, userdata, thread, and table.
    • Variables can be local or global. If you type “local” in front of a variable definition, it will be local, otherwise it will be considered global. Local variables can be declared anywhere inside a block and will only be accessible within that block. Once processing leaves that block, the variable will be deleted. We’ll talk more about blocks in a bit.
      local numberVar = 10
      local stringVar = "Hello"
      local boolVar = true
  11. Basic Operations: A variable is pretty useless if it never changes.
    • Arithmetic Operations: Lua supports the following arithmetic operators:
      • +: addition
      • -: subtraction
      • *: multiplication
      • /: float division
      • //: floor division
      • %: modulo
      • ^: exponentiation
      • -: unary minus
        local sum = 5 + 3 -- 8
        local difference = 5 - 3 -- 2
        local product = 5 * 3 -- 15
        local quotient = 5 / 3 -- 1.6667
        local remainder = 5 % 3 -- 2
    • String Operations: Concatenation, length, and common string functions.
      local fullName = "Lua" .. " Scripting" -- "Lua Scripting"
      local length = string.len(fullName) -- 13
  12. Control Structures and Blocks
    • Blocks: A block is simply the body of a control structure or function and ends with the “end” keyword.
    • Conditionals: If-else statements generally have the structure of “if expression is true then do something, else do something, end”.
      • Conditionals can use a number of relational operators:
        • == equality
        • ~= inequality
        • < less than
        • > greater than
        • <= less or equal
        • >= greater or equal
      • Conditionals can also use logical operators:
        • and
        • or
        • not
          local a = 10
          if a > 5 then
          Space.Log("a is greater than 5")
          else
          Space.Log("a is 5 or less")
          end
    • Loops: For, while, and repeat-until loops.
      • For: The for statement consists of 2 or 3 expressions between the “for” and the “do”.
        • The first expression is for setting a control variable. For example “i = 1”. This declares a variable “i” and sets its value to 1.
        • The second expression defines what value the control variable should cross before the for loop is terminated. For example, if the control variable starts at 1, and the second expression is 5, as soon as the control variable is > 5, the for loop will stop.
        • The third expression is optional, but is how much the control variable should change by on each loop. By default this is 1. So if the control variable starts at 1, then each loop it would add 1. 1,2,3,4,5…
          for i = 1, 5 do
          Space.Log(i) -- Prints numbers 1 to 5
          end
      • While: A while loop is similar to a for loop, but only checks a single expression. If the expression is true, it loops. If it is false, the loop stops.
        local j = 1
        while j <= 5 do

        Space.Log(j) -- Prints numbers 1 to 5
        j = j + 1
        end
      • Repeat: A repeat is basically a while loop, but with the expression being evaluated at the end of the loop instead of the beginning, and instead of continuing if true, it stops if true, and loops if false.
        local k = 1
        repeat
        Space.Log(k) -- Prints numbers 1 to 5
        k = k + 1
        until k > 5