补齐 package Tests 第一刀
This commit is contained in:
@@ -1,8 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Added `Samples~/MainMenuP0` package sample metadata and content.
|
||||||
|
- Added the first `Tests~/EditMode` package smoke test slice.
|
||||||
|
- Updated package installation and layout documentation to reflect the current P2 package state.
|
||||||
|
|
||||||
## 0.2.0-preview.1
|
## 0.2.0-preview.1
|
||||||
|
|
||||||
- Added the first Git-consumable FlowScope Game Core package layout.
|
- Added the first Git-consumable FlowScope Game Core package layout.
|
||||||
- Mirrored Runtime, Addressables, and Editor sources from `Assets/FlowScope`.
|
- Mirrored Runtime, Addressables, and Editor sources from `Assets/FlowScope`.
|
||||||
- Added package metadata and Git installation notes for consuming Unity projects.
|
- Added package metadata and Git installation notes for consuming Unity projects.
|
||||||
|
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ Add the package to the consuming project's `Packages/manifest.json`:
|
|||||||
- `FlowScope.Addressables` references `FlowScope.Runtime`, `Unity.Addressables`, and `Unity.ResourceManager`.
|
- `FlowScope.Addressables` references `FlowScope.Runtime`, `Unity.Addressables`, and `Unity.ResourceManager`.
|
||||||
- `FlowScope.Editor` is Editor-only and only provides read-only diagnostics.
|
- `FlowScope.Editor` is Editor-only and only provides read-only diagnostics.
|
||||||
- `Samples~/MainMenuP0` is a package sample candidate mirrored from the project-internal MainMenuP0 sample.
|
- `Samples~/MainMenuP0` is a package sample candidate mirrored from the project-internal MainMenuP0 sample.
|
||||||
|
- `Tests~/EditMode` contains the first package-level smoke tests.
|
||||||
|
|
||||||
Runtime must not depend on Addressables, Editor, Samples, or Tests.
|
Runtime must not depend on Addressables, Editor, Samples, or Tests.
|
||||||
|
|||||||
8
Packages/com.flowscope.gamecore/Tests~.meta
Normal file
8
Packages/com.flowscope.gamecore/Tests~.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9593988203244d3796c30233d04321de
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Packages/com.flowscope.gamecore/Tests~/EditMode.meta
Normal file
8
Packages/com.flowscope.gamecore/Tests~/EditMode.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7e85b5827334420a6d81b9f37a5c8d1
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "FlowScope.PackageTests.EditMode",
|
||||||
|
"rootNamespace": "FlowScope.PackageTests.EditMode",
|
||||||
|
"references": [
|
||||||
|
"FlowScope.Runtime",
|
||||||
|
"FlowScope.Addressables",
|
||||||
|
"R3.Unity"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": true,
|
||||||
|
"precompiledReferences": [
|
||||||
|
"R3.dll",
|
||||||
|
"nunit.framework.dll"
|
||||||
|
],
|
||||||
|
"autoReferenced": false,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"optionalUnityReferences": [
|
||||||
|
"TestAssemblies"
|
||||||
|
],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e213b3e4bd60472087919ca2efba94bc
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FlowScope.Addressables;
|
||||||
|
using FlowScope.Container;
|
||||||
|
using FlowScope.Resources;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace FlowScope.PackageTests.EditMode
|
||||||
|
{
|
||||||
|
public sealed class PackageSmokeTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void PackageAssemblies_CanBeReferencedFromPackageTests()
|
||||||
|
{
|
||||||
|
var container = new Container();
|
||||||
|
var backend = new AddressablesResourceBackend();
|
||||||
|
IResourceService resources = new ResourceService(new ImmediateBackend());
|
||||||
|
|
||||||
|
container.RegisterInstance(resources);
|
||||||
|
|
||||||
|
Assert.AreEqual("Addressables", backend.Name);
|
||||||
|
Assert.AreSame(resources, container.Resolve<IResourceService>());
|
||||||
|
|
||||||
|
container.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ResourceService_LoadAsync_CanRunInsidePackageTestAssembly()
|
||||||
|
{
|
||||||
|
var backend = new ImmediateBackend();
|
||||||
|
var service = new ResourceService(backend);
|
||||||
|
|
||||||
|
using var handle = service
|
||||||
|
.LoadAsync<TestAsset>("package-smoke", CancellationToken.None)
|
||||||
|
.GetAwaiter()
|
||||||
|
.GetResult();
|
||||||
|
|
||||||
|
Assert.That(handle.Asset, Is.Not.Null);
|
||||||
|
Assert.AreEqual(1, backend.LoadCalls);
|
||||||
|
|
||||||
|
handle.Dispose();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, backend.ReleaseCalls);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ImmediateBackend : IResourceBackend
|
||||||
|
{
|
||||||
|
public string Name => "Immediate";
|
||||||
|
public int LoadCalls { get; private set; }
|
||||||
|
public int ReleaseCalls { get; private set; }
|
||||||
|
|
||||||
|
public Task<T> LoadAsync<T>(string key, CancellationToken cancellationToken)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
LoadCalls++;
|
||||||
|
return Task.FromResult(new TestAsset() as T);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Release<T>(string key, T asset)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
ReleaseCalls++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class TestAsset
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: adbf3a7109f64fea8a6c75febc85d0f7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
22
Packages/com.flowscope.gamecore/Tests~/README.md
Normal file
22
Packages/com.flowscope.gamecore/Tests~/README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# FlowScope Package Tests
|
||||||
|
|
||||||
|
This directory contains the first package-level test slice for FlowScope Game Core.
|
||||||
|
|
||||||
|
The current tests are intentionally small. They prove that a package test assembly can reference:
|
||||||
|
|
||||||
|
- `FlowScope.Runtime`
|
||||||
|
- `FlowScope.Addressables`
|
||||||
|
- Unity Test Framework / NUnit
|
||||||
|
|
||||||
|
The full development test suite still lives under `My project/Assets/FlowScope/Tests` during P2 migration. Real Addressables fixture validation also remains in the development project because Addressables settings are project-level assets.
|
||||||
|
|
||||||
|
## Current Scope
|
||||||
|
|
||||||
|
- `EditMode/PackageSmokeTests.cs`
|
||||||
|
|
||||||
|
## Not Migrated Yet
|
||||||
|
|
||||||
|
- Full Runtime EditMode tests.
|
||||||
|
- Full PlayMode tests.
|
||||||
|
- MainMenuP0 sample tests.
|
||||||
|
- Real Addressables fixture tests.
|
||||||
7
Packages/com.flowscope.gamecore/Tests~/README.md.meta
Normal file
7
Packages/com.flowscope.gamecore/Tests~/README.md.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0b532bf970be439aab8ef4bc3eb5cf2c
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,14 +1,43 @@
|
|||||||
# FlowScope 安装与最小接入
|
# FlowScope 安装与最小接入
|
||||||
|
|
||||||
日期:2026-05-26
|
日期:2026-06-06
|
||||||
|
|
||||||
本文说明 FlowScope 在 P2 第一阶段面向使用者的安装路径、项目内开发模式,以及基于当前真实 API 的最小 Bootstrap 写法。当前仓库尚未完成标准 Unity Package 物理搬迁,package path 与 Git URL 方式是目标接入形态;项目内 `Assets/FlowScope` 开发模式是当前可用形态。
|
本文说明 FlowScope 在 P2 package/editor 阶段的当前安装方式、最小接入写法和已知限制。当前仓库已经存在真实 Unity Package 目录 `Packages/com.flowscope.gamecore`,同时仍保留 `My project/Assets/FlowScope` 作为开发工程内的测试与样例源。
|
||||||
|
|
||||||
## 安装方式
|
## 当前可用安装方式
|
||||||
|
|
||||||
|
### Git URL
|
||||||
|
|
||||||
|
消费方项目推荐通过 SSH Git URL 安装,并固定到 preview tag 或明确 commit:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scopedRegistries": [
|
||||||
|
{
|
||||||
|
"name": "Unity NuGet",
|
||||||
|
"url": "https://unitynuget-registry.openupm.com",
|
||||||
|
"scopes": [
|
||||||
|
"org.nuget"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"com.cysharp.r3": "https://github.com/Cysharp/R3.git?path=src/R3.Unity/Assets/R3.Unity#1.3.0",
|
||||||
|
"com.flowscope.gamecore": "ssh://git@git.zz.com:2222/Developer/FlowScope.git?path=/Packages/com.flowscope.gamecore#v0.2.0-preview.1",
|
||||||
|
"org.nuget.r3": "1.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:
|
||||||
|
- `com.cysharp.r3` 提供 Unity 适配层。
|
||||||
|
- `org.nuget.r3` 提供 `R3.dll` 和相关 BCL DLL。
|
||||||
|
- Unity Package Manager 不可靠支持在 package 的 `package.json` 中声明 Git dependency,因此 R3 必须由消费方 manifest 显式声明。
|
||||||
|
- 当前 `v0.2.0-preview.1` 已在 FishingFrenzy 消费方工程完成最小编译验证;后续文档、Samples、Tests 收口后应打新的 preview tag。
|
||||||
|
|
||||||
### 本地 package path
|
### 本地 package path
|
||||||
|
|
||||||
当后续完成标准包目录后,可在使用方 Unity 项目的 `Packages/manifest.json` 中使用本地路径:
|
本机调试时可在消费方 Unity 项目的 `Packages/manifest.json` 中使用本地路径:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -19,66 +48,60 @@
|
|||||||
```
|
```
|
||||||
|
|
||||||
适用场景:
|
适用场景:
|
||||||
|
- 同时开发 FlowScope 和消费方项目。
|
||||||
- 本机同时开发 FlowScope 与游戏项目。
|
- 需要快速验证 Runtime、Addressables、Editor、Samples 或 Tests package 布局。
|
||||||
- 需要在包仓库中调试 Runtime、Addressables、Editor 或 Samples。
|
- 不希望每次小改都重新打 Git tag。
|
||||||
- 希望由 Unity Package Manager 识别包结构与 `Samples~`。
|
|
||||||
|
|
||||||
注意:P2 第一阶段当前仓库还没有 `Packages/com.flowscope.gamecore` 物理目录,因此此方式需要等第二阶段本地 package 试迁移完成后再用于实装验证。
|
|
||||||
|
|
||||||
### Git URL
|
|
||||||
|
|
||||||
当包目录与发布分支稳定后,可在 `Packages/manifest.json` 中使用 Git URL:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"com.flowscope.gamecore": "<最终发布仓库 Git URL>?path=/Packages/com.flowscope.gamecore#v0.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
适用场景:
|
|
||||||
|
|
||||||
- 使用方只消费稳定版本,不直接修改 FlowScope 源码。
|
|
||||||
- 团队希望通过 tag 或固定 commit 控制接入版本。
|
|
||||||
|
|
||||||
当前仓库 `origin` 仍带有旧项目名,不应直接写入对外安装文档。发布前需要由团队确认最终 FlowScope 包仓库地址;使用 Git URL 时应固定 tag 或 commit,避免使用浮动分支导致使用方项目在不同时间解析到不同代码。
|
|
||||||
|
|
||||||
### 项目内 Assets 开发模式
|
### 项目内 Assets 开发模式
|
||||||
|
|
||||||
当前可用模式是将 FlowScope 放在 Unity 项目内:
|
FlowScope 自身开发工程仍保留:
|
||||||
|
|
||||||
```text
|
|
||||||
Assets/
|
|
||||||
FlowScope/
|
|
||||||
Runtime/
|
|
||||||
Addressables/
|
|
||||||
Samples/
|
|
||||||
Tests/
|
|
||||||
```
|
|
||||||
|
|
||||||
本仓库当前路径为:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
My project/Assets/FlowScope
|
My project/Assets/FlowScope
|
||||||
```
|
```
|
||||||
|
|
||||||
适用场景:
|
该路径继续承担:
|
||||||
|
- P0/P1 Runtime 回归测试。
|
||||||
|
- 主项目内 Addressables 真实 fixture 验收。
|
||||||
|
- MainMenuP0 Assets 样例源。
|
||||||
|
- 迁移到 package `Samples~` / `Tests~` 前的稳定参照。
|
||||||
|
|
||||||
- P2 第一阶段继续验证 P0/P1 Runtime 行为。
|
不要在消费方项目同时复制 `Assets/FlowScope` 并安装 Git package,否则会混淆“项目内源码导入”和“package 消费”两条验证路径。
|
||||||
- 并行开发 Addressables 验收、Editor 诊断与 package 文档。
|
|
||||||
- 在包迁移前保持 `MainMenuP0` 示例与测试路径稳定。
|
|
||||||
|
|
||||||
使用此模式时,不需要在 `manifest.json` 中声明 `com.flowscope.gamecore`。仍需要确保项目已有当前代码依赖的包,例如 `com.cysharp.r3`、`com.unity.addressables` 与 `com.unity.ugui`。
|
## 当前 package 内容
|
||||||
|
|
||||||
|
```text
|
||||||
|
Packages/com.flowscope.gamecore/
|
||||||
|
package.json
|
||||||
|
Runtime/
|
||||||
|
Addressables/
|
||||||
|
Editor/
|
||||||
|
Samples~/
|
||||||
|
Tests~/
|
||||||
|
Documentation~/
|
||||||
|
README.md
|
||||||
|
CHANGELOG.md
|
||||||
|
```
|
||||||
|
|
||||||
|
已完成:
|
||||||
|
- Runtime / Addressables / Editor 镜像到 package。
|
||||||
|
- `Samples~/MainMenuP0` 作为 package sample 候选。
|
||||||
|
- `Tests~/EditMode` 第一刀最小 smoke 测试。
|
||||||
|
- Git package 在 FishingFrenzy 中完成最小消费方验证。
|
||||||
|
|
||||||
|
仍未完成:
|
||||||
|
- package sample 导入后的人工验收。
|
||||||
|
- package `Tests~` 全量策略与 PlayMode 测试迁移。
|
||||||
|
- 真正空白 Unity 项目的 Git URL 安装复验。
|
||||||
|
- 下一个 preview tag。
|
||||||
|
|
||||||
## 最小 Bootstrap 示例
|
## 最小 Bootstrap 示例
|
||||||
|
|
||||||
下面示例只使用当前代码中已经存在的 API 名称。示例使用 Addressables 作为资源后端,适合未来包接入;如果项目暂时没有 Addressables 资源,也可以参考 `MainMenuP0` 示例中的自定义 `IResourceBackend` 做本地验证。
|
下面示例只使用当前真实 API 名称。示例使用 Addressables 作为资源后端;如果项目暂时没有 Addressables 资源,也可以参考 `MainMenuP0` 中的 `SampleResourceBackend` 做本地验证。
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
using System.Collections.Generic;
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FlowScope.Addressables;
|
using FlowScope.Addressables;
|
||||||
@@ -213,67 +236,38 @@ public sealed class FlowScopeBootstrap : MonoBehaviour
|
|||||||
_screenNavigator = screenNavigator;
|
_screenNavigator = screenNavigator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task LoadAsync(FeatureContext context)
|
public Task LoadAsync(FeatureContext context) => Task.CompletedTask;
|
||||||
{
|
public Task EnterAsync(FeatureContext context) => Task.CompletedTask;
|
||||||
return Task.CompletedTask;
|
public Task ExitAsync(FeatureContext context) => Task.CompletedTask;
|
||||||
}
|
public void Dispose() { }
|
||||||
|
|
||||||
public Task EnterAsync(FeatureContext context)
|
|
||||||
{
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ExitAsync(FeatureContext context)
|
|
||||||
{
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
接入要点:
|
## 接入要点
|
||||||
|
|
||||||
- `GameFlow.StartupAsync<TInitialFeature>(Container root, CancellationToken cancellationToken)` 会先解析并加载 `IConfigProvider`。
|
- `GameFlow.StartupAsync<TInitialFeature>` 会先解析并加载 `IConfigProvider`。
|
||||||
- 初始 Feature 必须实现 `IFeature`,并能从 Feature scope 中解析;示例使用 `_root.RegisterTransient(_ => new ExampleFeature(screenNavigator))`。
|
- 初始 Feature 必须实现 `IFeature`,并能从 root 或 Feature scope 中解析。
|
||||||
- 业务资源统一通过 `IResourceService` 或 `IResourceGroup` 加载,不直接在业务层调用 Addressables。
|
- 业务资源统一通过 `IResourceService` 或 `IResourceGroup` 加载,不直接调用 Addressables。
|
||||||
- UI 层使用 `UIManager.RegisterLayer(...)` 建立层级,再由 `UIScreenNavigator` 或业务 Feature 打开面板。
|
- UI 层使用 `UIManager.RegisterLayer(...)` 建立层级,再由 `UIScreenNavigator` 或业务 Feature 打开面板。
|
||||||
- Shutdown 时应调用 `GameFlow.ShutdownAsync(...)`,并释放 UI 预加载资源,例如 `_preloadService.ReleaseAll()`。
|
- Shutdown 时应调用 `GameFlow.ShutdownAsync(...)`,并释放 UI 预加载资源,例如 `_preloadService.ReleaseAll()`。
|
||||||
|
|
||||||
## Addressables 接入说明
|
|
||||||
|
|
||||||
使用 Addressables 时,推荐注册:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
IResourceService resources = new AddressablesResourceService(
|
|
||||||
new AddressablesResourceBackend());
|
|
||||||
```
|
|
||||||
|
|
||||||
这会把业务层依赖收敛到 `IResourceService`。`AddressablesResourceBackend` 只位于 Addressables 适配程序集,Runtime 不需要知道 Addressables 的存在。
|
|
||||||
|
|
||||||
如果某个系统需要独立资源生命周期,应通过 `resources.CreateGroup()` 创建 `IResourceGroup`,让 Feature 的资源释放跟随 `FeatureContext.Resources.Dispose()`。
|
|
||||||
|
|
||||||
## 常见误用
|
## 常见误用
|
||||||
|
|
||||||
- 不要让业务 Feature 直接调用 `UnityEngine.AddressableAssets.Addressables`;应通过 `IResourceService` 或 `IResourceGroup` 访问资源。
|
- 不要让业务 Feature 直接调用 `UnityEngine.AddressableAssets.Addressables`。
|
||||||
- 不要把短生命周期对象注册成 `RegisterInstance` 或 `RegisterSingletonFactory`;临时对象优先使用 `RegisterTransient`,需要随 Feature 生命周期释放的对象放在 Feature scope。
|
- 不要把短生命周期对象注册为 `RegisterInstance` 或 `RegisterSingletonFactory`。
|
||||||
- 不要跳过 `GameFlow.ShutdownAsync(...)`;它负责退出当前 Feature、释放 Feature scope,并处置 root container。
|
- 不要跳过 `GameFlow.ShutdownAsync(...)`。
|
||||||
- 不要把 `UIScreenNavigator` 当成完整页面路由系统;它是当前 UI 导航辅助,不负责 URL、跨 Feature 页面恢复或全局路由。
|
- 不要把 `UIScreenNavigator` 当作完整页面路由系统。
|
||||||
- 不要让 `FlowScope.Runtime` 反向依赖 Addressables、Editor、Samples 或 Tests。
|
- 不要让 `FlowScope.Runtime` 反向依赖 Addressables、Editor、Samples 或 Tests。
|
||||||
- 不要在没有注册 UI layer 的情况下打开面板;`UIManager.OpenAsync` 会要求面板声明的 layer 已经通过 `RegisterLayer` 注册。
|
- 不要在没有注册 UI layer 的情况下打开面板。
|
||||||
- 不要在未初始化 `AudioService.Initialize(IResourceService, AudioServiceConfig)` 前调用播放接口。
|
- 不要在未初始化 `AudioService.Initialize(...)` 前调用播放接口。
|
||||||
- 不要假设 package path 与 Git URL 在 P2 第一阶段已经可安装;当前真实可用形态仍是项目内 `Assets/FlowScope` 开发模式。
|
|
||||||
|
|
||||||
## 当前限制
|
## 当前限制
|
||||||
|
|
||||||
P2 第一阶段文档完成后,FlowScope 仍需要后续 worker 或阶段完成以下验证后,才能把 package 安装方式视为可交付:
|
P2 收口前仍需要完成:
|
||||||
|
|
||||||
1. 建立真实 package 根目录与 `package.json`。
|
1. package sample 导入验收。
|
||||||
2. 通过本地 package path 在干净 Unity 项目中验证安装。
|
2. package `Tests~` 全量策略和 PlayMode 迁移策略。
|
||||||
3. 验证 Git URL 安装与依赖解析。
|
3. 真正空白 Unity 项目 Git URL 安装复验。
|
||||||
4. 将 `MainMenuP0` 从 `Assets/FlowScope/Samples` 整理为可导入 package sample。
|
4. 下一个 preview tag。
|
||||||
5. 在干净 Unity 项目中复验 Addressables 测试资源、settings 与 PlayMode 用例;主项目内的真实 load/release 验收记录已完成。
|
5. Unity Test Runner 或明确记录无法执行原因。
|
||||||
6. 保持 generated csproj build 与 Unity Test Runner 记录为 0 error。
|
|
||||||
|
|||||||
@@ -1,86 +1,88 @@
|
|||||||
# FlowScope Package 目标结构
|
# FlowScope Package 结构与迁移边界
|
||||||
|
|
||||||
日期:2026-05-26
|
日期:2026-06-06
|
||||||
|
|
||||||
本文说明 FlowScope P2 阶段的目标 Unity Package 目录形态,以及第一阶段暂不搬迁 `Assets/FlowScope` 的边界。本文只描述目标结构与迁移约束,不代表当前仓库已经完成物理搬迁。
|
本文说明 FlowScope P2 阶段当前 package 结构、仍保留的 Assets 开发模式,以及后续迁移边界。
|
||||||
|
|
||||||
## 当前状态
|
## 当前状态
|
||||||
|
|
||||||
当前 FlowScope 仍处于项目内开发模式:
|
FlowScope 当前采用双轨结构:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
My project/
|
My project/Assets/FlowScope
|
||||||
Assets/
|
Packages/com.flowscope.gamecore
|
||||||
FlowScope/
|
|
||||||
Runtime/
|
|
||||||
Addressables/
|
|
||||||
Samples/
|
|
||||||
Tests/
|
|
||||||
```
|
```
|
||||||
|
|
||||||
当前尚未建立标准 Unity Package 根目录,未发现包级 `package.json`、`Samples~`、`Tests~`、`Documentation~` 目录。`MainMenuP0` 示例仍位于 `Assets/FlowScope/Samples/MainMenuP0`。
|
`Assets/FlowScope` 仍是开发工程内的测试和样例源;`Packages/com.flowscope.gamecore` 是面向消费方的 Unity Package 雏形。
|
||||||
|
|
||||||
## 目标包根目录
|
当前 package 目录:
|
||||||
|
|
||||||
目标包建议使用独立目录承载,例如:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Packages/
|
Packages/com.flowscope.gamecore/
|
||||||
com.flowscope.gamecore/
|
package.json
|
||||||
package.json
|
Runtime/
|
||||||
Runtime/
|
Addressables/
|
||||||
Addressables/
|
Editor/
|
||||||
Editor/
|
Samples~/
|
||||||
Samples~/
|
Tests~/
|
||||||
Tests/
|
Documentation~/
|
||||||
Documentation~/
|
README.md
|
||||||
README.md
|
CHANGELOG.md
|
||||||
CHANGELOG.md
|
|
||||||
LICENSE.md
|
|
||||||
```
|
```
|
||||||
|
|
||||||
目录职责如下:
|
已完成:
|
||||||
|
- Runtime 镜像到 `Runtime/`。
|
||||||
|
- Addressables adapter 镜像到 `Addressables/`。
|
||||||
|
- Editor 诊断窗口镜像到 `Editor/`。
|
||||||
|
- MainMenuP0 镜像到 `Samples~/MainMenuP0`。
|
||||||
|
- `Tests~/EditMode` 已建立最小 smoke 测试。
|
||||||
|
- package 顶层 `.meta` 已补齐,避免 immutable package 导入错误。
|
||||||
|
|
||||||
|
未完成:
|
||||||
|
- package `Tests~` 全量迁移策略。
|
||||||
|
- package sample 导入验收。
|
||||||
|
- 空白 Unity 项目安装复验。
|
||||||
|
- 下一个 preview tag。
|
||||||
|
|
||||||
|
## 目录职责
|
||||||
|
|
||||||
| 目录 | 职责 |
|
| 目录 | 职责 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `package.json` | Unity Package Manager 元数据,声明包名、显示名、版本、Unity 版本与依赖。 |
|
| `package.json` | Unity Package Manager 元数据,声明包名、显示名、版本、Unity 版本、依赖和 sample。 |
|
||||||
| `Runtime/` | FlowScope 核心运行时代码,包括 Container、Feature、GameFlow、Resource、Config、Save、Audio、UI 等能力。 |
|
| `Runtime/` | FlowScope 核心运行时代码,包括 Container、Feature、GameFlow、Resource、Config、Save、Audio、UI。 |
|
||||||
| `Addressables/` | Addressables 适配层,提供 `AddressablesResourceBackend` 与 `AddressablesResourceService`。 |
|
| `Addressables/` | Addressables 适配层,提供 `AddressablesResourceBackend` 与 `AddressablesResourceService`。 |
|
||||||
| `Editor/` | 只放编辑器诊断、检查、菜单入口等 Editor-only 内容,不承载运行时逻辑。 |
|
| `Editor/` | Editor-only 诊断入口,不承载运行时逻辑,不自动修改用户资源。 |
|
||||||
| `Samples~/` | Package Manager 可导入示例,例如 `MainMenuP0`。示例可以依赖 Runtime 与所演示的适配包。 |
|
| `Samples~/` | Package Manager 可导入示例。当前包含 `MainMenuP0`。 |
|
||||||
| `Tests/` | 包内测试,按 EditMode 与 PlayMode 分层保留测试 asmdef。 |
|
| `Tests~/` | package 内测试候选。当前先放最小 EditMode smoke 测试,不替代开发工程内完整测试。 |
|
||||||
| `Documentation~/` | Package Manager 文档入口,包含安装、接入、诊断与示例说明。 |
|
| `Documentation~/` | Package Manager 文档入口,包含安装和接入说明。 |
|
||||||
|
|
||||||
## package.json 建议形态
|
## package.json 当前形态
|
||||||
|
|
||||||
目标包元数据建议保持最小可识别:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "com.flowscope.gamecore",
|
"name": "com.flowscope.gamecore",
|
||||||
"displayName": "FlowScope Game Core",
|
"displayName": "FlowScope Game Core",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0-preview.1",
|
||||||
"unity": "2022.3",
|
"unity": "2022.3",
|
||||||
"description": "A lightweight Unity game flow, resource, config, save, audio, and UI runtime foundation.",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.cysharp.r3": "https://github.com/Cysharp/R3.git?path=src/R3.Unity/Assets/R3.Unity#1.3.0",
|
|
||||||
"com.unity.addressables": "1.21.21",
|
"com.unity.addressables": "1.21.21",
|
||||||
"com.unity.ugui": "1.0.0"
|
"com.unity.ugui": "1.0.0"
|
||||||
}
|
},
|
||||||
|
"samples": [
|
||||||
|
{
|
||||||
|
"displayName": "MainMenuP0",
|
||||||
|
"description": "Minimal FlowScope bootstrap, feature, UI, save, and preload sample.",
|
||||||
|
"path": "Samples~/MainMenuP0"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
依赖说明:
|
注意:`com.cysharp.r3` 和 `org.nuget.r3` 当前由消费方项目显式声明,原因是 Unity Package Manager 不可靠支持 package 内 Git dependency 传递解析。
|
||||||
|
|
||||||
- `com.cysharp.r3` 是当前 `FlowScope.Runtime.asmdef` 直接引用 `R3.Unity` 的来源。
|
|
||||||
- `com.unity.addressables` 只服务 `FlowScope.Addressables`,Runtime 不直接依赖 Addressables。
|
|
||||||
- `com.unity.ugui` 服务当前 UI 与示例中的 `Canvas`、`Button`、`Text` 等 UGUI 类型。
|
|
||||||
|
|
||||||
如果后续发布渠道不接受 Git URL 形式依赖,应在发布前改为团队确认过的 OpenUPM、内网 registry 或嵌入式依赖策略。
|
|
||||||
|
|
||||||
## asmdef 依赖方向
|
## asmdef 依赖方向
|
||||||
|
|
||||||
当前与目标结构都必须保持以下方向:
|
必须保持以下方向:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
FlowScope.Runtime
|
FlowScope.Runtime
|
||||||
@@ -93,45 +95,49 @@ FlowScope.Addressables
|
|||||||
|
|
||||||
FlowScope.Editor
|
FlowScope.Editor
|
||||||
-> FlowScope.Runtime
|
-> FlowScope.Runtime
|
||||||
-> 需要诊断的编辑器程序集
|
-> 诊断所需的 Editor 程序集
|
||||||
|
|
||||||
FlowScope.Samples.MainMenuP0
|
FlowScope.Samples.MainMenuP0
|
||||||
-> FlowScope.Runtime
|
-> FlowScope.Runtime
|
||||||
-> R3.Unity
|
-> R3.Unity
|
||||||
|
|
||||||
FlowScope.Tests.EditMode / FlowScope.Tests.PlayMode
|
FlowScope.PackageTests.EditMode
|
||||||
-> 被测程序集
|
-> FlowScope.Runtime
|
||||||
|
-> FlowScope.Addressables
|
||||||
|
-> NUnit / Unity Test Framework
|
||||||
```
|
```
|
||||||
|
|
||||||
禁止反向依赖:
|
禁止反向依赖:
|
||||||
|
|
||||||
- `FlowScope.Runtime` 不依赖 `FlowScope.Addressables`。
|
- `FlowScope.Runtime` 不依赖 `FlowScope.Addressables`。
|
||||||
- `FlowScope.Runtime` 不依赖 `FlowScope.Editor`。
|
- `FlowScope.Runtime` 不依赖 `FlowScope.Editor`。
|
||||||
- `FlowScope.Runtime` 不依赖 `FlowScope.Samples.*`。
|
- `FlowScope.Runtime` 不依赖 `FlowScope.Samples.*`。
|
||||||
- `FlowScope.Runtime` 不依赖测试程序集。
|
- `FlowScope.Runtime` 不依赖测试程序集。
|
||||||
- Samples 不作为 Runtime 的依赖来源。
|
- Samples 不作为 Runtime 的依赖来源。
|
||||||
|
|
||||||
`AddressablesResourceService` 当前命名空间位于 `FlowScope.Resources`,但文件处于 `Assets/FlowScope/Addressables` 并编译进 `FlowScope.Addressables` 程序集;迁移时应保留程序集边界,不应因为命名空间相同而把 Addressables 适配代码并回 Runtime。
|
`AddressablesResourceService` 当前命名空间为 `FlowScope.Resources`,但文件位于 Addressables 适配程序集;迁移和镜像时必须保留程序集边界,不应因为命名空间相同而把 Addressables 适配代码并回 Runtime。
|
||||||
|
|
||||||
## 第一阶段暂不搬迁 Assets/FlowScope 的原因
|
## 双轨边界
|
||||||
|
|
||||||
P2 第一阶段只建立分发边界、安装接入文档、Addressables 验收与最小 Editor 诊断入口,不做物理搬迁,原因如下:
|
当前不删除 `Assets/FlowScope`,原因:
|
||||||
|
|
||||||
1. 当前 `Assets/FlowScope` 已承载 P0/P1 Runtime、Addressables、Samples、Tests 的稳定验证路径。
|
1. `Assets/FlowScope` 仍承载完整 EditMode / PlayMode 回归测试。
|
||||||
2. `MainMenuP0` 示例、PlayMode 测试与 Unity 生成的 csproj 仍依赖当前 Asset 路径。
|
2. 主项目内 Addressables 真实 fixture 和 settings 是当前真实验收来源。
|
||||||
3. 一次性移动 Runtime、Samples、Tests 会同时改变 asmdef 路径、资源路径、场景引用、prefab 引用与测试发现路径,容易把包结构问题和运行时回归混在一起。
|
3. `Samples~/MainMenuP0` 是 package sample 候选,但尚未完成消费方导入验收。
|
||||||
4. 第一阶段还有并行 worker 处理 Addressables 验收与 Editor 诊断;Package 文档 worker 不应覆盖或移动他们的文件。
|
4. 一次性把 Samples、Tests 和 Addressables fixture 全部迁入 package 会扩大验证面。
|
||||||
5. 先用文档锁定目标结构与依赖方向,可以让第二阶段本地 package 试迁移按批次验证,而不是一次性大搬迁。
|
|
||||||
|
|
||||||
## 建议迁移顺序
|
当前迁移策略是“镜像 + 逐步验收”:
|
||||||
|
|
||||||
后续进入 P2 第二阶段时,建议按以下顺序迁移,每一步都保留独立验证记录:
|
1. package 内保留 Runtime / Addressables / Editor 镜像。
|
||||||
|
2. package sample 先镜像 MainMenuP0,不删除 Assets 样例。
|
||||||
|
3. package tests 先建立最小 smoke 测试,不删除 Assets 测试。
|
||||||
|
4. 待 package 导入、Tests~、空白项目验证完成后,再决定是否把 package 作为源码主线。
|
||||||
|
|
||||||
1. 创建 package 根目录与 `package.json`,先不移动 Runtime。
|
## 后续 P2 顺序
|
||||||
2. 将 `Runtime/` 移入包目录并验证 `FlowScope.Runtime` 编译边界。
|
|
||||||
3. 将 `Addressables/` 移入包目录并验证 `FlowScope.Addressables` 仍只依赖 Runtime 与 Unity Addressables。
|
|
||||||
4. 将文档迁入 `Documentation~/` 或同步保留到仓库 `docs/`。
|
|
||||||
5. 将 `MainMenuP0` 作为包示例迁入 `Samples~/MainMenuP0`,验证场景、prefab、配置与测试路径。
|
|
||||||
6. 将 EditMode / PlayMode 测试整理进包内 `Tests/`,验证 Unity Test Runner 发现与执行。
|
|
||||||
|
|
||||||
每一步完成前都应验证 generated csproj build、Unity Test Runner 和关键示例路径;如果某一步失败,应先回到该步骤修复,不继续叠加后续搬迁。
|
建议继续按以下顺序收口:
|
||||||
|
|
||||||
|
1. 完成 package `Tests~` 第一刀并验证静态结构。
|
||||||
|
2. 决定哪些测试可迁入 package,哪些仍留在开发工程。
|
||||||
|
3. 在消费方导入 `Samples~/MainMenuP0` 做人工验收。
|
||||||
|
4. 在空白 Unity 项目中复验 Git URL 安装。
|
||||||
|
5. 根据最新 package 内容打下一个 preview tag。
|
||||||
|
|||||||
@@ -54,6 +54,6 @@
|
|||||||
|
|
||||||
1. 当前 preview tag 已可被消费方解析,但 tag 内 package 文档仍是打 tag 当时的快照。后续如果要让 package 内文档也随 tag 发布,应在文档修正后创建下一个 preview tag。
|
1. 当前 preview tag 已可被消费方解析,但 tag 内 package 文档仍是打 tag 当时的快照。后续如果要让 package 内文档也随 tag 发布,应在文档修正后创建下一个 preview tag。
|
||||||
2. 已在后续切片镜像 `Samples~/MainMenuP0`,但尚未在消费方导入 package sample 做人工验收。
|
2. 已在后续切片镜像 `Samples~/MainMenuP0`,但尚未在消费方导入 package sample 做人工验收。
|
||||||
3. 还没有迁移 package 内 `Tests`。
|
3. 已在后续切片建立 package `Tests~/EditMode` 第一刀 smoke 测试,但尚未迁移完整 Runtime/EditMode/PlayMode 测试。
|
||||||
4. Addressables 测试资源已统一到主项目测试目录的 `Resources/Fixtures/Addressables`,后续迁移 Tests 前需要决定是否镜像到 package `Tests~`。
|
4. Addressables 测试资源已统一到主项目测试目录的 `Resources/Fixtures/Addressables`,后续迁移 Tests 前需要决定是否镜像到 package `Tests~`。
|
||||||
5. 仍需在一个真正空白 Unity 项目中重复 Git package 接入;FishingFrenzy 是真实消费方,但不是空白项目。
|
5. 仍需在一个真正空白 Unity 项目中重复 Git package 接入;FishingFrenzy 是真实消费方,但不是空白项目。
|
||||||
|
|||||||
Reference in New Issue
Block a user