diff --git a/docs/used/SRP_URP_ScriptableObjectRenderAssetInstantiationPlan_2026-04-21_完成归档.md b/docs/used/SRP_URP_ScriptableObjectRenderAssetInstantiationPlan_2026-04-21_完成归档.md new file mode 100644 index 00000000..c1ad3898 --- /dev/null +++ b/docs/used/SRP_URP_ScriptableObjectRenderAssetInstantiationPlan_2026-04-21_完成归档.md @@ -0,0 +1,68 @@ +# SRP URP ScriptableObject Render Asset Instantiation Plan + +Date: 2026-04-21 + +## Background + +The previous stage introduced a minimal managed `ScriptableObject` substrate and +already moved the SRP/URP render asset types onto it: + +- `RenderPipelineAsset` +- `ScriptableRendererData` +- `ScriptableRendererFeature` + +That fixed the inheritance model, but the creation model is still mixed: + +- several production code paths still instantiate render assets with `new` +- user-facing probes still demonstrate `new UniversalRenderPipelineAsset()` and + `new UniversalRendererData()` + +For a Unity-style SRP/URP direction, the next cleanup is to move the common +creation paths onto `ScriptableObject.CreateInstance(...)` semantics. + +## Goal + +Make the managed SRP/URP render asset creation model more Unity-like: + +- default renderer data creation uses `ScriptableObject.CreateInstance` +- default builtin renderer feature creation uses `ScriptableObject.CreateInstance` +- key user-facing probes demonstrate the same model + +This stage does not try to ban every direct `new` immediately. It focuses on +the primary engine paths and the API examples users are most likely to follow. + +## Scope + +Included: + +- `managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs` +- `managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs` +- `managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs` +- selected user-facing probes in `managed/GameScripts/RenderPipelineApiProbe.cs` + +Not included: + +- constructor access restriction across every custom probe type +- editor serialization work +- native asset persistence work + +## Implementation Plan + +1. Switch default renderer data creation to `ScriptableObject.CreateInstance` +2. Switch builtin renderer feature creation to `ScriptableObject.CreateInstance` +3. Switch the main fallback `UniversalRenderer` path to the same substrate +4. Update key SRP/URP selection probes to use `CreateInstance` +5. Rebuild `XCEditor` +6. Run old editor smoke for at least 10 seconds and verify a fresh + `SceneReady` +7. Archive the plan, commit, and push + +## Expected Result + +After this stage: + +- engine-side SRP/URP default creation paths match the new ScriptableObject + substrate +- user-facing probe code demonstrates the intended Unity-style creation model +- the codebase takes another step away from plain-object semantics for render + assets diff --git a/managed/GameScripts/RenderPipelineApiProbe.cs b/managed/GameScripts/RenderPipelineApiProbe.cs index 61eae00d..5321a5fd 100644 --- a/managed/GameScripts/RenderPipelineApiProbe.cs +++ b/managed/GameScripts/RenderPipelineApiProbe.cs @@ -2310,14 +2310,21 @@ namespace Gameplay public void Start() { UniversalRenderPipelineAsset asset = - new UniversalRenderPipelineAsset - { - rendererDataList = - new ScriptableRendererData[] - { - new UniversalRendererData() - } - }; + ScriptableObject + .CreateInstance(); + UniversalRendererData rendererData = + ScriptableObject + .CreateInstance(); + if (asset != null && + rendererData != null) + { + asset.rendererDataList = + new ScriptableRendererData[] + { + rendererData + }; + } + GraphicsSettings.renderPipelineAsset = asset; UniversalRenderPipelineAsset selectedAsset = @@ -2356,15 +2363,24 @@ namespace Gameplay { public void Start() { - GraphicsSettings.renderPipelineAsset = - new UniversalRenderPipelineAsset + UniversalRenderPipelineAsset asset = + ScriptableObject + .CreateInstance(); + UniversalRendererData rendererData = + ScriptableObject + .CreateInstance(); + if (asset == null || + rendererData == null) + { + return; + } + + asset.rendererDataList = + new ScriptableRendererData[] { - rendererDataList = - new ScriptableRendererData[] - { - new UniversalRendererData() - } + rendererData }; + GraphicsSettings.renderPipelineAsset = asset; } } @@ -2373,20 +2389,26 @@ namespace Gameplay { public void Start() { - GraphicsSettings.renderPipelineAsset = - new UniversalRenderPipelineAsset + UniversalRenderPipelineAsset asset = + ScriptableObject + .CreateInstance(); + UniversalRendererData rendererData = + ScriptableObject + .CreateInstance(); + if (asset == null || + rendererData == null) + { + return; + } + + rendererData.mainScene = + UniversalMainSceneData.CreateOpaqueOnly(); + asset.rendererDataList = + new ScriptableRendererData[] { - rendererDataList = - new ScriptableRendererData[] - { - new UniversalRendererData - { - mainScene = - UniversalMainSceneData - .CreateOpaqueOnly() - } - } + rendererData }; + GraphicsSettings.renderPipelineAsset = asset; } } @@ -2395,29 +2417,38 @@ namespace Gameplay { public void Start() { - GraphicsSettings.renderPipelineAsset = - new UniversalRenderPipelineAsset + UniversalRenderPipelineAsset asset = + ScriptableObject + .CreateInstance(); + UniversalRendererData rendererData = + ScriptableObject + .CreateInstance(); + ColorScalePostProcessRendererFeature colorScaleFeature = + ScriptableObject + .CreateInstance(); + if (asset == null || + rendererData == null || + colorScaleFeature == null) + { + return; + } + + colorScaleFeature.colorScale = new Vector4( + 1.08f, + 0.96f, + 0.92f, + 1.0f); + rendererData.rendererFeatures = + new ScriptableRendererFeature[] { - rendererDataList = - new ScriptableRendererData[] - { - new UniversalRendererData - { - rendererFeatures = - new ScriptableRendererFeature[] - { - new ColorScalePostProcessRendererFeature - { - colorScale = new Vector4( - 1.08f, - 0.96f, - 0.92f, - 1.0f) - } - } - } - } + colorScaleFeature }; + asset.rendererDataList = + new ScriptableRendererData[] + { + rendererData + }; + GraphicsSettings.renderPipelineAsset = asset; } } @@ -2426,22 +2457,33 @@ namespace Gameplay { public void Start() { - GraphicsSettings.renderPipelineAsset = - new UniversalRenderPipelineAsset + UniversalRenderPipelineAsset asset = + ScriptableObject + .CreateInstance(); + UniversalRendererData rendererData = + ScriptableObject + .CreateInstance(); + DisableDirectionalShadowRendererFeature shadowlessFeature = + ScriptableObject + .CreateInstance(); + if (asset == null || + rendererData == null || + shadowlessFeature == null) + { + return; + } + + rendererData.rendererFeatures = + new ScriptableRendererFeature[] { - rendererDataList = - new ScriptableRendererData[] - { - new UniversalRendererData - { - rendererFeatures = - new ScriptableRendererFeature[] - { - new DisableDirectionalShadowRendererFeature() - } - } - } + shadowlessFeature }; + asset.rendererDataList = + new ScriptableRendererData[] + { + rendererData + }; + GraphicsSettings.renderPipelineAsset = asset; } } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs index 531d389e..a1e74395 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs @@ -61,7 +61,9 @@ namespace XCEngine.Rendering.Universal protected override ScriptableRendererData CreateDefaultRendererData() { - return new UniversalRendererData(); + return ScriptableObject + .CreateInstance() ?? + new UniversalRendererData(); } protected override int ResolveRendererIndex( diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs index b2434852..a21886c5 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs @@ -39,7 +39,10 @@ namespace XCEngine.Rendering.Universal UniversalRendererData rendererData) { m_rendererData = - rendererData ?? new UniversalRendererData(); + rendererData ?? + ScriptableObject + .CreateInstance() ?? + new UniversalRendererData(); } protected override void ConfigureCameraFramePlan( diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs index 4abd0dc5..685c0e02 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs @@ -35,10 +35,18 @@ namespace XCEngine.Rendering.Universal protected override ScriptableRendererFeature[] CreateDefaultRendererFeatures() { + BuiltinGaussianSplatRendererFeature gaussianSplatFeature = + ScriptableObject + .CreateInstance() ?? + new BuiltinGaussianSplatRendererFeature(); + BuiltinVolumetricRendererFeature volumetricFeature = + ScriptableObject + .CreateInstance() ?? + new BuiltinVolumetricRendererFeature(); return new ScriptableRendererFeature[] { - new BuiltinGaussianSplatRendererFeature(), - new BuiltinVolumetricRendererFeature() + gaussianSplatFeature, + volumetricFeature }; }