不改变按钮大小,扩大点击区域

本期的问题是,如何扩大一个按钮(Button)的点击区域。

比如,将下图的 **TAP TO START**(点击开始游戏)的有效点击区域扩大到红色区域。

不改变按钮大小,扩大点击区域

遇到这样的需求,你会怎么去寻找方案呢?

每个问题,综合起来,都有这么几个解题思路:

1. 问有经验的人

2. 网上搜是否有类似问题

3. 看手册了解原理,然后自行设计方案

了解我的人,知道我比较喜欢自己琢磨。所以,我一般的思路是

1. 先看手册了解原理,然后尝试设计方案并测试。

2. 如果不行,第二选择是问Google。因为我们遇到的大部分问题,都不是新问题。只要你有一个明确的问题,用对关键字,一般都能找到**同病相怜**的人。

3. 最后,如果手册里讲的不清楚,而网上搜不到类似案例(这时候多半是因为我们用错了搜索关键字),那就去请教有经验的人

可惜的是,关于如何扩大按钮的点击区域,手册里并没有太多可以参考的……

如果不反编译Unity的代码,那么Unity对于我们就是一个黑盒。不过,对于一个设计合理的黑盒,我们依然可以从它的表现猜测出一些工作原理。

由于Unity是基于组件设计的,任何一个对象,或者说一个具体的功能,都是由一个或者多个组件配合实现的。

关于Button对象,我们可以看到它包含这么几个组件并猜测各自的具体工作:

  • RectTransform 管理位置和尺寸

  • CanvasRenderer 管理具体渲染

  • Image 管理显示内容

  • Button 管理按钮的逻辑

不改变按钮大小,扩大点击区域

对于我们要解决的问题,最重要的一个点:

**点击区域,由谁来决定。**

边看边猜

  • 负责逻辑的Button组件,没有看到任何点击区域相关的信息。

  • 负责位置和尺寸的RectTransform,由于有坐标/尺寸/旋转等信息,完全可以计算出可点击区域。

  • 负责显示的Image组件,虽然看起来只是用于显示,但是,有个 **Raycast Target** 这个奇怪的选项开关。

大胆测试

  • 测试 1.

修改RectTransform的Width和Height,扩大按钮的尺寸,点击区域就变大了。

然而,这带来了负面作用:

Image也被拉伸了。

不改变按钮大小,扩大点击区域

但是这离我们的目标近了一步,现在,问题转换为:

有没有可能不拉伸图片的同时,改变按钮的尺寸?

可以明确的是,

如果Image组件和Button组件在同一个GameObject里,这是不可能实现的,或者需要很复杂的技巧,比如修改渲染方式(修改shader之类),使Image维持原尺寸渲染。

那么,能否把Image作为子对象呢?

  • 测试 2.

1. 从Button对象上,移除Image组件,然后改变按钮尺寸。

简单点,直接勾掉,设为disable就可以了。

2. 添加一个Image的子对象。

不改变按钮大小,扩大点击区域

3. 为了保持按钮的状态切换效果(点击高亮什么的),需要把子GameObject对象(GameObject的名字叫Image)设置为Button的Target Graphic

不改变按钮大小,扩大点击区域

测试结果:

还是只有图片区域可以点击……

不改变按钮大小,扩大点击区域

但是,这不科学,对不对?

**按钮的尺寸明明扩大了,但是并没有生效。**

更过分的是,如果我把子对象去掉,这时候,整个按钮都没法响应点击事件了!

且慢,刚刚我们说Image组件有个奇怪的选项:

**Raycast Target**

不改变按钮大小,扩大点击区域

莫非,Image组件还负责**控制是否可以响应点击事件**?

  • 测试 3.

1. 保留测试2里的图片子对象

2. 保留Button对象里的Image组件,为了不影响显示,把Image的alpha(透明度)设为0

不改变按钮大小,扩大点击区域

测试结果:

成功!!

点击开始游戏图片外的区域,依然可以正常响应。

总结

于是,我们就得到了这个问题的解决方法:

  1. 将按钮图片分离出来,作为按钮的子对象,同时把它设置为Button组件的Target Graphic,因为我们需要根据按钮的状态切换不同图片。

  2. 把Button对象自身的Image组件透明度设为 0(用于响应点击事件)

  3. 改变Button对象的尺寸。这里要注意子对象的位置,可以将其设为不受父节点的尺寸变化而变化。(这个问题比较简单,留给大家自己试咯)

这是我自己测试出来的一个方案。实际上,如果你去Google,这个问题还有很多别的方案。