修复 Unity 编译依赖和测试程序集配置

This commit is contained in:
JSD\13999
2026-05-18 14:18:19 +08:00
parent fac8e9a7f3
commit e35981d246
13 changed files with 247 additions and 30 deletions

View File

@@ -197,7 +197,7 @@ namespace FlowScope.Data
return; return;
} }
if (IsReactiveCollection(memberType)) if (IsReactiveCollection(memberType) || IsMutableCollection(memberType, currentValue))
{ {
PopulateCollection(currentValue, memberType, value, fieldName); PopulateCollection(currentValue, memberType, value, fieldName);
return; return;
@@ -216,7 +216,7 @@ namespace FlowScope.Data
throw TypeMismatch(fieldName, collectionType, value); throw TypeMismatch(fieldName, collectionType, value);
} }
var itemType = collectionType.GetGenericArguments()[0]; var itemType = GetCollectionItemType(collectionType);
collectionType.GetMethod("Clear", Type.EmptyTypes)?.Invoke(collection, Array.Empty<object>()); collectionType.GetMethod("Clear", Type.EmptyTypes)?.Invoke(collection, Array.Empty<object>());
var addMethod = collectionType.GetMethod("Add", new[] { itemType }); var addMethod = collectionType.GetMethod("Add", new[] { itemType });
if (addMethod == null) if (addMethod == null)
@@ -330,6 +330,38 @@ namespace FlowScope.Data
return type.IsGenericType && type.GetGenericTypeDefinition().FullName == "R3.ReactiveCollection`1"; return type.IsGenericType && type.GetGenericTypeDefinition().FullName == "R3.ReactiveCollection`1";
} }
private static bool IsMutableCollection(Type type, object value)
{
return value != null &&
type != typeof(string) &&
GetCollectionItemType(type) != null &&
type.GetMethod("Clear", Type.EmptyTypes) != null;
}
private static Type GetCollectionItemType(Type type)
{
if (type.IsArray)
{
return type.GetElementType();
}
if (type.IsGenericType && type.GetGenericArguments().Length == 1)
{
return type.GetGenericArguments()[0];
}
foreach (var interfaceType in type.GetInterfaces())
{
if (interfaceType.IsGenericType &&
interfaceType.GetGenericTypeDefinition() == typeof(ICollection<>))
{
return interfaceType.GetGenericArguments()[0];
}
}
return null;
}
private static bool IsSimple(Type type) private static bool IsSimple(Type type)
{ {
type = Nullable.GetUnderlyingType(type) ?? type; type = Nullable.GetUnderlyingType(type) ?? type;

View File

@@ -1,7 +1,9 @@
{ {
"name": "FlowScope.Runtime", "name": "FlowScope.Runtime",
"rootNamespace": "FlowScope", "rootNamespace": "FlowScope",
"references": [], "references": [
"R3"
],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,

View File

@@ -1,5 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 9841d62cd2d24cb48e23ac11adaaf5a9 guid: 5e5172994f0edc6468e55a5e1e742064
folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
userData: userData:

View File

@@ -1,14 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &100000
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component: []
m_Layer: 0
m_Name: MainMenuPanel
m_TagString: Untagged
m_IsActive: 1

View File

@@ -9,6 +9,7 @@ using FlowScope.Resources;
using FlowScope.Save; using FlowScope.Save;
using FlowScope.UI; using FlowScope.UI;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using ContainerType = FlowScope.Container.Container; using ContainerType = FlowScope.Container.Container;
namespace FlowScope.Samples.MainMenuP0 namespace FlowScope.Samples.MainMenuP0
@@ -39,10 +40,9 @@ namespace FlowScope.Samples.MainMenuP0
_gameFlow = new GameFlow(); _gameFlow = new GameFlow();
var resources = new SampleResourceService(); var resources = new SampleResourceService();
if (mainMenuPanelPrefab != null) resources.Register(
{ "FlowScope/Samples/MainMenuP0/MainMenuPanel",
resources.Register("FlowScope/Samples/MainMenuP0/MainMenuPanel", mainMenuPanelPrefab.gameObject); ResolveMainMenuPanelPrefab().gameObject);
}
_saveService = new SaveService( _saveService = new SaveService(
new FileSaveStorage(), new FileSaveStorage(),
@@ -108,6 +108,35 @@ namespace FlowScope.Samples.MainMenuP0
return hudCanvas; return hudCanvas;
} }
private MainMenuPanel ResolveMainMenuPanelPrefab()
{
if (mainMenuPanelPrefab != null)
{
return mainMenuPanelPrefab;
}
var panelObject = new GameObject("MainMenuPanel Template");
panelObject.transform.SetParent(transform, false);
panelObject.SetActive(false);
var panel = panelObject.AddComponent<MainMenuPanel>();
var goldObject = new GameObject("GoldText");
goldObject.transform.SetParent(panelObject.transform, false);
var goldText = goldObject.AddComponent<Text>();
goldText.text = defaultGold.ToString();
goldText.alignment = TextAnchor.MiddleCenter;
var buttonObject = new GameObject("IncrementGoldButton");
buttonObject.transform.SetParent(panelObject.transform, false);
buttonObject.AddComponent<Image>();
var button = buttonObject.AddComponent<Button>();
panel.Configure(goldText, button);
mainMenuPanelPrefab = panel;
return mainMenuPanelPrefab;
}
private sealed class SampleResourceService : IResourceService private sealed class SampleResourceService : IResourceService
{ {
private readonly Dictionary<string, GameObject> _prefabs = new(); private readonly Dictionary<string, GameObject> _prefabs = new();

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using FlowScope.Save; using FlowScope.Save;
using NUnit.Framework; using NUnit.Framework;
using R3; using R3;
@@ -35,7 +36,7 @@ namespace FlowScope.Tests.EditMode.Data
} }
[Test] [Test]
public void Serialize_ReactiveCollection_WritesJsonArray() public void Serialize_Collection_WritesJsonArray()
{ {
var serializer = new JsonSaveSerializer(); var serializer = new JsonSaveSerializer();
var data = new InventoryData(); var data = new InventoryData();
@@ -49,7 +50,7 @@ namespace FlowScope.Tests.EditMode.Data
} }
[Test] [Test]
public void Deserialize_ReactiveCollection_ReplacesCollectionContents() public void Deserialize_Collection_ReplacesCollectionContents()
{ {
var serializer = new JsonSaveSerializer(); var serializer = new JsonSaveSerializer();
var data = new InventoryData(); var data = new InventoryData();
@@ -79,7 +80,7 @@ namespace FlowScope.Tests.EditMode.Data
private sealed class InventoryData private sealed class InventoryData
{ {
public ReactiveCollection<int> ItemIds { get; } = new(); public List<int> ItemIds { get; } = new();
} }
} }
} }

View File

@@ -0,0 +1,22 @@
{
"name": "FlowScope.Tests.EditMode",
"rootNamespace": "FlowScope.Tests",
"references": [
"FlowScope.Runtime",
"R3"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"optionalUnityReferences": [
"TestAssemblies"
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4292f95f100145edb6c1ebc8e206eb59
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
{
"name": "FlowScope.Tests.PlayMode",
"rootNamespace": "FlowScope.Tests",
"references": [
"FlowScope.Runtime",
"R3"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"optionalUnityReferences": [
"TestAssemblies"
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e6cb2de461674c0ea86229d044f2f8a6
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,15 @@
{ {
"scopedRegistries": [
{
"name": "Unity NuGet",
"url": "https://unitynuget-registry.openupm.com",
"scopes": [
"org.nuget"
]
}
],
"dependencies": { "dependencies": {
"com.cysharp.r3": "https://github.com/Cysharp/R3.git?path=src/R3.Unity/Assets/R3.Unity#1.3.0",
"com.unity.collab-proxy": "2.12.4", "com.unity.collab-proxy": "2.12.4",
"com.unity.feature.development": "1.0.1", "com.unity.feature.development": "1.0.1",
"com.unity.textmeshpro": "3.0.7", "com.unity.textmeshpro": "3.0.7",
@@ -36,6 +46,7 @@
"com.unity.modules.video": "1.0.0", "com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0", "com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0", "com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0" "com.unity.modules.xr": "1.0.0",
"org.nuget.r3": "1.3.0"
} }
} }

View File

@@ -1,5 +1,14 @@
{ {
"dependencies": { "dependencies": {
"com.cysharp.r3": {
"version": "https://github.com/Cysharp/R3.git?path=src/R3.Unity/Assets/R3.Unity#1.3.0",
"depth": 0,
"source": "git",
"dependencies": {
"com.unity.modules.imgui": "1.0.0"
},
"hash": "329ca7915713417f2e0837b0e0a80b4da074db4a"
},
"com.unity.collab-proxy": { "com.unity.collab-proxy": {
"version": "2.12.4", "version": "2.12.4",
"depth": 0, "depth": 0,
@@ -135,6 +144,88 @@
}, },
"url": "https://packages.unity.cn" "url": "https://packages.unity.cn"
}, },
"org.nuget.microsoft.bcl.asyncinterfaces": {
"version": "6.0.0",
"depth": 2,
"source": "registry",
"dependencies": {
"org.nuget.system.threading.tasks.extensions": "4.5.4"
},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.microsoft.bcl.timeprovider": {
"version": "8.0.0",
"depth": 1,
"source": "registry",
"dependencies": {
"org.nuget.microsoft.bcl.asyncinterfaces": "6.0.0"
},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.r3": {
"version": "1.3.0",
"depth": 0,
"source": "registry",
"dependencies": {
"org.nuget.microsoft.bcl.timeprovider": "8.0.0",
"org.nuget.system.buffers": "4.5.1",
"org.nuget.system.componentmodel.annotations": "5.0.0",
"org.nuget.system.memory": "4.5.5",
"org.nuget.system.runtime.compilerservices.unsafe": "6.0.0",
"org.nuget.system.threading.channels": "8.0.0"
},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.buffers": {
"version": "4.5.1",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.componentmodel.annotations": {
"version": "5.0.0",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.memory": {
"version": "4.5.5",
"depth": 1,
"source": "registry",
"dependencies": {
"org.nuget.system.buffers": "4.5.1",
"org.nuget.system.numerics.vectors": "4.4.0",
"org.nuget.system.runtime.compilerservices.unsafe": "4.5.3"
},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.runtime.compilerservices.unsafe": {
"version": "6.0.0",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.threading.channels": {
"version": "8.0.0",
"depth": 1,
"source": "registry",
"dependencies": {
"org.nuget.system.threading.tasks.extensions": "4.5.4"
},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.threading.tasks.extensions": {
"version": "4.5.4",
"depth": 2,
"source": "registry",
"dependencies": {
"org.nuget.system.runtime.compilerservices.unsafe": "4.5.3"
},
"url": "https://unitynuget-registry.openupm.com"
},
"com.unity.modules.ai": { "com.unity.modules.ai": {
"version": "1.0.0", "version": "1.0.0",
"depth": 0, "depth": 0,

View File

@@ -26,11 +26,19 @@ MonoBehaviour:
m_IsDefault: 1 m_IsDefault: 1
m_Capabilities: 7 m_Capabilities: 7
m_ConfigSource: 0 m_ConfigSource: 0
m_UserSelectedRegistryName: - m_Id: scoped:project:Unity NuGet
m_Name: Unity NuGet
m_Url: https://unitynuget-registry.openupm.com
m_Scopes:
- org.nuget
m_IsDefault: 0
m_Capabilities: 0
m_ConfigSource: 4
m_UserSelectedRegistryName: Unity NuGet
m_UserAddingNewScopedRegistry: 0 m_UserAddingNewScopedRegistry: 0
m_RegistryInfoDraft: m_RegistryInfoDraft:
m_Modified: 0 m_Modified: 0
m_ErrorMessage: m_ErrorMessage:
m_UserModificationsInstanceId: -836 m_UserModificationsInstanceId: -834
m_OriginalInstanceId: -838 m_OriginalInstanceId: -836
m_LoadAssets: 0 m_LoadAssets: 0