Class WaveCreator
Generates (or updates) a Wave aggregate asset chain for one stage: an ordered list of
UnityWaveConfigSO assets under <StageFolderPath>/Waves/ and one
UnityWaveSetSO directly under StageFolderPath referencing them, in the exact order
they were authored. Mirrors Serenity.InputGateway.Installation.Editor.Builder.PlayerInputCreator's
multi-asset shape (bottom-up resolve-or-create, then the referencing asset, full rollback on any failure) —
wave configs are the "leaves", the wave set is the "root" that references them, exactly like Device
Filter/Join Gate feeding Routing.
Folder convention, verified against StageSpawnPointProvider, not assumed. The
provider does not require a literal Stages path segment anywhere — it only requires the stage
prefab to sit directly in StageFolderPath and wave assets to sit in
StageFolderPath/Waves/. This engine enforces exactly that (and nothing about the folder's name),
matching what FindStagePrefab(string) and
ScanStagePrefab(string) actually scan — the …/Stages/<Name>/
naming in the cookbooks is a human convention on top of this, not a code requirement.
Spawn-point resolution intentionally bypasses StageSpawnPointProvider's cache —
FindStagePrefab(string)/ScanStagePrefab(string)
are called directly (the same raw scan the cached GetSpawnPointIds wraps) so validation is always
fresh, never stale from a scene/prefab edit the cache has not yet observed via
EditorApplication.projectChanged.
Known, deliberately unfixed semantic gap — ToConfig(). Verified by
reading the source: ToConfig() returns WaveConfig(waveIndex, spawnEntries.Count) — the
domain's TotalActors is the NUMBER OF ENTRIES, not the sum of each entry's Count. A wave
with one entry authored with count = 5 reports TotalActors == 1 at runtime (and
WaveState will consider the wave cleared after a single RecordActorRemoved(), even though
5 actors were actually spawned). This engine does not change that runtime behavior — the fix is out of
scope for this change — but never reports a per-run actor total that relies on it: Preview(Input)
exposes both EntryCount (what ToConfig() will actually use) and
ActorSum (the sum of every entry's authored Count — what a designer
most likely means by "how many actors does this wave spawn") side by side, so the gap is visible at
authoring time instead of silently surprising someone reading a HUD later.
Wiring correction versus Assets/Serenity/Scripts/Unity/Stage/README.md. That README
documents a StageRoot.WaveSet field ("Wave data sourced from StageRoot.WaveSet, fed to wave
service"). Reading the actual StageRoot (Unity/Stage/Infrastructure/Authoring/StageRoot.cs)
on this branch shows no such field — it exposes only stageId. The README is stale. The real
wiring (confirmed in Stage.md §10 step 4 and Wave.md §6) happens exclusively at the
composition root, which must call UnityWaveService.ConfigureFromWaveSet(waveSetSO) and
SetSpawnPointResolver(stageService.SpawnPointResolver) explicitly. Create(Input)'s result
always carries a warning to this effect — creating these assets never wires anything by itself.
A wizard window collecting input and rendering results ships in a separate change; every asset mutation lives here.
Inherited Members
Namespace: Serenity.Wave.Editor.Builder
Assembly: Serenity.UnityWave.Editor.dll
Syntax
public static class WaveCreator
Fields
CompositionRootWiringWarningMessage
The exact prose Create(Input) always adds to Result.Warnings alongside
setting NeedsCompositionRootWiring — a single shared literal so a caller matching
on the message (e.g. to avoid rendering it twice) compares against this constant instead of sniffing a
substring. Public: read by CreateWaveWindow (same assembly) and asserted on directly by
WaveCreatorTests (a separate test assembly).
Declaration
public const string CompositionRootWiringWarningMessage = "These assets do nothing by themselves — the composition root must call UnityWaveService.ConfigureFromWaveSet(waveSet) and SetSpawnPointResolver(stageService.SpawnPointResolver) explicitly (see Stage.md §10 and Wave.md §6)."
Field Value
| Type | Description |
|---|---|
| string |
Methods
Create(Input)
Validates the request, then resolves-or-creates every wave config bottom-up (in
Waves order) and finally the Wave Set referencing them in that same order. On any
failure every mutation across every touched asset is rolled back: created assets/folders are deleted
(with Serenity.Global.Infrastructure.Editor.Validation.References.SerenitySafeDeleteScope suppressed — the Wave Set holds live, not-yet-saved
references to the wave configs this same call may have just created, which would otherwise trip
SerenitySafeDeleteAssetProcessor's referencer scan and silently abort the delete), their
Addressables entries removed, and any already-existing asset that was being edited has its pre-call
field values restored.
Declaration
public static WaveCreator.Result Create(WaveCreator.Input input)
Parameters
| Type | Name | Description |
|---|---|---|
| WaveCreator.Input | input |
Returns
| Type | Description |
|---|---|
| WaveCreator.Result |
Preview(Input)
Computes what Create(Input) would do without mutating the project.
Declaration
public static WaveCreator.PreviewResult Preview(WaveCreator.Input input)
Parameters
| Type | Name | Description |
|---|---|---|
| WaveCreator.Input | input |
Returns
| Type | Description |
|---|---|
| WaveCreator.PreviewResult |
Validate(Input)
Declaration
public static SerenityCreationValidationResult Validate(WaveCreator.Input input)
Parameters
| Type | Name | Description |
|---|---|---|
| WaveCreator.Input | input |
Returns
| Type | Description |
|---|---|
| SerenityCreationValidationResult |