Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
unity: [2022.3.12f1, 2022.3.62f3, 6000.0.58f2, 6000.0.63f1, 6000.1.17f1, 6000.2.6f2, 6000.2.15f1, 6000.3.0f1, 6000.3.12f1, 6000.4.0f1, 6000.4.1f1]
unity: [2022.3.12f1, 2022.3.62f3, 6000.0.58f2, 6000.0.63f1, 6000.1.17f1, 6000.2.6f2, 6000.2.15f1, 6000.3.0f1, 6000.3.12f1, 6000.4.0f1, 6000.4.12f1, 6000.5.0f1, 6000.5.5f1]
steps:
- uses: actions/checkout@v4
with:
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## Version 1.2.2

### Unity 6000.4 and 6000.5 support

- Added version-aware compatibility extensions for the APIs Unity changed in 6000.4: `Object.GetInstanceID()` (obsolete in 6000.4, removed in 6000.5), `Scene.handle`, and `SceneHierarchyWindow.SetExpanded` (now takes an `EntityId`). Context identity and hierarchy expansion now work across all supported Unity versions.
- Widened context identity keys from `int` to `long` so the new entity and scene handle values are stored without truncation.
- Extended the CI test matrix and tested-versions docs to cover Unity 6000.4 and 6000.5.

### Fixes

- Fixed a `NullReferenceException` in the custom inspector when a component had a field Unity cannot serialize (e.g. a multidimensional array). Such fields are now omitted from the inspector, matching Unity's default behavior.

## Version 1.2.1

### Fixes
Expand Down
4 changes: 3 additions & 1 deletion Docs/docs/reference/tested-unity-versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ The test matrix is defined using minimum and maximum tested editor versions per
| 6000.3.0f1 | LTS | Minimum tested Unity 6.3 |
| 6000.3.12f1 | LTS | Maximum tested Unity 6.3 |
| 6000.4.0f1 | Supported | Minimum tested Unity 6.4 |
| 6000.4.1f1 | Supported | Maximum tested Unity 6.4 |
| 6000.4.12f1 | Supported | Maximum tested Unity 6.4 |
| 6000.5.0f1 | Supported | Minimum tested Unity 6.5 |
| 6000.5.5f1 | Supported | Maximum tested Unity 6.5 |

In-between versions will likely work, but only the above are verified in automated tests.
Unity 2023 releases are skipped since they are tech stream builds (not long-term supported), and Unity does not recommend them for production.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using System.Text;
using Plugins.Saneject.Editor.Extensions;
using Plugins.Saneject.Runtime.Settings;
using UnityEditor;
using UnityEditor.SceneManagement;
Expand All @@ -24,9 +25,9 @@ public ContextIdentity(Object obj)
}

public ContextType Type { get; }
public int Id { get; }
public long Id { get; }
public ContextType ContainerType { get; }
public int ContainerId { get; }
public long ContainerId { get; }
public bool IsPrefab { get; }

public override string ToString()
Expand Down Expand Up @@ -76,42 +77,42 @@ private static ContextData GetContextData(Object obj)
? new ContextData
(
type: ContextType.PrefabInstance,
key: prefabInstanceRoot.GetInstanceID(),
key: prefabInstanceRoot.GetInstanceIDCompat(),
containerType: ContextType.PrefabAsset,
containerKey: prefabAssetRoot.GetInstanceID()
containerKey: prefabAssetRoot.GetInstanceIDCompat()
) // Prefab instance inside prefab asset
: new ContextData
(
type: ContextType.PrefabInstance,
key: prefabInstanceRoot.GetInstanceID(),
key: prefabInstanceRoot.GetInstanceIDCompat(),
containerType: ContextType.SceneObject,
containerKey: gameObject.scene.handle
containerKey: gameObject.scene.GetHandleCompat()
); // Prefab instance inside scene

if (isPrefabAssetObject)
return new ContextData
(
type: ContextType.PrefabAsset,
key: prefabAssetRoot.GetInstanceID(),
key: prefabAssetRoot.GetInstanceIDCompat(),
containerType: ContextType.PrefabAsset,
containerKey: prefabAssetRoot.GetInstanceID()
containerKey: prefabAssetRoot.GetInstanceIDCompat()
); // Prefab asset

return new ContextData(
type: ContextType.SceneObject,
key: gameObject.scene.handle,
key: gameObject.scene.GetHandleCompat(),
containerType: ContextType.SceneObject,
containerKey: gameObject.scene.handle
containerKey: gameObject.scene.GetHandleCompat()
); // Scene object
}

private class ContextData
{
public ContextData(
ContextType type,
int key,
long key,
ContextType containerType,
int containerKey)
long containerKey)
{
Type = type;
Key = key;
Expand All @@ -120,9 +121,9 @@ public ContextData(
}

public ContextType Type { get; }
public int Key { get; }
public long Key { get; }
public ContextType ContainerType { get; }
public int ContainerKey { get; }
public long ContainerKey { get; }
}

#region Equality logic
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;

namespace Plugins.Saneject.Editor.Extensions
{
Expand All @@ -15,5 +16,26 @@ public static T[] AsArray<T>(this T obj)
{
return new[] { obj };
}

public static long GetInstanceIDCompat(this Object obj)
{
#if UNITY_6000_4_OR_NEWER
return (long)EntityId.ToULong(obj.GetEntityId());
#else
return (int)obj.GetInstanceID();
#endif
}

// Returns the object id boxed as the exact type expected by reflection calls
// against APIs whose signature changed from int to EntityId in Unity 6000.4
// (e.g. SceneHierarchyWindow.SetExpanded). Do not use for identity keys.
public static object GetInstanceIDBoxedCompat(this Object obj)
{
#if UNITY_6000_4_OR_NEWER
return obj.GetEntityId();
#else
return obj.GetInstanceID();
#endif
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using UnityEngine.SceneManagement;

namespace Plugins.Saneject.Editor.Extensions
{
public static class SceneExtensions
{
public static long GetHandleCompat(this Scene scene)
{
#if UNITY_6000_4_OR_NEWER
return (long)scene.handle.GetRawData();
#else
return (int)scene.handle;
#endif
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public PropertyModel(
ExpectedType = elementType;
HasInjectAttribute = field.HasInjectAttribute();
IsReadOnly = HasInjectAttribute || field.HasReadOnlyAttribute();
IsCollection = SerializedProperty.isArray && SerializedProperty.propertyType != SerializedPropertyType.String;
IsCollection = SerializedProperty is { isArray: true } && SerializedProperty.propertyType != SerializedPropertyType.String;

Children = field.FieldType.IsNestedSerializable() && SerializedProperty != null
? field.FieldType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Reflection;
using Plugins.Saneject.Editor.Data.Context;
using Plugins.Saneject.Editor.Extensions;
using Plugins.Saneject.Runtime.Settings;
using UnityEditor;
using UnityEngine;
Expand Down Expand Up @@ -94,7 +95,7 @@ public static void Expand(Object[] objects)
{
setExpanded!.Invoke(window, new object[]
{
current.gameObject.GetInstanceID(),
current.gameObject.GetInstanceIDBoxedCompat(),
true
});

Expand All @@ -104,7 +105,7 @@ public static void Expand(Object[] objects)
// Finally expand the object itself
setExpanded!.Invoke(window, new object[]
{
gameObject.GetInstanceID(),
gameObject.GetInstanceIDBoxedCompat(),
true
});
}
Expand Down
2 changes: 1 addition & 1 deletion UnityProject/Saneject/Assets/Plugins/Saneject/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "com.alexanderlarsen.saneject",
"author": "Alexander Larsen",
"displayName": "Saneject",
"version": "1.2.1",
"version": "1.2.2",
"description": "Inject dependencies in the Unity Editor, not Play Mode, by writing them directly into serialized fields at edit-time using familiar DI APIs, so everything stays visible in the Inspector, including interfaces.\n\nNo runtime container. No startup cost. No hidden wiring. No weird lifecycles. Just simple, deterministic edit-time DI that works with Unity, not around it.",
"documentationUrl": "https://github.com/alexanderlarsen/Saneject/blob/main/README.md",
"changelogUrl": "https://github.com/alexanderlarsen/Saneject/blob/main/CHANGELOG.md",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using NUnit.Framework;
using Plugins.Saneject.Editor.Data.Context;
using Plugins.Saneject.Editor.Extensions;
using Tests.Saneject.Fixtures.Scripts;
using UnityEditor;
using UnityEngine;
Expand All @@ -20,9 +20,9 @@ public void SceneObject_InScene_SetsExpectedContextIdentity()
// Assert
Assert.That(sceneObject, Is.Not.Null);
Assert.That(identity.Type, Is.EqualTo(ContextType.SceneObject));
Assert.That(identity.Id, Is.EqualTo(Convert.ToInt32(sceneObject.gameObject.scene.handle)));
Assert.That(identity.Id, Is.EqualTo(sceneObject.gameObject.scene.GetHandleCompat()));
Assert.That(identity.ContainerType, Is.EqualTo(ContextType.SceneObject));
Assert.That(identity.ContainerId, Is.EqualTo(Convert.ToInt32(sceneObject.gameObject.scene.handle)));
Assert.That(identity.ContainerId, Is.EqualTo(sceneObject.gameObject.scene.GetHandleCompat()));
Assert.That(identity.IsPrefab, Is.False);
}

Expand All @@ -43,9 +43,9 @@ public void PrefabInstance_InScene_SetsExpectedContextIdentity()
// Assert
Assert.That(prefabObject, Is.Not.Null);
Assert.That(identity.Type, Is.EqualTo(ContextType.PrefabInstance));
Assert.That(identity.Id, Is.EqualTo(prefabInstance.Root.GetInstanceID()));
Assert.That(identity.Id, Is.EqualTo(prefabInstance.Root.GetInstanceIDCompat()));
Assert.That(identity.ContainerType, Is.EqualTo(ContextType.SceneObject));
Assert.That(identity.ContainerId, Is.EqualTo(Convert.ToInt32(prefabObject.gameObject.scene.handle)));
Assert.That(identity.ContainerId, Is.EqualTo(prefabObject.gameObject.scene.GetHandleCompat()));
Assert.That(identity.IsPrefab, Is.True);
}
finally
Expand All @@ -72,9 +72,9 @@ public void PrefabAssetObject_InPrefabAsset_SetsExpectedContextIdentity()
// Assert
Assert.That(prefabObject, Is.Not.Null);
Assert.That(identity.Type, Is.EqualTo(ContextType.PrefabAsset));
Assert.That(identity.Id, Is.EqualTo(prefabStage.Root.GetInstanceID()));
Assert.That(identity.Id, Is.EqualTo(prefabStage.Root.GetInstanceIDCompat()));
Assert.That(identity.ContainerType, Is.EqualTo(ContextType.PrefabAsset));
Assert.That(identity.ContainerId, Is.EqualTo(prefabStage.Root.GetInstanceID()));
Assert.That(identity.ContainerId, Is.EqualTo(prefabStage.Root.GetInstanceIDCompat()));
Assert.That(identity.IsPrefab, Is.True);
}
finally
Expand Down Expand Up @@ -103,9 +103,9 @@ public void PrefabAssetObject_LoadedFromAssetDatabase_SetsExpectedContextIdentit
Assert.That(prefabAsset, Is.Not.Null);
Assert.That(prefabObject, Is.Not.Null);
Assert.That(identity.Type, Is.EqualTo(ContextType.PrefabAsset));
Assert.That(identity.Id, Is.EqualTo(prefabAsset.GetInstanceID()));
Assert.That(identity.Id, Is.EqualTo(prefabAsset.GetInstanceIDCompat()));
Assert.That(identity.ContainerType, Is.EqualTo(ContextType.PrefabAsset));
Assert.That(identity.ContainerId, Is.EqualTo(prefabAsset.GetInstanceID()));
Assert.That(identity.ContainerId, Is.EqualTo(prefabAsset.GetInstanceIDCompat()));
Assert.That(identity.IsPrefab, Is.True);
}
finally
Expand Down Expand Up @@ -133,9 +133,9 @@ public void PrefabInstance_InPrefabAsset_SetsExpectedContextIdentity()
// Assert
Assert.That(prefabObject, Is.Not.Null);
Assert.That(identity.Type, Is.EqualTo(ContextType.PrefabInstance));
Assert.That(identity.Id, Is.EqualTo(nestedInstance.Root.GetInstanceID()));
Assert.That(identity.Id, Is.EqualTo(nestedInstance.Root.GetInstanceIDCompat()));
Assert.That(identity.ContainerType, Is.EqualTo(ContextType.PrefabAsset));
Assert.That(identity.ContainerId, Is.EqualTo(hostStage.Root.GetInstanceID()));
Assert.That(identity.ContainerId, Is.EqualTo(hostStage.Root.GetInstanceIDCompat()));
Assert.That(identity.IsPrefab, Is.True);
}
finally
Expand Down
Loading