Making FactoIsle
This is the engineering behind FactoIsle — the systems I had to invent so a solo Unity factory game would actually run. Chunks, a compact save, pipes, multiblocks, and a quest graph.
Chunks
The playable world is 512×512 Unity units. Terrain continues past that edge, but anything outside is underwater and empty. I could not load the whole map at once — more than 100,000 entities.
I split it into 32×32 chunks that load and unload with the player. A ticket system I wrote keeps selected chunks resident, so machines still tick off-screen and the player’s current chunk is never dropped.

Saving
On first load, a chunk fills itself from its biome. I split entities into logic and data. The data containers are binary-serializable and hold whatever that entity needs.
When a chunk unloads, each entity writes its container with an id and type. Chunks save independently, so the whole world fits in one file under 10MB.
NBData tag = Data.Get<NBData>(); // Named Binary Data
if (tag.Has("itemInMouth"))
{
int logType = tag.GetInt("itemInMouth");
Entity entity = Library.Entity(logType);
if (entity != null && entity is Log log)
{
_itemInMouth = log;
}
}
Pipes
Automation is the point of the game, so I built pipes as placeable blocks. After a placement, the world rebuilds tube systems from connectivity and machine ports.

Pipes have their own storage and tick, and they save through the same data-container path as entities.
Multiblocks
I did not want machines as prefabs you drop. You place a pattern of blocks; the checker I wrote accepts every rotation and runs on place and destroy.

public override void AssembleMultiblockPattern(MultiblockPattern pattern)
{
pattern.AddBlock(new Vector3Int(0, 0, 0), Library.Entity<BlockPlank>());
pattern.AddBlock(new Vector3Int(1, 0, 0), Library.Entity<BlockPlank>());
pattern.AddBlock(new Vector3Int(2, 0, 0), Library.Entity<BlockPlank>());
pattern.AddBlock(new Vector3Int(0, 0, 1), Library.Entity<BlockPlank>());
pattern.AddBlock(new Vector3Int(1, 0, 1), Library.Entity<BlockPlank>());
pattern.AddBlock(new Vector3Int(2, 0, 1), Library.Entity<BlockPlank>());
pattern.AddBlock(new Vector3Int(1, 1, 1), Library.Entity<BlockMachineAdvanced>());
pattern.AddBlock(new Vector3Int(1, 1, 0), Library.Entity<BlockMachineBasic>());
}
Quests
Quests are the progression layer I used to unlock items, liquids, and machines.

Each quest is a class on a shared base. Requirements, unlocks, and dependencies are declared in code. The story system loads them by reflection; custom state goes into the same entity data containers.
public class ChopTreeQ : Quest
{
public override Sprite GetSprite()
{
return Library.Entity<OakTree>().GetSprite();
}
protected override void OnInit(Action<Requirement> add)
{
add(new GatherRequirement(Library.Entity<OakTree>(), 2));
add(new PickupRequirement(Library.Entity<LogOak>(), 10));
}
public override List<Quest> UnlockedBy(Story story)
{
return new List<Quest>() { story.GetQuest<PickupStoneQ>() };
}
public override List<Entity> UnlockedEntities()
{
return new List<Entity>
{
Library.Entity<Plank>(),
};
}
public override Chapter GetChapter(Story story)
{
return story.GetChapter<TutorialC>();
}
}
The game is in alpha on itch.io.
Part of FactoIsle