- 游戏架构:核心技术与面试精粹
- 樊松阳
- 1449字
- 2020-08-28 01:55:24
1.1 绑定事件响应
请列出为UI控件绑定事件响应的方法,并分析不同方法之间的优劣。
问题分析
面对问题时,最重要的是确定它的边界。对于这个问题,如何绑定当然是关键,但UI控件的范围也很重要。不是所有的UI控件都能绑定事件,但能绑定的也不是只有按钮,至少还应包含:
◎ 拖动条
◎ 输入框
◎ 开关
◎ 滚动区域
当然还有千千万万我们实际工作中用到的自扩展控件。这里不受限于按钮的点击事件,我们用按钮、开关、拖动条三种控件来举例说明。
搭建测试环境
在面临一个新问题时,我们通常会在一个独立的场景中搭建测试环境,来快速验证我们的逻辑是否正确。
在这个例子中,我们要在界面中创建三个控件,并摆放到屏幕的中心。创建方法是用右键快捷菜单添加各种控件,相信大家都知道如何操作。如果不熟悉,也可以通过网络很容易地查到。类似的基础操作不是本书的重点,因此针对此类情况,后文大多一笔带过。创建好的界面大概如图1.1所示。
图1.1
接着,编写处理函数。在Unity中,创建名为TestEvent.cs的代码文件,并在场景中创建一个空的GameObject,将TestEvent脚本挂载到GameObject上。打开
TestEvent.cs,输入如下代码:
using UnityEngine; using System.Collections; using UnityEngine.UI; public class TestEvent : MonoBehaviour { public void OnBtnClick() { Debug.Log("Btn Click"); } public void OnToggleChange(bool isOn) { Debug.Log("Toggle Is "+isOn); } public void OnSliderChange(float rate) { Debug.Log("Slider cur is "+rate); } }
现在我们已经配置好了测试环境,接下来就看看如何绑定响应。
绑定响应
从操作层面看,绑定响应的方式有两种,但它们的核心是相同的。
1)组件中添加
在Inspector界面中,可以直接在组件中通过拖曳的方式完成绑定。我们以Button控件为例,演示如何操作。
首先创建一个空的GameObject,命名为MyTrigger,在它上面挂载刚刚创建的TestEvent脚本。
完成上述步骤后,在Hierarchy面板中选中Button,然后在Inspector面板中找到Button组件。不难发现在组件的下方有个区域名为OnClick,单击这个区域下方的“+”,就可以添加一个点击事件的处理设置,效果如图1.2所示。
图1.2
然后将刚刚含有TestEvent脚本的GameObject拖到下方的“None (Object)”中。操作完成后,单击右侧的“No Function”按钮,在下拉菜单中找到TestEvent.OnBtnClick。操作成功,效果如图1.3所示。
图1.3
单击“Runtime Only”按钮进行测试,即可发现在Console中可以输出“Btn Click”。
用相同的方式,可以为Toggle和Slider添加相同的事件处理。添加好后,运行游戏,分别测试控件响应,控制台输出如图1.4所示。
图1.4
2)代码中添加
代码添加的方式要简单得多,打开TestEvent脚本,在类中添加如下代码:
public Button m_btn; public Toggle m_toggle; public Slider m_slider; void Start() { m_btn.onClick.AddListener(OnBtnClick); m_toggle.onValueChanged.AddListener(OnToggleChange); m_slider.onValueChanged.AddListener(OnSliderChange); }
然后在Inspector中将三个控件分别拖到脚本的对应位置上即可。
优劣比较
以笔者的经验来看,绝大多数程序员喜欢用代码添加的方式。
一般来说,程序员不会轻易动别人的代码,但预设很可能被其他人更改。当Bug出现时,不使用代码编写绑定,开发人员心里就很没底,无法确认是否是自己的原因。
笔者认为如果有很好的框架支撑,编辑器设置绑定的方式也是可取的。就好像没人质疑在Unity 3D中,Start函数是否会在一开始调用一样。如果有一目了然的绑定显示,并且有稳固的框架支撑,那么在编辑器中绑定也没什么不好。在编辑器中绑定有个优势,就是支持动态更新。由于绑定关系存储在预设中,因此意味着整个逻辑可以跟随AssetBundle更新。如果C#代码逻辑写错了,只更新预设也是白费力气,但可以在基类里提供一个默认的出错处理,以便最大限度地降低影响。
总结
绑定响应的方式有两种;在组件中添加和在代码中添加。它们的核心相同,都是通过代理来回调自己的函数。组件绑定的操作更友好,但容易被人更改。代码绑定的优点是更稳定,而且能更灵活地控制监听的时间点,缺点是逻辑编译在代码中,最好有健全的框架支持,以防止出现使用问题。例如,重复绑定的处理函数,忘记移除的绑定,等等。
扩展问题
(1)有没有办法克服代码绑定的缺点?
(2)既然大家都倾向于使用代码绑定,那么组件绑定的存在有意义吗?