I want to add SSAO settings to ingame graphic settings menu. It seems I need to use reflection to access Renderer Feature fields. I managed to do this however since all URP assets are ScriptableObject. So when I change fields on runtime in Editor, Fields are changed after game stopped. I don’t want to change original asset.
I achieve this with instantiate all ScriptableObjects. Everything seems worked for now, but I’m afraid some side effects later. TLDR; I need some expert advices for proper way to change RendererFeature fields without change original asset.
private void LoadRendererData()
{
var rendererAsset = GraphicsSettings.renderPipelineAsset as UniversalRenderPipelineAsset;
if (rendererAsset == null)
{
Debug.LogError("Renderer asset is null!");
return;
}
//Instantiate and set URP asset
QualitySettings.renderPipeline =
GraphicsSettings.renderPipelineAsset =
_currentRenderPipelineAsset = Instantiate(rendererAsset);
if (_renderDataListField == null)
{
_renderDataListField = typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList",
BindingFlags.NonPublic | BindingFlags.Instance);
}
//Instantiate and set renderer data
var rendererDataList = _renderDataListField.GetValue(_currentRenderPipelineAsset) as ScriptableRendererData[];
rendererDataList[0] = _currentRendererData = Instantiate(rendererDataList[0]);
//Find SSAO
var ssaoFeature = _currentRendererData.rendererFeatures
.FirstOrDefault(x => x.GetType().Name == "ScreenSpaceAmbientOcclusion");
if (ssaoFeature == null) return;
//Instantiate new SSAO
var newFeature = Instantiate(ssaoFeature);
//Replace SSAO with new one
_currentRendererData.rendererFeatures.Remove(ssaoFeature);
_currentRendererData.rendererFeatures.Add(newFeature);
//Should I call these???
ssaoFeature.Dispose();
newFeature.Create();
}