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
Start here
Concepts
Authoring for a build
Playing a story
The generated assets and code
The plugin and sync
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.
| Layer | Unity assembly | Unreal module | Holds | Game engine inside it |
|---|---|---|---|---|
| the engine | TaleShard.Runtime | TaleShardCore | the dialogue engine, the expression evaluator, the payload reader, the save codec, the text pipeline | none, and that is enforced |
| the integration | TaleShard.Unity | TaleShardRuntime and TaleShardUMG | the player wrapper, media loading, entity display, policies, localization strings, the widget | yes β this is where it is allowed |
| the editor | TaleShard.Editor | TaleShardEditor | the code generator and the sync window | editor-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.