Basic Usage
The included tools may provide you with a basic starting point to start using Tycoon Tile in your project. However, each project may require to modify the terrain based on events specific to your project or needs to respond to any terrain changes. This section explains how to integrate Tycoon Tile with the rest of your project via code.
Modifying tiles with Terrain Operations
Tycoon Tile comes with many terrain operations included. To execute a given operation on the map, call the ScheduleOperation method and pass it an operation instance as a parameter. The map will automatically track changes made by the operation and will regenerate any meshes at the end of the frame as necessary.
using UnityEngine;
using Unity.Mathematics;
using TycoonTerrain.Core;
using TycoonTerrain.Core.TerrainOperations;
public class MyTool : MonoBehaviour
{
// Define reference to TycoonTileMap behaviour instance.
// You can assign this in the inspector.
public TycoonTileMap Map;
// Add a mode switch to toggle between smooth/connected and cliff generating operations.
public bool UseSmooth;
public void Update()
{
// Fire operation scheduling when pressing the left mouse button.
if(Input.GetMouseButtonDown(0))
{
ExecuteMyTool();
}
}
public void ExecuteMyTool() {
// Determine any area you want to modify
var selectedArea = new IntBound(new int2(3, 3), new int2(6, 7));
if (UseSmooth)
{
// Decrease the terrain height by 1 within the selected area
// and update neighbouring tile surfaces
// Such that their surfaces remain connected.
Map.ScheduleOperation(new DecreaseHeightSmoothConnectedOperation(selectedArea));
}
else
{
// Decrease the terrain height by 1 within the selected area
// and create cliffs between neighbouring tiles
Map.ScheduleOperation(new DecreaseHeightCliffOperation(selectedArea));
}
}
}
It is possible to create your own terrain operations if the included ones do not suffice for your use-case. See the Creating Custom Operations section for more information.
Modification event callbacks
Call the TycoonTileMap.RegisterTileListener method and give it a callback function and tile position or bounds to listen for. Whenever the tile at that position or any tiles within the bounds are modified, the callback function will be called. The TycoonTileMap.RegisterTileListener will return a CallbackHandle which you should store somewhere. You can use this handle to unsubscribe from the tile modified event with TycoonTileMap.UnregisterTileListener when required. A common use-case would be to subscribe to this event in your Start or OnEnable method, while unsubscribing in OnDestroy or OnDisable. The included TileListener example class demonstrates an implementation and usage for these events.
using TycoonTerrain.Core;
using Unity.Mathematics;
using UnityEngine;
/// <summary>
/// This is an example script that makes use of the tile listener functionality.
/// It updates the GameObject position when the terrain is modified at its position.
/// Example use cases are rocks, trees or other objects that are attached to the surface.
/// </summary>
public class TileListener : MonoBehaviour
{
// The reference to the Tycoon Tile Map component.
// Assign this in the inspector.
public TycoonTileMap Terrain;
// Store the callback handle such that we can unregister later.
private CallbackHandle callbackHandle;
// Store the corresponding tile position for this object.
private int2 tilePosition;
// Store the last know tile heights for our tile,
// such that we can determine when the tile has actually changed.
private int4 lastTileHeights;
// Start is called before the first frame update
void Start()
{
// Calculate our tile position within the map based on our world position.
tilePosition = Terrain.WorldToTilePosition(transform.position);
// Register callback for terrain modified event
callbackHandle = Terrain.RegisterTileListener(tilePosition, OnTerrainModified);
// Initialize the last tile heights to an invalid value,
// such that we are sure the first update is applied.
lastTileHeights = new int4(-1);
}
private void OnDestroy()
{
// Unregister the callback from the terrain modified event.
Terrain.UnregisterTileListener(callbackHandle);
}
// This callback method will be fired when the tile on our position is modified.
private void OnTerrainModified(TerrainModifiedEvent eventData)
{
// Retrieve a reference to the tile we are located on.
var tile = eventData.Grid.GetTile(tilePosition);
// Retrieve the new tile corner heights.
var newTileHeights = tile.GetData().Heights;
// Check if any corner heights have changed since previous update.
if (!math.all(newTileHeights == lastTileHeights))
{
// If the tile heights were changed,
// update the position of this gameObject.
var position = transform.position;
// Convert unity world position to Tycoon Tile map position.
var mapPosition = Terrain.GetMapPosition(position);
// Convert Tycoon Tile map position to local tile position.
var localPosition = TilePosition.MapToLocalPosition(mapPosition);
// Calculate y axis position of the tile surface
// at our x and z coordinates.
// This returns a Vector3 with our x, z and the calculated y position.
var surfacePosition = handle.GetSurfacePosition(localPosition);
// Move our object to conform to the new position.
// Now we are propely positioned at the tile surface again.
transform.position = Terrain.MapToWorldPosition(surfacePosition);
}
// Store the new position of this update
// Such that we can detect any changes in the future.
lastTileHeights = newTileHeights;
}
}