技术分享连载(七十七)

技术分享连载(七十七)

本期聚集话题:如何用脚本批量修改AnimatorController中各state的参数、检测UI重复事件、批量修改动画模块中的参数、动画曲线命名规范...


我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
UWA QQ群:793972859
UWA 问答社区:answer.uwa4d.com


动画

Q1:我需要修改Animator Controller中动画间的Transition信息(比如Duration),但AC较多,AC的状态也多,每次都手动修改非常耗时,请问有没有相关的API通过脚本来批量修改呢?

UnityEditor.Animations.AnimatorController (https://docs.unity3d.com/ScriptReference/Animations.AnimatorController.html) 可以获取Animator,其含有AnimatorController.layers (https://docs.unity3d.com/ScriptReference/Animations.AnimatorControllerLayer.html) 属性,通过该属性可以获取该Layer的StateMachine,然后获取state然后可以修改相关参数了。

参考代码:

    AnimatorController ac = Selection.activeObject 
                             as UnityEditor.Animations.AnimatorController;
            foreach(var layer in ac.layers){
                foreach(var curState in layer.stateMachine.states){
                    foreach(var transition in curState.state.transitions){
                        transition.duration = 0.0f;
                        transition.exitTime = 1.0f;
                    }
                }
            }

该问题来自UWA 社区,感谢 Switch.N提供了回答,大家可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59a51ecc2e6e640b53802414


UI

Q2:通常UGUI中的Button点击事件在代码中是通过onClick.addListener()来添加的。而且这种按钮的点击事件通常只会执行一次,如果添加了多次就会出现点击一次、按钮调用多次的事件函数。如果该Button只会添加一种事件,可以通过引用来判断是否添加了重复事件,从而不再重复添加相同事件。但是如果Button添加了多种点击事件,那么引用的方式就无效了。C#中的Delegate中有一个函数GetInvocationListD()可以获取此委托中的事件列表,从而剔除相同事件。然而让人头痛的是,我查看了Button的API似乎并没有暴露出此Button添加了的事件列表,所以没有办法剔除相同事件。不知道是否有什么办法可以解决这个问题?

onClick是一个ButtonClickedEvent对象,而ButtonClickedEvent的基类是UnityEventBase。UnityEventBase里有一个InvokableCallList对象,里面应该就存了事件列表,但这个是private的,可能只能尝试通过反射,去取里面的值来对比了。看上去并没有比较简便的方法。

也可以考虑扩展下Button组件,封装一个AddUniqueListener的接口,保留一下已经onClick.addListener的UnityEvent,然后每次Add前都先和这些UnityEvent做个对比,没有重复再进行onClick.addListener。

该问题来自UWA 社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/599514e96040df957a0a7497


动画

Q3:场景中放置一动画物体,原先正常进行动画,修改了物体Hierarchy某结点的名称,然后动画就异常了。打开Animation Window,发现动画曲线变为Missing。把物体名称改回后又恢复正常。我的疑问是动画Curve是与物体名称绑定的吗?如果是,如何修改动画物体的名称呢?

anim文件里有节点路径的:
比如:curve: serializedVersion: 2 m_Curve:

  • time: 0 value: {x: -0.187, y: -0.003, z: 0.062} inSlope: {x: 0, y: 0, z: 0} outSlope: {x: 0, y: 0, z: 0} tangentMode: 0
  • time: 0.93333334 value: {x: -0.187, y: -0.003, z: 0.062} inSlope: {x: 0, y: 0, z: 0} outSlope: {x: 0, y: 0, z: 0} tangentMode: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 path: Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1/Bip001 Neck/Bip001 R Clavicle/Bip001 R UpperArm/Bip001 R Forearm/Bip001 R Hand/Bip001 R Finger1

最好的方式就是让美术用新节点名再出一次动画。

感谢 UWA 问答社区的李先生提供了以上回答。

  • Animation Curve与动画物体是名称绑定的(名称包含其Hierarchy的Path,除去Root);
  • Animation Window中可以修改Curve的绑定名,可以将其更新为改名后物体的Path;
  • 如李先生所说Animation文件包含结点路径,可以“ForceText”后用文本工具来修改,比较方便;

感谢 UWA 问答社区的Saber提供了以上回答。

该问题来自UWA 社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59a7d5b5c8e4bc891d40cccb


UI

Q4:UI界面勾选Static是会节省一部分性能,但是如果我移动了某个设置为Static界面下的元素,这个界面还算是静态的么? 还是等运动的元素停下来后的界面才算静态的? 如果是这样,是不是我全部界面都设置静态就好了?

如果题主所指的“勾选static”是指GameObject右上角的Static框,这个Static和UI是无关的,不会对UI有影响;如果是NGUI的UIPanel上的Static选项,勾上之后,子节点中的UI元素是无法移动的(即使改了Transform,其图标位置也不会更新)。

该问题来自UWA 社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/598b1d79fb389f61434c5d4d


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