Using the API
The other tutorials have shown you how to set up a tiles and a generator, without any coding. But now you need to hook up the generation to the rest of your level.
Starting the generator
The easiest way to start working with Tessera is to press the Generate button on the inspector.
However, when it comes to running it in a game, you'lll need to actually launch it programatically. There's two methods for this, Generate and StartGenerate.
Generate will start the generation, wait for it to complete, and the return some details about the result. This is easy to use, but can cause Unity to freeze briefly while the generation runs.
using UnityEngine;
using Tessera;
using System.Collections;
public class MyBehaviour : MonoBehaviour
{
private TesseraGenerator generator;
void Start()
{
generator = GetComponent<TesseraGenerator>();
var completion = generator.Generate();
Debug.Log(c.success);
}
}
StartGenerate instead runs the generation asyncrhonopusly (if the platform supports it). It is intended for use in coroutines.
using UnityEngine;
using Tessera;
using System.Collections;
public class MyBehaviour : MonoBehaviour
{
private TesseraGenerator generator;
void Start()
{
StartCoroutine(MyCoro());
}
public IEnumerator MyCoro()
{
// Start the generation
var run = generator.StartGenerate();
// Waits for it to run
yield return run;
// Get the details of the run.
var completion = s.Result;
Debug.Log(completion.success);
}
}
To do so, you need to call or StartGenerate. Generate will run synchoronously, and return details about the generation. It's easier to use, but can cause noticable stutter if you are doing a big generation. StartGenerate behaves exactly the same, but can be used from a Unity coroutine.
Because co-routines cannot return information, you can instead supply various callbacks using TesseraGenerateOptions. Most commonly, you'll want to set onCreate to replace the behaviour for instantiating new tiles. The default behaviour instantiates them all at once, which can cause stutter.
using UnityEngine;
using Tessera;
using System.Collections;
public class MyBehaviour : MonoBehaviour
{
private TesseraGenerator generator;
void Start()
{
generator = GetComponent<TesseraGenerator>();
StartCoroutine(MyCoro());
}
IEnumerator MyCoro()
{
var options = new TesseraGenerateOptions { onCreate = MyCreate };
yield return generator.StartGenerate(options);
// Any following code will be run after the generation
}
void MyCreate(TesseraTileInstance instance)
{
Debug.Log("Creating " + instance.Tile.gameObject.name);
// Do the default behaviour
TesseraGenerator.Instantiate(instance, generator.transform);
}
}
Generation options
TesseraGenerateOptions lets you customize the generation in much greater detail than the options in the inspector.
onCreate
A callback called for each newly generated tile. By default,
This can be used to customize the output of Tessera (in addition to the output settings).
onComplete
A callback called when the generation is complete. By default, checks for success then invokes onCreate
on each instance.
This can be used to complete replace the behaviour of Tessera after a run has completed.
progress
A callback called with a string describing the current phase of the calculations, and the progress from 0 to 1. Progress can move backwards for retries or backtracing.
Note
progress
can be called from threads other than the main thread.
cancellationToken
Allows interuption of the calculations
seed
Fixes the seed for random number generator. By defult, random numbers from from Unity.Random.
multithreaded
If set, then generation is offloaded to another thread stopping Unity from freezing. Requires you to use StartGenerate in a coroutine. Multithreaded is ignored in the WebGL player, as it doesn't support threads.
initialConstraints
If set, overrides TesseraGenerator.initialConstraints and TesseraGenerator.searchInitialConstraints.
This setting is discussed further below.
onComplete example
Here's an example of overriding onComplete, to so we can create the tiles one at a time rather than all at once:
using UnityEngine;
using Tessera;
using System.Collections;
using System.Collections.Generic;
public class MyBehaviour : MonoBehaviour
{
private TesseraGenerator generator;
void Start()
{
generator = GetComponent<TesseraGenerator>();
StartCoroutine(MyCoro());
}
IEnumerator MyCoro()
{
IList<TesseraTileInstance> instances = null;
var options = new TesseraGenerateOptions
{
onComplete = completion =>
{
if(completion.success)
{
// Store the tile instances for instantion later.
instances = completion.tileInstances;
}
}
};
yield return generator.StartGenerate(options);
if(instances != null)
{
// Loop over every object that we want to create.
foreach(var instance in instances)
{
TesseraGenerator.Instantiate(instance, generator.transform);
// Wait for next frame.
yield return null;
}
}
}
}
Initial constraints
By default, Tessera scans the scene for pins, placed tiles, and volumes, which serve as constraints on generation. Collectively, these are known as "initial constraints". They are described more here.
Scanning the scene for objects, can be quite slow and inconvenient, so Tessera has an API specifically for setting up initial constraints in the generator without instantiating anything.
To use it, create an builder using TesseraGenerator.GetInitialConstraintBuilder.
The builder then has many methods on it for creating ITesseraInitialConstraint
objects. Store as many of these as you like in a list, then pass that list into the generator options (described above) when running the generation.
Example:
var builder = generator.GetInitialConstraintBuilder();
var initialConstraints = new List<ITesseraInitialConstraint>();
// Pins a tile at a given position.
// The tile doesn't need to be in the scene, it can be a prefab.
initialConstraints.Add(builder.GetInitialConstraint(tile, localToWorldMatrix));
// Set up and run the generation.
var generateOptions = new TesseraGenerateOptions();
generateOptions.initialConstraints = initialConstraints;
generator.Generate(generateOptions);
TesseraCompletion
After a run is finished, a TesseraCompletion object is returned.
This gives a complete description of what has been generated. It's also used in the onComplete
callback.
TesseraCompletion has the following properties.
success
True if all tiles were successfully found.
tileInstances
The list of tiles to create.
Big tiles will be listed a single time, and each TileInstance has the world position set.
tileData
The raw tile data, describing which tile is located in each cell.
retries
The number of times the generation process was restarted.
backtrackCount
The number of times the generation process backtracked.
contradictionLocation
If success is false, indicates where the generation failed.
isIncremental
Indicates these instances should be added to the previous set of instances.
grid
Describes the geometry and layout of the cells. See separate Sylves documentations for more details.
gridTransform
The position of the grid in world space. (Sylves grids always operate in local space).
GetGrid
The grid that Tessera uses is available via GetGrid. This gives a Sylves.IGrid
object lets you easily work out the position of each cell, convert positions to cells, and many other operations. The grid is also available in the TesseraCompletion object.
Tessera grids are handled by Sylves, an open source library. You can refer to its own docs for how to use it.
Note
In many places, Tessera uses Vector3Int, which needs to be explicitly cast to a Sylves.Cell when working with Sylves' API.
Note
If you are using a Mesh Surface based grid, then GetGrid() can be quite slow, and you are recommended to cache the result of it.