Produces a stable type hash for a Type based on its layout in memory and how that memory should be interpreted.
This hash is NOT expected to remain the same across versions.
You can rename field members and this hash isn't affected. However, if a field's type changes,
this hash changes, because the interpretation of the underlying memory will have contextually changed.
The purpose of the stable type hash is to provide a version linking serialized component data to its runtime
representation.
As such, the type hash has a few requirements:
- R0: TypeHashes apply only to types that Unity.Entities serializes. The internals of a UnityEngine.Object reference
contained in a component mustn't have an effect on the type hash. You can safely change the internals of the
UnityEngine.Object reference because they're serialized outside of Unity.Entities.
- R1: Types with the same data layout but are different types should have different hashes.
- R2: If a type's data layout changes, so should the type hash. This includes:
- A nested field's data layout changes (for example, a new member added)
- FieldOffsets, explicit size, or pack alignment are changed
- Different types of the same width swap places (for example if a uint swaps with an int)
- Note: Unity can't detect if fields of the same type swap (for example, mInt1 swaps with mInt2) This is a semantic
difference which you should increase your component [TypeVersion(1)] attribute. You shouldn't
try to hash field names to handle this, because you can't control all field names.
Also, field names have no effect serialization and doesn't affect hashes.
- R3: You should version the hash in case the semantics of a type change, but the data layout is unchanged
- R4: DOTS Runtime relies on hashes generated from the Editor (used in serialized data) and hashes generated
during compilation. These hashes must match. This rule exists because of the following:
- Tiny swapa out assemblies for 'tiny' versions, which means you should avoid any hashing using the AssemblyName
or handle it specially for the known swapped assemblies.
- This means you should avoid Type.AssemblyQualifiedName in hashes, but as well, closed-form
generic types include the assembly qualified name for GenericArguments in Type.FullName which
causes issues. For example, typeof(ComponentWithGeneric.GenericField).FullName ==
Unity.Entities.ComponentWithGeneric.GenericField1System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
- System.Reflection and Mono.Cecil provide different Type names (they use a different format).
Generating hashes from System.Reflection to match hashes using Mono.Cecil must account for this difference.
| Method | Description |
|---|---|
| CalculateMemoryOrdering | Calculates a MemoryOrdering for the input type. |
| CalculateStableTypeHash | Calculates a stable type hash for the input type. |
| CombineFNV1A64 | Combines a FNV1A64 hash with a value. |
| FNV1A64 | Generates a FNV1A64 hash. |