【Unity URP】通过代码动态添加URP渲染通道RendererFeature

URP的渲染通道RendererFeature可以很方便的实现一些渲染问题,比如渲染顺序问题,遮挡后的材质替换等等。
那么我们如何通过代码来动态添加和修改呢?

首先我们需要获取到当前的URP配置文件,在对配置文件进行添加

1.通过反射获取当前UniversalRendererData

我们通过GraphicsSettings.renderPipelineAsset或QualitySettings.renderPipeline,可以获取到Edit中Graphic或Quality中设置的URP配置。

但无法获取配置中的RendererList,
在这里插入图片描述
UniversalRenderPipelineAsset并没有开放此属性。
在这里插入图片描述
所以我们可以通过反射来获取此属性。(获取了RendererList中第一个data)

        UniversalRenderPipelineAsset URPAsset = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
        FieldInfo propertyInfo = URPAsset.GetType().GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic);
        UniversalRendererData URPData = (UniversalRendererData)(((ScriptableRendererData[])propertyInfo?.GetValue(URPAsset))?[0]);

2. 动态添加RendererFeature渲染

代码完成AddRendererFeature功能(运行时可用)
在这里插入图片描述

以在最前方渲染为例:

        RenderObjects rendererFeatrue = ScriptableObject.CreateInstance<RenderObjects>();
        rendererFeatrue.name = "Test";
        //填写期望的layer
        rendererFeatrue.settings.filterSettings.LayerMask = (1 << LayerMask.NameToLayer("yourlayer0") | 1 << LayerMask.NameToLayer("yourlayer1"));
        //设置材质是否透明
        rendererFeatrue.settings.filterSettings.RenderQueueType = RenderQueueType.Transparent;
        rendererFeatrue.settings.overrideDepthState = true;
        rendererFeatrue.settings.depthCompareFunction = CompareFunction.Disabled;

创建完成后,添加到UniversalRendererData的rendererFeatures中

URPData.rendererFeatures.Add(rendererFeatrue);

如在编辑器模式中添加,则还需要RenderObjects的本地文件id,添加到UniversalRendererData的m_RendererFeatureMap中 。 m_RendererFeatureMap使用反射获取

        FieldInfo propertyInfo = _urpData.GetType().GetField("m_RendererFeatureMap", BindingFlags.Instance | BindingFlags.NonPublic);
        List<long> renderFeatureMapList = (List<long>)propertyInfo?.GetValue(_urpData);
        UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(rendererFeatrue, out var guid, out long localId);
        renderFeatureMapList.Add(localId);

要注意,如在Editor下添加,需将动态添加的Reature写入URP配置文件中,否则,缓存丢失后,该Reature会报空错误提示。

UnityEditor.AssetDatabase.AddObjectToAsset(rendererFeatrue , URPAsset );

最后要使改动立刻生效。

URPData.SetDirty();

完整代码:

 private RenderObjects rendererFeatrue;
    private UniversalRendererData URPData;
    private void Start()
    {
        AddRenderFeatrue();
    }

    private void OnDestroy()
    {
        URPData.rendererFeatures.Remove(rendererFeatrue);
    }

    private void AddRenderFeatrue()
    {
        rendererFeatrue = ScriptableObject.CreateInstance<RenderObjects>();
        rendererFeatrue.name = "Test";
        rendererFeatrue.settings.filterSettings.LayerMask = (1 << LayerMask.NameToLayer("yourlayer0") | 1 << LayerMask.NameToLayer("yourlayer1"));
        rendererFeatrue.settings.filterSettings.RenderQueueType = RenderQueueType.Transparent;
        rendererFeatrue.settings.overrideDepthState = true;
        rendererFeatrue.settings.depthCompareFunction = CompareFunction.Disabled;

         
        UniversalRenderPipelineAsset URPAsset = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
        FieldInfo propertyInfo = URPAsset.GetType().GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic);
        URPData = (UniversalRendererData)(((ScriptableRendererData[])propertyInfo?.GetValue(URPAsset))?[0]);
        URPData.rendererFeatures.Add(rendererFeatrue);

	    //在编辑器模式下,需将RenderObjects的本地文件id添加到m_RendererFeatureMap中        
        FieldInfo propertyInfo = URPAsset.GetType().GetField("m_RendererFeatureMap", BindingFlags.Instance | BindingFlags.NonPublic);
        List<long> renderFeatureMapList = (List<long>)propertyInfo?.GetValue(URPAsset);
        UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(rendererFeatrue, out var guid, out long localId);
        renderFeatureMapList.Add(localId);
        
        UnityEditor.AssetDatabase.AddObjectToAsset(rendererFeatrue , URPAsset );
        URPData.SetDirty();

    }

参考https://forum.unity.com/threads/how-to-access-scriptablerendererdata-from-script.1012336/

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真鬼123

祝你节节高升岁岁平安越来越漂亮

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值