Skip to main content

API Library

This page will contain information about Genies-specific API for TypeScript.

File Types

There are three different script file types that can be created for TypeScript coding:

  1. Genies Behavior Script - similar to C# Monobehaviour scripts
  2. ScriptableObject Script - similar to the C# ScriptableObjects scripts
  3. Genies Script - regular TypeScript script that can't be attached to GameObjects or ScriptableObjects

Creating TypeScript Files

In the Project window, right click and select the top GENIES option. There you can create any of the three TypeScript file types.

Creating Files

Using Scriptable Objects

Genies Scriptable Objects work similar to Unity's version but are created a little different.

  1. In the Project window, right click the GENIES > Scripting > Create Genies ScriptableObject Script.
  2. Add your variables to the script.
  3. Right click the script and select GENIES > Create GeniesScriptableObject Instance.
  4. Select the instance and in the Inspector window add the property values.
  5. Reference the instance from a Genies Monobehaviour script.
import { ScriptableObject } from "UnityEngine";

export default class MyScriptable extends ScriptableObject {
public playerName: string;
}

Lifecycle Events

Here is a TypeScript file with all the lifecycle events available in a Genies Behaviour script:

note

A ScriptableObject script only has Awake, OnEnable, and OnDisable lifecycle events implemented.

import { Monobehaviour, Collider, Collider2D, Collision, Collision2D } from 'UnityEngine';

export default class MyScript extends Monobehaviour {

Awake() {}
OnEnable() {}
Start() {}

Update() {}
FixedUpdate() {}
LateUpdate() {}

OnDisable() {}
OnDestroy() {}

OnTriggerEnter(coll: Collider) {}
OnTriggerExit(coll: Collider) {}
OnTriggerStay(coll: Collider) {}

OnTriggerEnter2D(coll: Collider2D) {}
OnTriggerExit2D(coll: Collider2D) {}
OnTriggerStay2D(coll: Collider2D) {}

OnCollisionEnter(coll: Collision) {}
OnCollisionExit(coll: Collision) {}
OnCollisionStay(coll: Collision) {}

OnCollisionEnter2D(coll: Collision2D) {}
OnCollisionExit2D(coll: Collision2D) {}
OnCollisionStay2D(coll: Collision2D) {}

OnGUI() {}
OnMouseDown() {}
OnMouseDrag() {}
OnMouseUp() {}
OnMouseEnter() {}
OnMouseExit() {}
OnMouseOver() {}
OnMouseUpAsButton() {}

OnAnimatorIK(layerIndex: number) {}

OnApplicationFocus() {}
OnApplicationPause() {}
OnApplicationQuit() {}

OnExperiencePaused() {}
OnExperienceResumed() {}
OnExperienceQuit();
}

Types

There are certain limitations with using TypeScript value types and inheriting C# value types that are important to know.

  1. You can’t use TypeScript types as arguments for Unity or C# generic types with the exception of string and number where number will be treated as a float.
  2. You can’t inherit any of the Unity or C# types besides MonoBehaviour or ScriptableObject.

Shim Types

  • int is a utility type that can be used in TS and will translate to int in C#
  • double is a utility type that can be used in TS and will translate to double in C#
  • float is a utility type that can be used in TS and will translate to float in C#
  • long is a utility type that can be used in TS and will translate to long in C#
  • bool is a utility type that can be used in TS and will translate to bool in C#

GameObject Calls

Here are some example lines of code for creating and destroying GameObjects, as well as adding and getting components from GameObjects.

// GameObject Create
const tempObj = new GameObject();
const obj = Object.Instantiate(tempObj);

// GameObject Destroy
Object.Destroy(obj);

// GameObject DestroyImmediate
Object.DestroyImmediate(obj);

// GetComponent with Generic
const myTransform = this.GetComponent<Transform>();

// AddComponent with Generic
const animator = this.gameObject.AddComponent<Animator>();

Coroutines

You can write custom coroutines using generator methods in TypeScript. Here is an example script that creates and starts a coroutine that is counting up every second:

import { WaitForSeconds, MonoBehaviour } from 'UnityEngine';

export default class MyScript extends MonoBehaviour {

private current: number;

Start() {
this.current = 0;
console.log(`Start Coroutine!`);
this.StartCoroutine(this.MyCoroutine());
}

//Generator methods are written with * at the beginning
*MyCoroutine() {
while(true) {
yield null;
console.log(`[${this.current++}]`);
yield new WaitForSeconds(1);
}
}
}

Asynch, Await, and Promises

Adding the modifier asynch to a method allows for asynchronous logic such as using await or Promise. Here is a example script of asynchronous logic:

import { MonoBehaviour } from "UnityEngine";

export class MyScript extends MonoBehaviour {
// Asynchronous function that simulates fetching data from a server
private async fetchData(): Promise<string> {
return new Promise<string>((resolve, reject) => {
setTimeout(() => {
resolve("Data fetched successfully!");
}, 2000); // Simulating a delay of 2 seconds
});
}

// Start is called before the first frame update
public async Start() {
try {
console.log("Fetching data...");
const data = await this.fetchData(); // Wait for the promise to resolve
console.log(data); // Output the fetched data
} catch (error) {
console.error("Error fetching data:", error);
}
}
}
tip

In TypeScript, you use promises instead of Task or UniTask from Unity. However you can still await a Task or UniTask that is defined by the Unity API bindings. You should use promises for any non Unity or Genies API interactions.

Checkout Mozilla's Using Promises docs for more information on promises.

Events

There are two types of events defined in TypeScript.

SignalBus

This is a global system where you register an event name and a function to call. You can pass any arguments needed. Here is an example script that connects a SignalBus event to a UI Button click:

import {MonoBehaviour} from "UnityEngine";
import {Button} from "UnityEngine.UI";

export default class MyScript extends MonoBehaviour {

public b : Button;

private Awake() {
//Register a function to an event, in our case its a custom Log method
SignalBus.on("MyEvent", this.Log);

//On button click, emit the event
this.b.onClick.AddListener(() => SignalBus.emit("MyEvent", 10));
}

private OnDisable() {
//You can disconnect a method from a SignalBus event
SignalBus.off("MyMEvent", this.Log);
this.b.onClick.RemoveAllListeners();
}

private Log(myInt : int)
{
console.log(`Hello World ${myInt}`);
}
}

GeniesEvent

In TypeScript, the GeniesEvent is a replacement for the UnityEvent callback. Here is an example script that connects a GeniesEvent to a UI Button click:

import {MonoBehaviour} from "UnityEngine";
import {Button} from "UnityEngine.UI";

export default class MyScript extends MonoBehaviour {

public b : Button;
//Initialize the GeniesEvent with arguments
private OnButtonClick : GeniesEvent<[int, string]> = new GeniesEvent<[int, string]>();

private Awake() {
//Add a listener function to the event
this.OnButtonClick.addListener(this.OnButtonClicked);
//Trigger the event when the button is clicked
this.b.onClick.AddListener(() => this.OnButtonClick.trigger(1, "Hello World"));
}

private OnDisable()
{
//Remove the listener function
this.OnButtonClick.removeListener(this.OnButtonClicked);
this.b.onClick.RemoveAllListeners();
}

private OnButtonClicked(myInt : int, myString : string)
{
console.log(`${myString}_${myInt}`);
}
}

Passing References

The ref and out keywords in C# are used when passing references to variables or structures to methods. In TypeScript, these keywords are not available, but you can achieve similar functionality using $ref and $unref.

Here is an example script that passes references:

import { GameObject, Rigidbody, MonoBehaviour, ParticleSystem } from 'UnityEngine'

export default class MyScript extends MonoBehaviour {

Start() {
const testObject = GameObject.Find("Cube");

// Create references to the components and object
let tempObj = $ref(testObject);

// Check if the GameObject reference is not null
if(tempObj != null) {
// Access the actual value of that reference
let objValue = tempObj.value;
console.log(`tempObj Name : ${objValue.name}`);
}

//Create a ParticleSystem reference
let psRef = $ref<ParticleSystem>();
//Try to get component using reference
if(this.TryGetComponent(psRef))
{
//Release the reference to obtain the value
let psValue = $unref(psRef);
console.log(`ParticleSystem Name : ${psValue.name}`);
}
}
}

Raycast Example

Raycasting is helpful for detecting collision along a ray or inside a shape. The Physics.Raycast method requires a $Ref parameter, so you need to pass a reference.

Here is an example script that can detect if the player clicks on an object with their mouse:

import { MonoBehaviour, Physics, RaycastHit, Input, Camera } from "UnityEngine";

export default class MyScript extends MonoBehaviour {
Update() {
this.MouseControl();
}

MouseControl() {
if (Input.GetMouseButtonDown(0)) {
let ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//Create a reference for the Raycast method parameter
let ref = $ref<RaycastHit>();
if (Physics.Raycast(ray, ref, 1000)) {
//Release the reference to obtain the value
let hitInfo = $unref(ref);
console.log(`Detect Hit!`);
console.log(`hitInfo.collider.name : ${hitInfo.collider.name}`);
} else {
console.log(`Failed to Detect Collision`);
}
}
}
}

Genies Frameworks

Genies SDK

Initialize Genies SDK

This syntax initializes the Genies SDK. This is required to use any of the other Genies frameworks like Avatars, Traits, or Things. It will prompt the log in UI when the project is started.

await GeniesSdk.Initialize();
note

This method is asynchronous and therefore requires the await keyword and also must be in a called in a method that uses the asynch keyword.

User Avatar

Create User Avatar

This syntax creates a new GameObject that includes a User Avatar component. It will return a reference to the UserAvatar component.

await UserAvatar.CreateUserAvatar();

Create and Load User Avatar

This syntax will do the same as CreateUserAvatar method but it will also load the Avatar model and add it as a child object to the User Avatar object.

await UserAvatar.CreateAndLoadUserAvatar();

Load Avatar Async

This syntax loads the Avatar using a given User Avatar component.

await myUserAvatarComponent.LoadAvatarAsync();

Set Animator Controller

This syntax sets the Animator Controller property for a given User Avatar component.

myUserAvatarComponent.SetAnimatorController(myAnimatorController);

Add Overlay

This syntax adds an overlay to the Avatar Overlays property for a given User Avatar component.

myUserAvatarComponent.AddOverlay(myAvatarOverlay);

Remove Overlay

This syntax adds an overlay to the Avatar Overlays property for a given User Avatar component.

myUserAvatarComponent.RemoveOverlay(myAvatarOverlay);