What shipped in each Scylla Core release, from the initial framework foundation that landed at 1.0.0 down through every fix that follows.
Release notes for Scylla Core, the foundational module that every other Scylla module depends on. Versions are listed newest at the top; each entry groups its bullets under Added, Removed, Changed, and Fixed. Core follows its own semver line, independent of the other modules in the framework.
1.2.0
This release adds a true binary serialization format, atomic file writes, the save contracts the Persistence module builds on, and a set of color analysis tools. In the Editor, configuration assets are no longer changed by Play mode. A few defaults changed along the way, and the Upgrading page lists what to check.
Added
- Binary serialization.
SerializationFormat.Binaryand theSerializationSettings.CompactBinarypreset now write a compact, tagged binary stream through the newScyllaBinaryWriterandScyllaBinaryReader. The stream is little-endian on every platform and stores NaN and Infinity as they are. SerializationSettings.EmitReferenceIDsandBuilder.WithEmitReferenceIDs(bool), which control whether preserved references carry an explicit$idmarker. The$idand$refproperty names are now public constants onSerializationSettings.ReferenceTracker.TryTrackWithIDandTypeMetadata.TryBuildMigrationPath, which finds the shortest chain of[ScyllaMigration]methods between two schema versions.- Atomic writes.
ScyllaFileUtil.WriteTextAtomic,WriteBytesAtomicandWriteBytesAtomicAsyncwrite to a temporary file in the same folder and swap it in, so a crash leaves either the old file or the new one, never half of each.FileSettingsgainsTempFileExtensionandKeepReplaceBackup, which these methods use, andUseAtomicWrite, which makes the regularWriteText,WriteBytesandWriteLinesmethods and their async versions write atomically too. With it set, those writes throw on WebGL, like the atomic methods. - Save contracts in
Scylla.Core.Persistence:IScyllaPersistableand the typedIScyllaPersistable<TState>for systems that save state,ScyllaPersistenceRegistryfor registering them, andScyllaPartitionID. The Persistence module uses these, and any module can implement them without depending on it. - Runtime configuration copies.
ScyllaConfiguration.CreateRuntimeCopy<T>()andReleaseRuntimeCopy(), plusIsRuntimeCopyandRuntimeSource, give Play mode in the Editor a copy of a configuration asset to work on.ScyllaModule.PrepareConfiguration<T>()copies a module’s configuration, applies JSON overrides, logs where it came from and registers it in one call. IScyllaModuleManager.CheckDependencies(), withScyllaModuleDependencyIssueandScyllaModuleDependencyIssueType. It checks the module dependency graph at any time without logging or changing module state.ScyllaModuleID.PERSISTENCE.- Color analysis tools:
ColorAnalysis: relative luminance, WCAG contrast ratios and checks againstWCAGLevel(AA, AAA), Oklab color difference, and correlated color temperature.ColorBlindnessSimulator: simulates the eightColorBlindnessTypevalues on one color or a span.ColorHarmony: generates complementary, triadic, analogous and seven otherColorHarmonyTypeschemes, in Oklch, HSV or OkHSL.ColorRamps: tints, shades, tones, ramps and material tones, each with an allocation-free span overload.ColorUtil:IsInSRGBGamut,MaxOklabChromaAtHueandClampToSRGBGamutfor Oklch colors.
WaitForSettledFrames, a coroutine wait that holds until the frame rate steadies, so delta-time work does not start during a loading hitch.ScyllaSafeSchedulerfor UI Toolkit, withRecurringSafe,DebouncedSafeandOnceSafe. A scheduled item pauses when its element leaves the panel, and a callback that throws is stopped and logged once instead of failing every tick. The editorScyllaSchedulerforwards to it and gainsOnceSafetoo.TweenVisualElementExtensions, which tweens UI Toolkit elements: opacity, fades, translation, scale, rotation, background and text color, width and height.ScyllaEditorSceneUtilin the Editor, withFindBootstrap()andFindOrCreateBootstrap(). Module setup wizards use it to create the Scylla Bootstrap themselves when the scene has none.ScyllaModuleTierandScyllaModuleInfo.Tier, set through a newScyllaModuleInfoconstructor that takes the tier. The existing constructor is unchanged.[ScyllaMenuItem]in the Editor, which adds a method to the Scylla menus by group and path instead of a menu priority, and[ScyllaCreateAsset], which adds a ScriptableObject type toAssets/Create/Scyllainstead of[CreateAssetMenu]. The Scylla menu registry places every item and draws every divider, so a module adding an item no longer moves the items of other modules.- A newly created Scylla Bootstrap gets the Core, Logger, Time, Event and Scene configuration assets from
Resources/Configassigned to its empty slots. This applies to adding the component in the Inspector, Tools > Scylla > Create > Scylla Core, the Setup Wizard and the module wizards. Before, those slots stayed empty until each Assign button was clicked. ScyllaUISafeArea.Compute(), which turns the screen safe area and a margin into anchors and offsets, with an override rectangle for simulating device cutouts.IUITextFieldgainsRestoreOriginalTextOnEscape,SelectAllTextOnFocusandSetPlaceholder().TimeUtil.UniqueUTCNow(), a UTC clock whose results always increase within a process, for timestamps that things are ordered by.DateTime.UtcNowonly advances about every 15.6 ms on Windows, so two saves made in quick succession could get the same time. It is safe to call from any thread.StringUtil.StripANSISequences(), and theChar.BELLandChar.ESCAPEconstants.- Editor:
ScyllaChoiceCardGroup, a selectable list of title-and-description cards;ScyllaEditorAssetUtil.LoadCachedStyleSheet()for modules that ship their own style sheets;ScyllaEditorBase.BuildDescriptionLabel(); new page, card and problem-box helpers onScyllaWizardWindowBase; and menu constants for the Persistence, TextMode and UI modules onScyllaEditorConstants.
Changed
- The
Tools/Scylla,GameObject/ScyllaandAssets/Create/Scyllamenus are built by the Scylla menu registry. Module submenus are sorted alphabetically, the Create and GameObject entries are grouped by module tier, theAssets/Create/Scyllaentries are sorted alphabetically, and menu paths and keyboard shortcuts are unchanged. - The menu priority constants in
ScyllaEditorConstantsare obsolete, exceptPRIORITY_GETTING_STARTEDandPRIORITY_CONTEXT_GAMEOBJECT. SerializationFormat.Binarynow produces binary data. In 1.1.0 it wrote UTF-8 JSON, so bytes saved with the Binary format under 1.1.0 no longer load with Binary settings. The defaultToBytesandFromBytesoverloads still use JSON and are unchanged.- With
ReferenceHandling.Preserve, the first occurrence of a shared object now carries an explicit$id, so$refback-references resolve whatever order the properties are read in. Documents without$idstill load. SetEmitReferenceIDsto false to write the old shape. - A schema version gap that no
[ScyllaMigration]method bridges now fails deserialization instead of being skipped. Direct migrations that span several versions, such as[ScyllaMigration(1, 3)], are now applied. - In the Editor, configuration assets are no longer changed by Play mode. The Bootstrap and every module work on runtime copies, so values set at runtime, console
config.*commands and JSON overrides last for the session only. Builds are unaffected. This also applies in projects that installed Scylla Core as a package. FontUtilnow defaults to the standard-width ScyllaMono font instead of the condensed ScyllaMono-Cond. Passcondensed: truetoLoadDefaultMono,LoadDefaultMonoSDFand theirTryLoadvariants to keep the old look.- On macOS,
FilePathUtil.DocumentsPathnow returns~/Documentsinstead of the home folder. Logs, config files and saves stored under it move to~/Documents/{Game}/. Existing files are not moved. - Script changes made during Play mode are now applied when Play mode ends. A reload in the middle of a session cleared the framework’s state without starting it again, which left the game running with nothing behind it. This follows the editor preference Script Changes While Playing and applies only while it is set to Recompile And Continue Playing, the default.
- Module dependency validation now reports every hard dependency cycle in one pass instead of stopping at the first.
- The
ScyllaShapeTweenExtensionshelpers now set the shape as the tween target, like the other tween extensions.ScyllaTween.KillTweensOf(shape)now stops a shape’s tweens, and a managed tween is dropped when its shape is destroyed instead of writing to the destroyed shape. - Opening a wizard that is already open now returns it to the first step. The Finish button grows to fit longer labels.
- The Persistence module now has editor menu priority 204. Stats moved to 205 and YM2612 to 208, which makes room for TextMode (206) and UI (207).
- Types that declare a
[ScyllaSerializable(TypeAlias = ...)]now write the alias as their$typemarker instead of the assembly-qualified name. Types without an explicit alias still write the assembly-qualified name, and theFullNamedefault is never written. A document with an alias in a polymorphic position cannot be read by 1.1.0. - A value whose runtime type differs from its declared type now always carries a
$typemarker, also whenIncludeTypeInfois off. The flag then only leaves out the marker of objects whose runtime type equals the declared type. Output for monomorphic, non-aliased data is unchanged. - A
$typemarker that resolves to a type not assignable to the declared type now fails the load. A marker that cannot be resolved still falls back to the declared type when that type is concrete, and fails with an error naming the marker when it is abstract or an interface. TypeMetadataCache.ResolveAliasdiscovers aliases it has not seen yet by scanning the loaded assemblies once, and registering an alias that another type already holds logs a warning.TypeMetadatagainsHasExplicitAliasandTypeMarkerName.- Per-settings serializers registered through
SerializationSettings.Builder.RegisterSerializer<T>now apply to the elements, keys and values of arrays, lists, hash sets, queues, stacks and dictionaries. A collection that was written with the default shape of its element type and is read with a custom serializer that cannot parse that shape no longer loads. Persistence registers no custom serializers, so its saves are unaffected. - A palette entry’s identifier is now called its ID.
ColorPaletteEntry.ID,ColorPaletteEntryData.ID,ColorPalette.GetColorIDandContainsID, andMutableColorPalette.SetIDandContainsIDreplace the members named after a name. The oldName,GetColorName,ContainsNameandRenamemembers still work but are marked obsolete. Palette assets saved with the old field name still load and are rewritten withIDthe next time they are saved. Lookups by ID, such aspalette["Background"], behave as before.
Fixed
- Core failed to compile in projects without the optional SharpZipLib package.
- In projects that installed Scylla Core as a package,
AssemblyUtil.OnBeforeReloadandOnAfterReloaddid not exist and were never raised, soIsReloadingandReloadCountnever changed. The events are now declared in every build and raised by the Core editor assembly. Scylla Core’s tests now compile in such projects as well. TimeDebugOverlaywas missing from projects that installed Scylla Core as a package and from development builds. It now works in the Editor and in development builds and switches itself off in release builds, so a scene that contains it no longer shows a missing script there.- Setup Wizard, module wizards and Tools > Scylla > Create > Scylla Core failed to create a Scylla Bootstrap in projects that installed Scylla Core as a package.
- Setting
ScyllaTime.TimeScalewhile paused was lost onResume(). The new value is now kept. - An auto-assigned reference ID could collide with an ID read from a document.
- A boxed struct behind an
objector interface field was treated as a shared reference during serialization. - The BSP map generator turned a partition into a single room when only one of its sides was too short to split. Maps generated from the same seed can differ from 1.1.0 where that happened.
- A
[MonoTextArea]field could lose its edited text on entering Play mode or after a domain reload. - The
ScyllaFileUtil.SaveObject,LoadObject,SaveSecureObjectandLoadSecureObjectoverloads without serialization settings, their async versions, and theSaveToFileandSaveSecureToFileextensions always failed with “Settings cannot be null.” Passingnullserialization settings now usesSerializationSettings.Default, as documented. ScyllaSerialization.ToJSONandToBytesignoredSerializationSettings.Indent, so pretty-printed JSON always used a tab. The configured indent is now used.SerializationSettings.IncludePrivateFieldswas never read. It now includes every non-public field and every non-public property with a getter and a setter, including those of base classes;[ScyllaIgnore]still excludes a member.- 3D shapes did not rebuild when their parameters were edited in the Inspector during Play mode. They now rebuild in Play mode as they do in Edit mode.
- A 3D shape with a custom material rendered in its tint color, white by default, instead of the material’s own color. A white tint now leaves a custom material’s color alone, as documented. On the Built-in Standard shader, which has
_Colorinstead of_BaseColor, tints now take effect. - The
MeshandMatchingPrimitivecollider modes of 3D shapes removed every collider on the GameObject, including colliders added by hand, andMatchingPrimitivereplaced its collider on every rebuild. A shape now manages only the collider it attached and resizes it in place. In scenes saved with an earlier version, a shape adopts its existing collider rather than adding a second one. Custom shapes should obtain their primitive collider with the new protectedGetOrAddManagedCollider<T>()inTryAttachPrimitiveCollider. - 3D shape properties now clamp fixed ranges when set, so
ScyllaSphereShape.Segments = 1000reads back as 256, and assigning a property its current value no longer rebuilds the mesh. Limits that depend on another property, such as a door against its wall, are still applied when the mesh is built. ScyllaShapes.CreateMeshassigned a destroyed material passed to it instead of falling back to the default material.- Collection serializers ignored per-settings custom serializers for their elements, keys and values, and ignored a global serializer registered after the collection type had first been serialized. They now resolve the element serializer on every call.
- A
nullelement in a collection of a nullable element type, such asList<int?>, threw during serialization. It now round-trips asnull. - A derived class stored in a base-typed field, or any value in an abstract, interface or
objectfield, lost its derived fields on serialization and could not be read back. The runtime type is now written with a$typemarker, so the value round-trips as its own type. Values behindobjectand interface fields that are not objects with properties, such as boxed numbers, enums and collections, use a{"$type", "$value"}envelope. TypeAliashad no effect on the written output and aliases could not be resolved on a cold start. Aliases are now written as the type marker and discovered on demand when a document is loaded.
1.1.0
Scene management joins the Core subsystems: framework persistence across scene loads plus a managed loading pipeline.
Added
- Scene management subsystem (
ScyllaSceneManager), initialized by the Bootstrap alongside Time and the event bus. Keeps the bootstrap hierarchy alive across scene changes viaDontDestroyOnLoadand deduplicates per-scene bootstraps automatically, so every scene stays playable directly from the Editor. - Managed asynchronous scene loading:
LoadSceneAsync(by name or build index),ReloadActiveSceneAsync, andUnloadSceneAsyncreturn aSceneLoadOperationwith progress, state, aCompletedevent, and anAwaitable. A synchronousLoadScenefallback is included. - Activation gate and minimum load duration for loading screens:
WithManualActivation()holds the load at 90% until code opens the gate;WithMinDuration(seconds)(or the config default) keeps fast loads from flashing. - Transition hygiene before destructive scene changes: active tweens are killed, the timescale-modifier stack is cleared, and destroyed event-bus subscribers are pruned. Each step is a configuration toggle with a per-call
HygieneOverride. - Transition tasks:
RegisterPreLoadTask/RegisterPostLoadTaskaccept awaitable hooks that the pipeline waits for (autosaves, fades, warm-ups). - Six typed scene events on the event bus: will-load, loaded, will-unload, unloaded, active-scene-changed, and throttled load progress.
- Addressables scene routing (when the Addressables package is installed):
LoadAddressableSceneAsyncby address key orAssetReference, through the same pipeline; unloads route back through Addressables automatically. ScyllaSceneConfigurationasset with a custom inspector, a Scene Configuration slot on the Bootstrap inspector, and Setup Wizard integration.PruneInvalidSubscribers()on the event bus, removing subscriptions whose Unity objects have been destroyed.- SceneManager demo: a hub scene exercising single, additive, gated, and addressable loads with a live status overlay and scene event log.
Changed
- The bootstrap hierarchy now persists across scene loads by default (
PersistFrameworkAcrossScenes, on by default). A scene that carries its own bootstrap no longer logs an error in a running session; the duplicate is removed in favor of the persistent instance.
1.0.0
This is the initial release of Scylla Core, the module every other Scylla module builds on.
Added
- Bootstrap and module manager: a scene-level
ScyllaBootstrapcomponent plus theScyllaCoresingleton andScyllaModuleManagerthat together discover, validate, and drive every module through the framework lifecycle (Discovered, Validated, Initialized, Started, Enabled, Disabled, Shutdown) with fail-fast validation of the dependency graph. - Scylla Event eXchange (SEX) bus, a typed publish-subscribe channel with priority ordering, cancellable propagation, and lifecycle-safe subscription management that cleans up automatically when subscribers are destroyed.
- Dual-layer configuration system: ScriptableObject assets for design-time defaults paired with JSON files for runtime overrides, resolved through a four-tier layered fallback (User Documents, Application, Unity Asset, Defaults) by
ConfigFileManager, and exportable straight from the Inspector via an “Export Config File” button. - Logging subsystem, with module categories, pluggable receivers (Unity console and file system), and uniform formatting across the framework.
- Time subsystem (
ScyllaTime), initialized by the Bootstrap before any module runs, owning framework-aware time, timescale control, and pause behaviour independent ofTime.timeScale. - Utility library, covering math and interpolation, noise (Perlin, OpenSimplex2, Value, ValueCubic, Cellular) with domain warping and curl flows, random (PCG32, Xoshiro256, Mersenne Twister, SplitMix64, Xoroshiro128+) with helpers for dice and IDs, strings and tabular text, files and paths, sprites and fonts, colors, lights, and cameras, threading, platform, assemblies, and type helpers.
- Data structures library, with generic and DOTS-compatible queue, priority queue, deque, stack, map, type-map, ring buffer, object pool, trie, quadtree, octree, BVH, KD-tree, bit array, disjoint set, graphs (adjacency list, CSR, grid adapter, algorithms), and grid utilities for hex, square, and triangle layouts.
- First-party types: the
ColorAssetRegistrywithColorPalette,ColorGradient, andColorSwatchCollection; theConfigFilefamily (ConfigFile,ConfigFileGroup,ConfigFileProperty) that backs the JSON configuration tier; and eight strongly-typed unit structs (LengthUnit,MassUnit,TimeUnit,AreaUnit,SpeedUnit,PressureUnit,TemperatureUnit,DataUnit) with conversion properties and validated math. - Serialization, compression, crypto, and checksum stack: a first-party JSON serialization engine with attribute-driven configuration, reference tracking, and type serializers; compression providers for GZip, Deflate, BZip2, and Zip; authenticated encryption via AES-CBC-HMAC, AES-GCM, and ChaCha20-Poly1305 with PBKDF2 key derivation; and non-cryptographic checksums (Adler32, CRC16, CRC32, Fletcher32, XXHash32, XXHash64).
- Tween system, a pooled and easing-aware engine for floats, vectors, colors, and quaternions with sequence composition and one-line extensions for
Transform,Material,AudioSource,CanvasGroup,SpriteRenderer, andRectTransform. - Procedural map generation toolkit: BSP, cellular automata, drunkard walk, maze, maze-with-rooms, room-and-corridor, Voronoi regions, noise threshold, and winding corridor, plus pluggable post-processing for connectivity repair, dead-end removal, room detection, door placement, and spawn points.
- Debug-draw subsystem, runtime visualization for primitives and meshes that works in both edit and play mode, across the Built-in and SRP render pipelines.
- Editor foundation, a UI Toolkit base for the rest of the framework’s editor experience with
ScyllaEditorBasefor custom inspectors,ScyllaToolWindowBasefor windows,ScyllaSchedulerfor safe recurring jobs, a USS token system for theming, and the bundled setup and getting-started wizards.