动画骨骼节点批处理

栏目: 后端 · 发布时间: 5年前

内容简介:这是第140篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。UWA 问答社区:answer.uwa4d.comUWA QQ群2:793972859(原群已满员)

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

UWA 问答社区:answer.uwa4d.com

UWA QQ群2:793972859(原群已满员)

本期目录:

  • 动画骨骼节点批处理
  • 粒子系统崩溃
  • 自定义Shader在iOS上出现异常
  • Editor里可以达到100帧,真机上FPS一直低于30帧
  • 多语言下Text组件大小和文本长度的适配

动画

Q:动画系统中开启Optimize GameObject选项后,不必要的骨骼会消失,我们在骨骼下面挂了很多特效挂点,也清楚可以通过 Extra Transforms to Expose暴露出挂点,但是每个模型去手选暴露太过麻烦,能否有批量处理的方法呢?

A1:这个可以通过Asset Postprocessor在导入的时候对模型进行遍历,将符合指定前缀的节点路径加入到Model Importer的Extra Exposed Transform Paths属性里,之后再调用Optimize Transform Hierarchy去实现优化节点的效果,不知道我有没有理解错。

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

UWA:补充楼上,如果是已知确定的节点名字,可以直接赋值,总之都是用OnPreprocessModel,具体规则自己项目组里约定好就好了。

public static string[] NodeNames = new string[]
{
    "node_head",
    "node_arm",  
    "node_leg", 
};

void OnPreprocessModel()
{
    ModelImporter importer = assetImporter as ModelImporter;
    importer.optimizeGameObjects = true;
    //若实际骨骼中没有以下节点,可能会报错,但不影响使用
    importer.extraExposedTransformPaths = EWEquipmentsBase.nodeNames;
}

A3:楼上两个回答都有效,但还有一个更简单的办法。

先说一下Extra Transforms to Expose的大概原理(不一定都对),观察UnityEditor.dll相关实现可知:

1)开发者修改ExtraTransformstoExpose后,Unity会将信息保存在fbx的meta文件的extraExposedTransformPaths属性中。

2)在Unity根据fbx文件生成Prefab时,会依据meta文件中的extraExposedTransformPaths每一个String创建一个对应名字的空GameObject,并且不需考虑父子关系。

3)运行时,(推测)Prefab被Instantiate后,其Animator组件Awake时触发了Animator.Rebind方法,该方法会遍历Transform的子节点,将子节点的name和Avatar中骨骼信息对比,随后自动绑定节点。

这也是Optimized之后Animator组件上必须有Avatar的原因(非Optimized的GameObject可以将Animator组件的Avatar引用置空),想进一步研究Avatar可以将Inspector改为Debug模式查看。

基于以上分析,我们可以模仿这一过程,直接在Optimized之后的Prefab下面创建空的GameObject,随后将该空GameObject的名字改成约定好的骨骼挂点名字,这样就实现了和ExtraExposedTransformPaths相同的功能。

更进一步,我们可以利用Animator.Rebind方法实现运行时动态添加删除挂点的功能。这样做的好处是一来特效和策划同学无需反复修改Prefab(当然也可以离线制作好);二是无需为Prefab绑定所有的挂点,只需创建配置表里实际用到的挂点,甚至可以把挂点GameObject放入对象池回收利用,角色比较多且默认挂点比较多的情况下可以起到优化内存的作用。缺点就是Animator.Rebind耗时比较大,可以考虑随着Instantiate调用。

动态绑定挂点示例:

1private static readonly string[] s_BindPoints = new string[]
 2{
 3    "node_head",
 4    "node_arm",
 5    "node_leg",
 6};
 7
 8private Animator m_Animator = null;
 9private void Awake()
10{
11    m_Animator = GetComponent<Animator>();
12    Assert.IsNotNull(m_Animator);
13    foreach (var bindPoint in s_BindPoints)
14    {
15        GameObject bindPointObj = new GameObject(bindPoint);
16        bindPointObj.layer = gameObject.layer;
17        bindPointObj.transform.SetParent(transform);
18    }
19    m_Animator.Rebind();    // important!
20}

感谢张迪@UWA问答社区分享了该经验

该问答来自UWA问答社区,欢迎大家转至社区交流:

https://answer.uwa4d.com/question/5c0a256a28c4e32cba3192eb

崩溃

Q:求助一个低概率随机崩溃问题,下面是崩溃的堆栈信息,我在网上搜索了下 “Abort message: ‘* Assertion at mini-arm.c:2634, condition `pdata.found == 1’ not met” 有人提到是与DLL相关,Android平台上应该是与本地的native code代码相关(当前项目使用了liblua53.so和其他 lua 相关的.so库),看了下mini-arm.c的源码,的确是在处理 mono_code_manager 相关一些东西,不知道有哪位大神遇见过并解决了的,请不吝赐教!

动画骨骼节点批处理

题主:上周我们项目进行了7天外网小规模(2000左右玩家)测试,在这期间面对的崩溃问题的处理过程和问题原因,仍旧比较深刻。

之前,崩溃在libmono.so “Abort message: Assertion at mini-arm.c:2634, condition `pdata.found == 1’ not met” 的这个低概率随机崩溃问题一直困扰着我,主要是这个问题崩溃在mono,崩溃的栈信息完全与libunity.so,libmain.so无关,更别说基于Unity的逻辑层代码,面对我们的对外测试11月30号时间临近,我在28号的时候对mono进行一次简单的处理:将mono代码mini-arm.c:2634 中的断言 g_assert (pdata.found == 1); 注释掉,换成了普通的错误信息输出,编译后直接提交到项目工程中,毕竟这个改动算是无害处理,然后开始去优化项目中卡顿点去了,也没有继续跟踪这个改动,因为当时想到是小概率事件。

11月29号提交给发行版本后,晚上发行反馈说,感觉这个版本的崩溃率有点高,但说没有实际统计过,得到这个反馈后,我也没有特别在意,继续处理其他问题去了(真后悔当时没有去看bugly)

11月30号中午正式开测,到下午4-5点后,部分同事反馈告诉我说,崩溃率有点高,平时测试都不会闪退,今天闪退2-3次了…其中一个同事告诉我说,挂机15分钟内必崩溃…当时听到这个问题后心里一紧,赶紧去看了下bugly,发现崩溃率到了7.x%,远高于平时我们测试2.x%的统计,我再仔细一看,都集中在各种粒子系统崩溃中:

动画骨骼节点批处理 动画骨骼节点批处理 动画骨骼节点批处理

看到这些崩溃后,回忆了下最近两天的优化,在优化卡顿的问题中,当时对粒子系统组件 ParticleSystem 进行了本地引用缓存,不需要每次播放技能特效时都进行一次GetGetComponentsInChildren(true),同时对技能特效粒子系统停止时调用stop()修改为pause()(技能特效播放完后就回收到pool中,所以调用pause()不会有残留,此时不需要释放数据,在切换场景时真正释放特效数据),这时我从崩溃栈看到信息首先想到的修改应该是stop()修改pause造成的崩溃,我让程序同学帮我在iOS上挂机复现这个问题,果然连续2次挂机打怪都复现了,8-12分钟内必崩,崩溃栈和bugly上统计一样。

动画骨骼节点批处理

这时我立刻开始在iOS上直接修改编译测试,将pause()还原为stop(),继续测试… 意外的是问题依然存在,15分钟内挂机必崩溃闪退,然后又思考了下,stop()只是停止当前粒子更新和粒子发射,但数据没有清,然后继续修改代码:stop()调用后,立刻调用clear()再次测试,郁闷的是仍旧15分钟内挂机必闪退崩溃…再仔细看了下播放特效的代码上下逻辑处理,找不出问题,平时的崩溃率绝对没有这么高,仔细回想了下,这2天还剩余唯一的改动就是添加了对 ParticleSystem本地引用缓存,于是直接在iOS上修改为播放完后立刻本地引用置空,编译,更新到真机测试…一直测试了30多分钟,40多分钟都没有再闪退崩溃,哪怕改回pause()调用,也没有再崩溃了…这个测试结果有点让我意外,当时没有细想,立刻正式修改热更新到外网…果然外网的崩溃率第二天的记录再下降,但仍然存在,但我心里已经知道问题了,因为还剩余UI特效播放未处理(技能特效和UI特效我们是划分开的,技能有高低配设置,初始化解析不同),同样修改UI特效之后,闪退崩溃几率继续下降,一直降低到1-2%,剩余的崩溃仍旧是UI粒子系统相关的,主要是部分UI功能业务层未主动调用回收特效的接口导致。

这次对外测试结束后,我再回头看看崩溃信息,意外地发现让我最头痛的mono崩溃数据终止在28号,也就是在我28号修改mono代码之后就再也没有报崩溃在libmono.so “Abort message: ‘* Assertion at mini-arm.c:2634, condition `pdata.found == 1’ not met” 这个堆栈数据,回忆了下,以前低概率崩溃本质就是UI粒子系统导致的,有部分业务层逻辑未主动调用释放接口的,而mono-arm.c崩溃行 g_assert (pdata.found == 1) 断言阻断了继续向上层抛出堆栈信息…

我们的Unity版本是5.6.5P4,为什么缓存粒子系统组件不立刻释放会导致崩溃未知,可能是Unity的底层Bug,也可能真的是我们对粒子系统组件ParticleSystem逻辑上下调用有问题。

感谢yangyonggen@UWA问答社区分享了该经验,欢迎大家转至社区交流: https://answer.uwa4d.com/question/5becf477a1dae055a7c051b7

Shader

Q:自定义Shader在安卓手机上正常,在iOS上出现异常, 伴随一大堆的警告,而且资源会都变成黑色。

动画骨骼节点批处理

A1:第一行提示不完整,应该是说是没有顶点Shader;

第二行提示Pass都被移除了;

第三行提示没有可用的Subshaders或者Fallbacks;

总结起来,就是Shader是个空Shader,不可用。所以进行了替换,表现就是黑色,而不是材质丢失。

没用过ShaderForge,但是看过几眼美术同学从ShaderForge导出来的Shader,包含有关于平台的编译选项,大概是编译选项不对,要检查下ShaderForge编译选项设置。

感谢赵林@UWA问答社区提供了回答

A2:首先切换到iOS平台,选择出错的Shader,有可能会显示Shader is not supported on this GPU,点击Compile and Show Code,应该会显示“Compile errors generating this shader.”

如果是这样的话,说明你用了Graphics API不支持的Feature。

感谢凯奥斯@UWA问答社区提供了回答
该问答来自UWA问答社区,欢迎大家转至社区交流: https://answer.uwa4d.com/question/5c07c21b28c4e32cba3192b8

帧率

Q:最近跑一个项目,在真机上无法超过30帧,看了耗时是只是十几毫秒。代码里没有对Application.targetframerate的限制。是什么原因呢?

可能是开了垂直同步限帧30帧那一档,垂直同步修改为60帧那一个,或者关闭垂直同步,用Application.targetframerate自己限帧。

感谢赵林@UWA问答社区提供回答,欢迎大家转至社区交流: https://answer.uwa4d.com/question/5c04d886a7bd4622df98d6f0

UI

Q:多语言下,如何做Text组件大小和文本长度的适配?同一段文本,同一字体大小,不同语言下其长度(文字个数)和文字大小(像素宽高)不同,那么如何防止文本超出Text组件显示范围?如何保证视觉效果合理(文字不会太小也不会太大,位置不会太偏)?有哪些自动化的方案?

首先应该根据一种语言规划好文本框的大致大小,建议根据英语来规划,汉字有时候两个字,翻译成其他语言就是一长串。英语较为折中。

一种方式是固定好文本框大小,Bestfit,设置好最小和最大的字体,如果不拓展Bestfit,这种就有点粗暴。我们之前的项目就是这么粗暴;另一种方式是用ContentSizeFitter,可以计算出单个字符的大小,根据自己设定的最大最小值,通过扩展脚本可以动态的实现水平和垂直的扩展。

一般来说,肯定逃不掉特别极端的,所以再扩展个脚本处理这种非常特殊的。

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

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

官网:www.uwa4d.com

官方技术博客:blog.uwa4d.com

官方问答社区:answer.uwa4d.com

官方技术QQ群:793972859(原群已满员)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript DOM编程艺术 (第2版)

JavaScript DOM编程艺术 (第2版)

[英] Jeremy Keith、[加] Jeffrey Sambells / 杨涛、王建桥、杨晓云 等 / 人民邮电出版社 / 2011-4 / 49.00元

JavaScript是Web开发中最重要的一门语言,它强大而优美。无论是桌面开发,还是移动应用。JavaScript都是必须掌握的技术。W3C的DOM标准是开发Web应用的基石。已经得到所有现代浏览器的支持,这使得跨平台Web开发成了一件轻松惬意的事。 本书是超级畅销书的升级版,由倡导Web标准的领军人物执笔,揭示了前端开发的真谛,是学习JavaScript和DOM开发的必读之作。 本......一起来看看 《JavaScript DOM编程艺术 (第2版)》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具