Skip to content

Commit c80203a

Browse files
committed
feat!: complete FixedMathSharp v7 Unity interop migration
1 parent 514ddf1 commit c80203a

66 files changed

Lines changed: 2707 additions & 2329 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/AGENTS.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ engine-agnostic FixedMathSharp core library. It ships two installable package
77
variants:
88

99
- `com.mrdav30.fixedmathsharp` - standard package with `MemoryPack` support.
10-
- `com.mrdav30.fixedmathsharp.lean` - no-MemoryPack package, preferred for
11-
Burst AOT-oriented Unity projects.
10+
- `com.mrdav30.fixedmathsharp.lean` - package without the MemoryPack
11+
serializer/runtime, preferred for Burst AOT-oriented Unity projects. It
12+
includes the attribute-only `Chronicler.MemoryPackShim` assembly.
1213

1314
The actual Git repository root is `Assets/Packages`, not the outer Unity
1415
project root. The outer project exists so Unity can compile, sync, export, and
@@ -29,12 +30,13 @@ context.
2930
## Current Package Facts
3031

3132
- Package manifests require Unity `2022.3` or newer.
32-
- This Unity host project currently uses Unity `6000.3.9f1` according to
33+
- This Unity host project currently uses Unity `6000.5.0f1` according to
3334
`../../ProjectSettings/ProjectVersion.txt`.
3435
- Both packages include the precompiled FixedMathSharp plugin assets under
3536
`Plugins/`.
36-
- The standard package carries the MemoryPack-related dependencies; the Lean
37-
package intentionally omits MemoryPack.
37+
- The standard package carries the MemoryPack serializer/runtime dependencies.
38+
The Lean package carries only `Chronicler.MemoryPackShim` for attribute
39+
compatibility and intentionally omits MemoryPack runtime serialization.
3840

3941
## Source Of Truth
4042

@@ -110,7 +112,7 @@ or exported assets change:
110112
| `Build/Base` | Shared managed Unity code copied into both package variants. |
111113
| `Build/Editor` | Unity editor tooling for syncing and exporting packages. |
112114
| `com.mrdav30.fixedmathsharp` | Standard UPM package with MemoryPack support. |
113-
| `com.mrdav30.fixedmathsharp.lean` | Lean UPM package without MemoryPack. |
115+
| `com.mrdav30.fixedmathsharp.lean` | Lean UPM package without the MemoryPack serializer/runtime; includes the attribute-only Chronicler shim. |
114116
| `Build/Base/Runtime/Extensions` | Shared Unity adapter helpers for transforms, matrices, bounds, vectors, and quaternions. |
115117
| `Build/Base/Runtime/Attributes` | Shared Unity-facing attributes such as fixed-number angle and vector rotation attributes. |
116118
| `Build/Base/Editor/Drawers` | Shared Unity inspector drawers for FixedMathSharp types and Unity-facing attributes. |
@@ -156,10 +158,11 @@ library's deterministic design.
156158
path is written back.
157159
- Keep editor-only code under `Editor/` and runtime package code under
158160
`Runtime/`. Editor asmdefs must include only the `Editor` platform.
159-
- Do not make the Lean package depend on MemoryPack or MemoryPack-specific
160-
runtime APIs.
161+
- Do not make the Lean package depend on the MemoryPack serializer/runtime or
162+
MemoryPack-specific runtime APIs. Its attribute-only Chronicler shim is the
163+
intentional exception.
161164
- Keep both package variants behaviorally aligned except for the intentional
162-
MemoryPack dependency difference.
165+
serializer/runtime integration difference.
163166

164167
## Sync And Verification Commands
165168

@@ -224,7 +227,8 @@ When bumping the FixedMathSharp core library:
224227
appropriate.
225228
- Keep standard-package dependency DLLs aligned with the MemoryPack-enabled
226229
build.
227-
- Keep the Lean package free of MemoryPack dependencies.
230+
- Keep the Lean package free of the MemoryPack serializer/runtime and keep its
231+
`Chronicler.MemoryPackShim` plugin aligned with the Lean core build.
228232
- Update both `package.json` files, package READMEs, and the root README when
229233
the public version, install guidance, dependencies, or variant behavior
230234
changes.
@@ -234,7 +238,7 @@ When bumping the FixedMathSharp core library:
234238

235239
- Keep the root README focused on package selection and Git URL installation.
236240
- Keep package READMEs package-specific: standard explains MemoryPack support,
237-
Lean explains the no-MemoryPack/Burst AOT rationale.
241+
Lean explains the no-MemoryPack-runtime/Burst AOT rationale and attribute shim.
238242
- Do not duplicate long core FixedMathSharp API documentation here. Link to or
239243
align with the core repo instead.
240244
- If a Unity package behavior depends on a core FixedMathSharp convention,

.assets/ci/unity-sample-import-smoke/Assets/Tests/EditMode/FixedMathSharpSampleImportSmokeTests.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
using System.IO;
33
using NUnit.Framework;
44
using UnityEditor;
5+
using UnityEditor.SceneManagement;
6+
using UnityEngine.SceneManagement;
57

68
public sealed class FixedMathSharpSampleImportSmokeTests
79
{
810
private const string ConfigAssetPath = "FixedMathSharpSampleImportSmokeConfig.json";
911
private const string ImportedPathKey = "FixedMathSharp.SampleImportSmoke.ImportedPath";
1012

1113
[Test]
12-
public void DemoSceneSampleWasImported()
14+
public void DemoSceneSampleWasImportedAndOpens()
1315
{
1416
var config = LoadConfig();
1517
Assert.That(config.expectedSampleAsmdef, Is.Not.Empty, $"Config must define expectedSampleAsmdef: {ConfigAssetPath}");
@@ -19,6 +21,38 @@ public void DemoSceneSampleWasImported()
1921

2022
var importedAsmdefPath = Path.Combine(importedPath, config.expectedSampleAsmdef);
2123
Assert.That(File.Exists(importedAsmdefPath), Is.True, $"Imported sample asmdef was not found: {importedAsmdefPath}");
24+
25+
var importedScenes = Directory.GetFiles(importedPath, "*.unity", SearchOption.AllDirectories);
26+
Assert.That(importedScenes, Has.Length.EqualTo(1), $"Expected one imported sample scene under: {importedPath}");
27+
28+
var importedScenePath = importedScenes[0];
29+
AssertSerializedFieldLine(importedScenePath, "worldRotationMatrix");
30+
AssertSerializedFieldLine(importedScenePath, "localFixedAsUnityMatrix");
31+
AssertSerializedFieldLine(importedScenePath, "worldFixedAsUnityMatrix");
32+
33+
var assetsPath = Path.GetFullPath(UnityEngine.Application.dataPath);
34+
var fullScenePath = Path.GetFullPath(importedScenePath);
35+
Assert.That(
36+
fullScenePath.StartsWith(assetsPath + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase),
37+
Is.True,
38+
$"Imported scene is outside the Unity project: {importedScenePath}");
39+
var sceneAssetPath = "Assets/" + fullScenePath[(assetsPath.Length + 1)..].Replace('\\', '/');
40+
41+
Scene scene = EditorSceneManager.OpenScene(sceneAssetPath, OpenSceneMode.Single);
42+
Assert.That(scene.IsValid(), Is.True, $"Imported sample scene did not open: {sceneAssetPath}");
43+
Assert.That(scene.rootCount, Is.GreaterThan(0), $"Imported sample scene has no roots: {sceneAssetPath}");
44+
}
45+
46+
private static void AssertSerializedFieldLine(string scenePath, string fieldName)
47+
{
48+
var prefix = $" {fieldName}:";
49+
foreach (var line in File.ReadLines(scenePath))
50+
{
51+
if (line.StartsWith(prefix, StringComparison.Ordinal))
52+
return;
53+
}
54+
55+
Assert.Fail($"Imported sample scene is missing serialized field '{fieldName}': {scenePath}");
2256
}
2357

2458
private static SmokeConfig LoadConfig()

.docs/Fixed64_Serialization.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
## Summary
44

5-
`Fixed64` has a Unity-compatible serialized shape. Unity can persist non-zero `Fixed64`, `Vector2d`, and `Vector3d` authoring values through ScriptableObject assets and prefabs, including nested structs and list elements.
5+
`Fixed64` has a Unity-compatible serialized shape. Unity can persist non-zero `Fixed64`, `Vector2d`, `Vector3d`, and `Vector4d` authoring values through ScriptableObject assets and prefabs, including nested structs and list elements.
66

77
Unity's field serialization rules state: Unity serializes fields, but it does not persist `readonly` fields. Hence, `Fixed64` cannot persist its payload as `public readonly long m_rawValue` since Unity had no durable payload to write. Inspector edits could affect the live object, then reload as zero from asset or prefab YAML.
88

99
The fix was to keep FixedMathSharp engine-agnostic by using a normal public `long` field instead of Unity attributes or Unity-specific wrapper types.
1010

11-
Unity 6000.3 serialization rules: <https://docs.unity3d.com/6000.3/Documentation/Manual/script-serialization-rules.html>
11+
Unity 6 serialization rules: <https://docs.unity3d.com/6000.0/Documentation/Manual/script-serialization-rules.html>
1212

1313
## Intentional Public Field
1414

@@ -23,6 +23,7 @@ The EditMode persistence tests cover:
2323
- `[SerializeField] Fixed64`
2424
- `[SerializeField] Vector2d`
2525
- `[SerializeField] Vector3d`
26+
- `[SerializeField] Vector4d`
2627
- a nested serializable struct containing `Fixed64`
2728
- a `List<T>` element containing `Fixed64` and `Vector3d`
2829
- ScriptableObject save/reload through `AssetDatabase`
@@ -37,7 +38,7 @@ This command produced TestRunner XML reliably without `-quit`:
3738

3839
```powershell
3940
$resultPath = 'F:\gamedevrepos\FixedMathSharp-Unity\TestResults\fixed-serialization-editmode.xml'
40-
$unity = 'C:\Program Files\Unity\Hub\Editor\6000.3.9f1\Editor\Unity.exe'
41+
$unity = 'C:\Program Files\Unity\Hub\Editor\6000.5.0f1\Editor\Unity.exe'
4142
$args = @(
4243
'-batchmode',
4344
'-projectPath', 'F:\gamedevrepos\FixedMathSharp-Unity',

.github/workflows/build-and-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
uses: actions/cache@v5
6363
with:
6464
path: .ci/unity-project/Library
65-
key: unity-library-${{ runner.os }}-${{ matrix.artifact_suffix }}-${{ hashFiles('.assets/ci/scripts/prepare-unity-editmode-test-project.sh', '.assets/ci/unity-editmode-tests/**', 'Tests/EditMode/**/*.cs', 'Tests/Runtime/**/*.cs', 'com.mrdav30.fixedmathsharp/**/*.cs', 'com.mrdav30.fixedmathsharp/**/*.asmdef', 'com.mrdav30.fixedmathsharp/package.json', 'com.mrdav30.fixedmathsharp.lean/**/*.cs', 'com.mrdav30.fixedmathsharp.lean/**/*.asmdef', 'com.mrdav30.fixedmathsharp.lean/package.json') }}
65+
key: unity-library-${{ runner.os }}-${{ matrix.artifact_suffix }}-${{ hashFiles('.assets/ci/scripts/prepare-unity-editmode-test-project.sh', '.assets/ci/unity-editmode-tests/**', 'Tests/EditMode/**/*.cs', 'Tests/Runtime/**/*.cs', 'com.mrdav30.fixedmathsharp/**/*.cs', 'com.mrdav30.fixedmathsharp/**/*.asmdef', 'com.mrdav30.fixedmathsharp/Plugins/**', 'com.mrdav30.fixedmathsharp/package.json', 'com.mrdav30.fixedmathsharp.lean/**/*.cs', 'com.mrdav30.fixedmathsharp.lean/**/*.asmdef', 'com.mrdav30.fixedmathsharp.lean/Plugins/**', 'com.mrdav30.fixedmathsharp.lean/package.json') }}
6666
restore-keys: |
6767
unity-library-${{ runner.os }}-${{ matrix.artifact_suffix }}-
6868
@@ -134,7 +134,7 @@ jobs:
134134
uses: actions/cache@v5
135135
with:
136136
path: .ci/unity-sample-import-${{ matrix.artifact_suffix }}/Library
137-
key: unity-sample-import-library-${{ runner.os }}-${{ matrix.artifact_suffix }}-${{ hashFiles('.assets/ci/scripts/prepare-unity-sample-import-smoke.sh', '.assets/ci/unity-sample-import-smoke/**', 'com.mrdav30.fixedmathsharp/package.json', 'com.mrdav30.fixedmathsharp/Samples~/**', 'com.mrdav30.fixedmathsharp.lean/package.json', 'com.mrdav30.fixedmathsharp.lean/Samples~/**') }}
137+
key: unity-sample-import-library-${{ runner.os }}-${{ matrix.artifact_suffix }}-${{ hashFiles('.assets/ci/scripts/prepare-unity-sample-import-smoke.sh', '.assets/ci/unity-sample-import-smoke/**', 'com.mrdav30.fixedmathsharp/Plugins/**', 'com.mrdav30.fixedmathsharp/package.json', 'com.mrdav30.fixedmathsharp/Samples~/**', 'com.mrdav30.fixedmathsharp.lean/Plugins/**', 'com.mrdav30.fixedmathsharp.lean/package.json', 'com.mrdav30.fixedmathsharp.lean/Samples~/**') }}
138138
restore-keys: |
139139
unity-sample-import-library-${{ runner.os }}-${{ matrix.artifact_suffix }}-
140140

Build/Base/Editor/Drawers/VectorDrawer.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ namespace FixedMathSharp.Editor
1818
/// <see cref="PropertyDrawer" />
1919
[CustomPropertyDrawer(typeof(Vector2d))]
2020
[CustomPropertyDrawer(typeof(Vector3d))]
21+
[CustomPropertyDrawer(typeof(Vector4d))]
2122
public class VectorDrawer : PropertyDrawer
2223
{
2324
private static readonly GUIContent XLabel = new("X");
2425
private static readonly GUIContent YLabel = new("Y");
2526
private static readonly GUIContent ZLabel = new("Z");
27+
private static readonly GUIContent WLabel = new("W");
2628

2729
/// <summary>
2830
/// Called when the GUI is drawn.
@@ -66,8 +68,13 @@ private int GetFieldCount(SerializedProperty property)
6668
Type type = fieldInfo?.FieldType;
6769
if (type == typeof(Vector2d))
6870
return 2;
71+
if (type == typeof(Vector4d))
72+
return 4;
6973

70-
return property.type == nameof(Vector2d) ? 2 : 3;
74+
if (property.type == nameof(Vector2d))
75+
return 2;
76+
77+
return property.type == nameof(Vector4d) ? 4 : 3;
7178
}
7279

7380
private static void DrawFixedVector(Rect contentPosition, SerializedProperty property, int fieldCount, float fieldWidth, bool hideLabels)
@@ -95,6 +102,20 @@ private static void DrawFixedVector(Rect contentPosition, SerializedProperty pro
95102
if (EditorGUI.EndChangeCheck())
96103
property.SetFixedPropertyValue(new Vector3d(x, y, z));
97104
}
105+
else if (fieldCount == 4 && propertyValue is Vector4d vector4d)
106+
{
107+
EditorGUI.BeginChangeCheck();
108+
Fixed64 x = DrawFixedComponent(contentPosition, XLabel, vector4d.X, hideLabels);
109+
contentPosition.x += fieldWidth;
110+
Fixed64 y = DrawFixedComponent(contentPosition, YLabel, vector4d.Y, hideLabels);
111+
contentPosition.x += fieldWidth;
112+
Fixed64 z = DrawFixedComponent(contentPosition, ZLabel, vector4d.Z, hideLabels);
113+
contentPosition.x += fieldWidth;
114+
Fixed64 w = DrawFixedComponent(contentPosition, WLabel, vector4d.W, hideLabels);
115+
116+
if (EditorGUI.EndChangeCheck())
117+
property.SetFixedPropertyValue(new Vector4d(x, y, z, w));
118+
}
98119
}
99120

100121
private static Fixed64 DrawFixedComponent(Rect position, GUIContent label, Fixed64 value, bool hideLabels)

0 commit comments

Comments
 (0)