如何动态获取URP设置里自定义的RenderFeatures

如何动态获取URP设置里自定义的RenderFeatures

1)如何动态获取URP设置里自定义的RenderFeatures
​2)UGUI里,把UI丢回池里,把方案SetActive(false)方法的最佳
3)Prefab中m_Text会自动换行导致搜索不到
4)URP变体优化shader_feature,MAIN_LIGHT_SHADOWS关键字废弃


这是第295篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Script

Q:我们在URP项目中自定义了多个RenderFeatures去实现游戏效果,现在想动态开启和关闭相关的RenderFeatures,请问怎么在代码里动态获取这些Features呢?

A:我们使用反射获取,供参考:

public static class ScriptableRendererExtension
{
    private static readonly Dictionary<ScriptableRenderer, Dictionary<string, ScriptableRendererFeature>> s_renderFeatures = new Dictionary<ScriptableRenderer, Dictionary<string, ScriptableRendererFeature>>();

    public static ScriptableRendererFeature GetRendererFeature(this ScriptableRenderer renderer, string name)
    {
        if (!s_renderFeatures.TryGetValue(renderer, out var innerFeatures))
        {
            var propertyInfo = renderer.GetType().GetProperty("rendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic);
            List<ScriptableRendererFeature> rendererFeatures = (List<ScriptableRendererFeature>)propertyInfo?.GetValue(renderer);
            if (rendererFeatures == null)
            {
                s_renderFeatures[renderer] = null;
            }
            else
            {
                innerFeatures = new Dictionary<string, ScriptableRendererFeature>();
                for (var i = 0; i < rendererFeatures.Count; i++)
                {
                    var feature = rendererFeatures[i];
                    innerFeatures[feature.name] = feature;
                }
                s_renderFeatures[renderer] = innerFeatures;
            }
        }
        if (innerFeatures != null)
        {
            innerFeatures.TryGetValue(name, out var result);
            return result;
        }
        return null;
    }
}

感谢yqsas@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/625d1d50a43e6117d06de3b8


UGUI

Q:想请教下在UGUI里,把UI扔回池里,取代SetActive(false)这种低效方法的最佳方案是什么呢?具体应当怎样操作?

A1:可以尝试移到屏幕外的一个池子里,不SetActive(false),SetScale=0,Disable一些逻辑脚本,移回去的时候做相反的操作。配合一些数值初始化的操作,可以减少UI重建的耗时。

感谢小ben@UWA问答社区提供了回答

A2:可以使用Canvas Group,改变Alpha来代替SetActive(),不会触发UI重建,我们有些项目已经使用这样的方式,效果还不错。

感谢廖武兴@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/625fd559a43e6117d071a58a


Script

Q:在Prefab中的m_Text会自动换行,导致完全匹配搜索的时候搜索不到,这应该怎么解决?

A:如果使用类似文本读取的方式解析Prefab,会出现换行的问题。

可以考虑使用AssetDatabase.LoadAssetAtPath来提取所有文本:

string[] dirs = { “Assets” };
var asstIds = AssetDatabase.FindAssets(“t:Prefab”, dirs);
for (int i = 0; i < asstIds.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(asstIds[i]);
var obj = AssetDatabase.LoadAssetAtPath(path);
var text = obj.GetComponent();
Debug.Log(text.text);
}

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/626127e436a2fd066de2f74f


Shader

Q:为了优化变体数量,将URP Shader中的multi_compile改成了shader_feature,然后遍历所有场景角色,收集一个变体和所有Shader打在了一个AssetBundle中。结果就是PC包的变体正常,但是Android包的变体却丢失了部分Keywords,主要是这个_MAIN_LIGHT_SHADOWS。

PC包:

Android包:

上面所有的关键字都是shader_feature定义的,但是只丢失_MAIN_LIGHT_SHADOWS和_MAIN_LIGHT_SHADOWS_CASCADE。

然后通过AssetStudio排查在shader.ab内编译后的Shader文件,也能够找到这个变体,说明这个变体实际上是在包内的。

再测试将Shader中的shader_feature还原成multi_compile形式,Android包的变体显示也都正确了,跟PC一样。

大家有遇到过类似的URP管线丢变体问题么?

A:找到原因了,遍历场景收集变体的代码写的有点问题,收集的时候Editor是PC平台,只考虑了开启阴影+Cascade的时候的变体。

所以PC上同时存在_MAIN_LIGHT_SHADOWS和_MAIN_LIGHT_SHADOWS_CASCADE关键字,表现是正常的。

而Android机器上没开启级联阴影,所以只有这个关键字_MAIN_LIGHT_SHADOWS,其实变体没有收集到。

感谢题主范世青@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/625e6f91a43e6117d06fab82

封面图来源于网络


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)