|
1 | 1 | # Unity SerializeReferenceExtensions |
2 | 2 |
|
3 | | -[](https://github.com/mackysoft/Unity-SerializeReferenceExtensions/actions/workflows/build.yaml) [](https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releases) [](https://openupm.com/packages/com.mackysoft.serializereference-extensions/) |
| 3 | +[](https://github.com/mackysoft/Unity-SerializeReferenceExtensions/actions/workflows/tests.yaml) [](https://github.com/mackysoft/Unity-SerializeReferenceExtensions/actions/workflows/build.yaml) [](https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releases) [](https://openupm.com/packages/com.mackysoft.serializereference-extensions/) |
4 | 4 |
|
5 | | -**Inspired by [this post](https://qiita.com/tsukimi_neko/items/7922b2433ed4d8616cce).** |
| 5 | +This library provides an Inspector dropdown (`SubclassSelector`) for fields serialized by Unity's `[SerializeReference]`. |
6 | 6 |
|
7 | | -The `SerializeReference` attribute, added in Unity 2019.3, makes it possible to serialize references to interfaces and abstract classes. |
8 | | - |
9 | | -The `SubclassSelector` attribute allows you to easily set subclasses of those abstract classes in the Editor that are serialized by `SerializeReference` attribute. |
10 | 7 |
|
11 | 8 |  |
12 | 9 |
|
13 | | -#### Features |
| 10 | +#### Key Features |
| 11 | + |
| 12 | +- Select a concrete type for `[SerializeReference]` fields via dropdown. |
| 13 | +- Search candidates with a fuzzy finder. |
| 14 | +- Collection support (`T[]`, `List<T>`, etc.). |
| 15 | +- Nested type support. |
| 16 | +- Customize type display name/path with `[AddTypeMenu]`. |
| 17 | +- Supports `CustomPropertyDrawer` for selected subtypes. |
| 18 | +- When switching types, restore previous values by matching property names (JSON-based). |
| 19 | +- Context menu utilities: |
| 20 | + - Copy & paste managed-reference values |
| 21 | + - Clear / reset managed-reference values |
| 22 | + |
| 23 | +**Generic support improvements on Unity 2023.2+** |
| 24 | +- Supports variance matching (`in`/`out`) for generic interfaces (covariance / contravariance) |
14 | 25 |
|
15 | | -- Easily set subclass by popup. |
16 | | -- **[New]** Type finding by fuzzy finder. |
17 | | -- **[New]** Override the type name and path by the `AddTypeMenu` attribute. |
18 | | -- **[New]** Available `CustomPropertyDrawer` for subclasses. |
19 | | -- **[New]** Restore values of previous object from JSON when subclass is changed. (required Unity 2021.3 or later) |
20 | | -- **[New]** Copy & Paste the subclass properties. (required Unity 2021.3 or later) |
21 | | -- **[New]** Clear & reset the subclass properties. (required Unity 2021.3 or later) |
22 | | -- **[New]** Covariance / Contravariance support. (required Unity 2023.2 or later) |
| 26 | +## Requirements |
| 27 | + |
| 28 | +- **Unity 2021.3 LTS or later** (officially supported). |
| 29 | +- **Unity 2023.2 or later** is recommended when you use **generic field types** (see “Generic support” below). |
23 | 30 |
|
24 | 31 | > See below for the reason for the limitation of versions less than Unity 2021.3. |
25 | | -> |
26 | 32 | > https://blog.unity.com/engine-platform/serializereference-improvements-in-unity-2021-lts |
27 | 33 |
|
28 | 34 | ## 📥 Installation |
29 | 35 |
|
30 | 36 | #### Install via `.unitypackage` |
31 | 37 |
|
32 | 38 | Download any version from releases. |
33 | | - |
34 | | -Releases: https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releases |
| 39 | +https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releases |
35 | 40 |
|
36 | 41 | #### Install via git URL |
37 | 42 |
|
38 | | -Or, you can add this package by opening PackageManager and entering |
| 43 | +Open Package Manager → “Add package from git URL…”, then input: |
39 | 44 |
|
40 | 45 | ``` |
41 | 46 | https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions |
42 | 47 | ``` |
43 | 48 |
|
44 | | -from the `Add package from git URL` option. |
45 | | - |
46 | | -If you are specifying a version, enter `#{VERSION}` at the end, as shown below. |
| 49 | +To pin a version, append `#{VERSION}`: |
47 | 50 |
|
48 | 51 | ``` |
49 | | -https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions#1.1.9 |
| 52 | +https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions#1.7.0 |
50 | 53 | ``` |
51 | 54 |
|
52 | 55 | #### Install via Open UPM |
@@ -136,19 +139,73 @@ public struct StructCommand : ICommand { |
136 | 139 | } |
137 | 140 | ``` |
138 | 141 |
|
139 | | -#### Supported Types |
| 142 | +## Generic support (Unity 2023.2+) |
| 143 | + |
| 144 | +Unity 2023.2+ supports generic type instances for `SerializeReference` fields more reliably. |
| 145 | +SerializeReferenceExtensions also enhances type discovery for generic base types. |
| 146 | + |
| 147 | +Examples: |
| 148 | + |
| 149 | +- Generic interface as base type: |
| 150 | + - `[SerializeReference, SubclassSelector] ICommand<int> cmd;` |
| 151 | + - Show candidates that implement `ICommand<int>` (including variance rules if applicable) |
| 152 | +- Abstract generic base type: |
| 153 | + - `[SerializeReference, SubclassSelector] BaseCommand<int> cmd;` |
| 154 | + - Show candidates derived from `BaseCommand<int>` |
| 155 | + |
| 156 | +> Note: |
| 157 | +> Candidate types shown in the menu still follow “Type > eligibility rules” below. |
| 158 | +
|
| 159 | +## Type discovery & eligibility rules |
140 | 160 |
|
141 | | -The `SubclassSelector` attribute supports types that meet the following conditions. |
| 161 | +The dropdown list is built by: |
142 | 162 |
|
143 | | -- Public or nested private |
144 | | -- Not abstract |
145 | | -- Not generic |
146 | | -- Not unity object |
147 | | -- Serializable attribute is applied. |
| 163 | +1. enumerating candidate types, then |
| 164 | +2. filtering by eligibility (intrinsic) and compatibility with the field base type |
| 165 | + |
| 166 | +### 1. Candidate type eligibility (intrinsic rules) |
| 167 | +|Rule|Eligible|Notes| |
| 168 | +|-|:-:|-| |
| 169 | +|Top-level `public` type|✅| Internal / non-public top-level types are not listed| |
| 170 | +|Nested `private` type|✅| Supported (useful for encapsulated implementations)| |
| 171 | +| Nested `public` type|✅| Listed like other candidates| |
| 172 | +| `abstract`|❌| Cannot be instantiated| |
| 173 | +| `generic` type (open or constructed) |❌| See “Generic support” (base type generics are supported, but generic candidate types are excluded) | |
| 174 | +| derives from `UnityEngine.Object`|❌| Unity `SerializeReference` limitation| |
| 175 | +| `[Serializable]` is applied|✅| Unity `SerializeReference` requires serializable types| |
| 176 | +| `[HideInTypeMenu]` is applied|❌| Explicitly hidden from menu| |
| 177 | + |
| 178 | +### 2. Compatibility rules (base type vs candidate type) |
| 179 | + |
| 180 | +| Field base type| Support | How compatibility is checked| |
| 181 | +| - | :-: | - | |
| 182 | +| non-generic interface / abstract class |✅| `baseType.IsAssignableFrom(candidateType)`| |
| 183 | +| generic base type (Unity 2023.2+)|✅| candidate must implement/derive from the same generic definition and match type arguments (supports variance for `in` / `out`) | |
| 184 | +| generic base type (Unity < 2023.2)|⚠️| Unity engine limitations may prevent correct serialization of generic instances| |
148 | 185 |
|
149 | 186 |
|
150 | 187 | ## ❓ FAQ |
151 | 188 |
|
| 189 | +### Why is my type not shown in the dropdown? |
| 190 | + |
| 191 | +Check the eligibility rules: |
| 192 | + |
| 193 | +- Is it `[Serializable]`? |
| 194 | +- Is it `abstract`? |
| 195 | +- Is it a generic candidate type? |
| 196 | +- Does it derive from `UnityEngine.Object`? |
| 197 | +- Is `[HideInTypeMenu] `applied? |
| 198 | + |
| 199 | +### Can I select MonoBehaviour / ScriptableObject? |
| 200 | + |
| 201 | +No. Unity does not allow `UnityEngine.Object` types in `SerializeReference`. |
| 202 | + |
| 203 | +### Structs (value types) |
| 204 | + |
| 205 | +Unity documentation states that value types are not supported for SerializeReference, |
| 206 | +but in practice boxed structs may work in some scenarios. |
| 207 | +If you rely on structs, test on your target Unity versions and prefer classes when possible. |
| 208 | + |
152 | 209 | ### If the type is renamed, the reference is lost. |
153 | 210 |
|
154 | 211 | It is a limitation of `SerializeReference` of Unity. |
|
0 commit comments