public readonly record struct SymbolAn interned name: four bytes that compare as fast as an integer, because they are one.
Remarks
A hash of the name rather than an index into a table, and the reason is determinism. An index assigned in first-seen order depends on what a process happened to load first, so two machines running the same build would assign different numbers to the same word — and a selection that breaks a tie on a number would then pick differently on each of them. [16](../../../docs/plan/16-networking.md) makes that a desync rather than a curiosity. A hash is the same everywhere, for ever, with no table to ship and no order to agree on.
⚠ 32 bits collide, and the bake is where that is caught. Two words in one vocabulary hashing alike would silently make them the same word. Whatever composes a vocabulary checks the whole of it for that and refuses — MoveSet.Compose for a movement vocabulary, BlackboardLayoutBuilder.Build for a blackboard's keys — which turns a one-in-fifty-thousand mystery into a build error naming both words. The alternative — 64 bits — doubles the size of every facet, key and world state to avoid a case the build can simply detect.
Names are kept for diagnostics only. ToString resolves through a process-wide table filled as symbols are created, so a debugger and an error message can say gait rather than 0x4f9a2b1c. Nothing in a frame reads it, and a symbol that arrived from a deserialised set with no name still compares correctly.
⚠ It lives here rather than beside its first caller. Move sets needed an interned name first, so this type spent its first release in Vixen.Animation.Moves; a blackboard key, a gameplay-relevant tag and a GOAP world key each want exactly the same four bytes, and two interned-name types in one engine is the duplication this repository avoids everywhere else. docs/plan/37 § The rows this touches is where that was decided.
Fields and properties (3)
public uint IdThe hash. Zero is the empty symbol and matches nothing.
public static Symbol NoneThe symbol that is not a word. Matches nothing, including itself in a facet.
public bool IsSomeWhether this is a real word.
Methods (4)
public Symbol(uint Id)An interned name: four bytes that compare as fast as an integer, because they are one.
public static Symbol Intern(string? name)Interns a name.
public bool TryGetCollision(out string first, out string second)Whether two different words this process has interned share this symbol.
public override string ToString()The name this was interned from, if this process has seen it.
Used by (193, showing 40)
- ConstraintStageBenchmarksVixen.Benchmarks.Animation
- ActiveHandlesVixen.Animation
- AgentActionRegistryVixen.Ai
- AgentActionRegistryTestsVixen.Ai.Tests
- AgentDebugRecordVixen.Ai
- AgentDebugRecorderTestsVixen.Ai.Tests
- AiAgentSnapshotVixen.Ai
- AiBreakpointVixen.Ai
- AiBreakpointTestsVixen.Ai.Tests
- AiBreakpointsVixen.Ai
- AiDebugChannelVixen.Ai
- AiDebugChannelTestsVixen.Ai.Tests
- AiDiagnosisVixen.Ai
- AiDiagnosisExitCriteriaTestsVixen.Ai.Tests
- AiFindingVixen.Ai
- AiSnapshotTestsVixen.Ai.Tests
- AiSnapshotsVixen.Ai
- AiSystemVixen.Ai
- AiSystemTreeTestsVixen.Ai.Tests
- AnimationParametersVixen.Animation
- AttachmentFrameVixen.Animation
- AttachmentSocketVixen.Animation
- AttachmentSocketsVixen.Animation
- AuthorableNodeTestsVixen.Ai.Tests
- AuthoringTestsVixen.Animation.Tests
- BehaviorBuildContextVixen.Ai
- BehaviorNodeVixen.Ai
- BehaviorNodeDefinitionVixen.Ai
- BehaviorTreeVixen.Ai
- BehaviorTreeAssetVixen.Ai
- BehaviorTreeCompilerTestsVixen.Ai.Tests
- BehaviorTreeContentVixen.Ai
- BehaviorTreeContentCompilerVixen.Ai
- BehaviorTreeDecoratorTestsVixen.Ai.Tests
- BehaviorTreeDeterminismTestsVixen.Ai.Tests
- BehaviorTreeDiagnosticVixen.Ai
- BehaviorTreeInstanceVixen.Ai
- BehaviorTreeLibraryVixen.Ai
- BehaviorTreeResolverVixen.Ai
- BehaviorTreeTaskTestsVixen.Ai.Tests