Categories
Advanced Tutorials

Introduction to Lua Scripting in Crayta

Preface

Scripts are the way to make your Crayta entities come to life by defining custom logic and behavior. All Crayta scripts are written in regular Lua, a lightweight and high-level programming language widely used in the video game industry.

In this tutorial you will learn how to start writing scripts by learning how to add/edit scripts through the editor, exploring the structure used by Crayta, the properties and methods commonly used and also how to start debugging your code.

Scripts can define reusable behaviors that extend the general purpose functionality Crayta implements. Here is an example of a simple script that gives a random rotation to an entity each time you press the interaction key:

local Rotate = {}

function Rotate:OnInteract(player)
    local rotation = Rotation.New(0, math.random(360), 0)
    self:GetEntity():SetRotation(rotation)
end

return Rotate 

When creating a script the user inputs a name. The script created can then be attached to any number of entities using a script component.

Here are a couple of ways a script exists in Crayta:

  • As an asset, a Lua  file that contains the script definition.
  • As a script component, which is the base Crayta class that loads a script asset and attaches it to an entity. This is what you can see and adjust in the editor Property window.
  • As a script instance, an instance of the object defined in the script and created on runtime for every entity that has this script attached as a script component.

If you are coming from a Unity background to Crayta you will feel right at home. 

The way a Unity C# script creates a component to extend the behavior of a GameObject, is similar in Crayta with a Lua script using a script component to add custom behavior to an Entity.

Creating scripts

There are several ways to create new scripts in Crayta. Here are two common ways to do so:

By right-clicking in any entity in the World Tree window and selecting Add -> Script->New Script from the contextual menu.

  • This action will create a new script asset and also attach it to the selected entity using a script component.
  • By navigating to Scripts in the Library and selecting Create New Asset.

A name has to be provided each time you create a new script.

Editing scripts

In the same manner editing any script can be done in two ways:

  1. By selecting the entity in the World Tree window, navigating its components to find the script in question and clicking the edit icon. 
  2. By finding the script in the Scripts Library and double clicking on it or right click -> Edit.

Both actions will open the Code Editor allowing you to easily edit your Lua scripts directly inside Crayta.

Anatomy of a script

Let’s analyze a basic Crayta script to better understand its structure:

local Rotate = {}

Rotate.Properties = {
    { name = "duration", type = "number", default = 2 }
}

function Rotate:Init()
    self.rotation = Rotation.New(0, 0, 0)
end

function Rotate:OnInteract(player)
    self.rotation.yaw = math.random(360)
    self:GetEntity():AlterRotation(self.rotation, self.properties.duration )
end

return Rotate

Let’s break down each section of the script.

Script declaration

local Rotate = {}

Declaring a Crayta script is as simple as defining a Lua table. The table can be stored to a local variable using any name, although a good practice is to keep them the same with the script name

Script properties

Rotate.Properties = {
    { name = "duration", type = "number", default = 2 }
}

This table (properties bag) can hold one or more script properties that are automatically parsed by Crayta and exposed to the editor. Each property is a table containing a number of attributes expected by Crayta.

Each property requires a name and a type attribute and there are optional attributes like min, max, default etc (explained in the Property Types Guide) that can be added to some property types.

Exposing script properties to the editor is powerful. It allows you to easily reuse the same script across different entities, and customize the behavior for each entity directly from the editor, allowing that way even designers/non-coders to adjust the game logic.

Initialize

function Rotate:Init()
    self.rotation = Rotation.New(0, 0, 0)
end

Each Crayta script can have an initializer method that is called automatically on each entity that the script is attached to. This method is called only once for each entity and is useful for preparation logic, defining variables and setting the initial state of the entity.

There are three types of initialize methods in Crayta: Init(), ClientInit(), LocalInit() which are be explained in the Events Functions Guide.

OnInteract

function Rotate:OnInteract()
    self.rotation.yaw = math.random(360)
    self:GetEntity():AlterRotation(self.rotation, self.properties.duration )
end

This is a method Crayta will call automatically when the Interact button is pressed on the entity (e.g. player targeting the entity and pressing keyboard E with the default mappings or the left face button on the controller).

There are plenty of useful methods that Crayta can call like OnTick, OnInteract, OnXActionPressed, OnUserLogin, OnTriggerEnter etc, also explained in the Events Guide.

Return

return Rotate

This is the default way to close a script and should come last after all the script methods.

The way Crayta parses and loads the script is by running it from top to bottom filling the Rotate table that is returned at the end of the script.

Even though Unity and Crayta use different programming languages for script authoring it is easy to spot several similarities.

Unity spawns a C# class to hold all properties/methods of a script, that would be the Lua table declared in the first line of the Crayta script.

In Unity public properties are exposed in the editor with various attributes, that would be the properties bag table in the Crayta script.

The Start() and Update() methods used by Unity to initialize and update the script, would be the Init() and OnTick() methods (in all their variants) in Crayta.

Debugging

Basic syntax errors in the code will generally highlight the relevant line in red to point it out:

Attempting to save a script that contains one or more syntax errors will produce an error in the Console window, the main tool used to debug Crayta scripts.

Errors printed to the console will provide the script name and a line number to locate the source of the problem in your code.

  • Your best friend to help with debugging any kind of error is using the Print and Printf commands.
  • Printf(string format, … varArgs), this function replaces instances of {1} with the first argument passed in, {2} with the second etc.
function Rotate:OnInteract(dt)
    self.rotation.yaw = math.random(360)
    
    Printf('Rotating {1} to {2} degrees.', self:GetEntity():GetName(), self.rotation.yaw);
    
    self:GetEntity():AlterRotation(self.rotation, self.properties.duration )
end

All messages printed in the console are searchable allowing you easily find something specific.