Skip to content

The two seams

The engine is portable and has no Unity or Unreal in it. The integration layer is where the game engine is allowed. What belongs on each side.

All documentation β€” Concepts
On this page

The plugin is not one assembly. Knowing which is which answers most of the questions that otherwise turn into a wrong design. The split is the same in both engines; only the names differ.

LayerUnity assemblyUnreal moduleHoldsGame engine inside it
the engineTaleShard.RuntimeTaleShardCorethe dialogue engine, the expression evaluator, the payload reader, the save codec, the text pipelinenone, and that is enforced
the integrationTaleShard.UnityTaleShardRuntime and TaleShardUMGthe player wrapper, media loading, entity display, policies, localization strings, the widgetyes β€” this is where it is allowed
the editorTaleShard.EditorTaleShardEditorthe code generator and the sync windoweditor-only, never in a build

In Unity, each optional package gets its own additional assembly, gated on a define, rather than a reference being added to the core one. In Unreal, the same rule holds for modules: TaleShardCore depends on Core and Json only, and a feature that needs more links it from the integration modules, never from the engine.

Why the engine has no game engine in it

TaleShard.Runtime contains no using UnityEngine, and TaleShardCore contains no UCLASS, no USTRUCT and no CoreUObject. That is load-bearing rather than tidy. It is what makes the engine testable headlessly, which is what makes the conformance suite possible β€” the suite that holds the C# engine, the C++ engine and the browser engine to identical step sequences. A single game-engine reference under that layer would take the whole headless gate down with it.

It also means the interesting, defect-prone parts are testable. The HTML parser and the rich-text formatter live in the engine as plain string and struct code, not in the integration layer, for exactly that reason.

The edge that keeps a bad update recoverable

The editor layer may reference the engine, and nothing else. Never the generated code, never your game’s own code. In Unity that is TaleShard.Editor referencing TaleShard.Runtime; in Unreal it is TaleShardEditor depending on TaleShardCore and TaleShardRuntime, with no plugin module allowed to name a generated type.

That single missing edge is what stops a plugin update from bricking a project. Unity does not reload the app domain while any assembly fails to compile, and Unreal does not open a project whose module fails to build. If the editor layer depended on generated code, then generated code that does not compile would take the sync tool down with it β€” and the only tool that can repair generated code would be gone, from inside a state you cannot leave. Keeping the edge absent means the generator is always loadable, whatever the generated output did.

In Unreal this goes one step further: content lands as data, and only a schema change emits C++ β€” generation is on by default and can be turned off in the plugin’s settings β€” so a content sync never needs a compile at all.

Where your own code goes

Presentation β€” your own code. Prefabs and MonoBehaviours in Unity, widgets and Blueprints in Unreal. The plugin hands you steps; drawing them is yours.

A custom media source β€” your own code, implementing the integration layer’s interface.

A custom generator β€” the editor side, because generation happens at sync time in the editor and never in a build. A generator emits source, so everything engine-looking inside it is a string in the emitted output rather than a call.

Anything that must run in a build β€” check that it does not need the editor layer. Editor code is stripped from a player build, and a reference that only exists at author time fails at the worst moment.

Written for
Unity developers Β· Advanced integrators
Last updated