浏览Unity论坛和Q&A网站的一些答案,关于如何制作一个不可见按钮的回答并不适用,因为取消与按钮相关联的图像会使其无法工作。
如何解决这个问题,在保持不可见属性的同时允许按钮实际工作?
浏览Unity论坛和Q&A网站的一些答案,关于如何制作一个不可见按钮的回答并不适用,因为取消与按钮相关联的图像会使其无法工作。
如何解决这个问题,在保持不可见属性的同时允许按钮实际工作?
简洁版:
每个Unity项目都需要 Touchable.cs :
// file Touchable.cs
// Correctly backfills the missing Touchable concept in Unity.UI's OO chain.
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(Touchable))]
public class Touchable_Editor : Editor
{ public override void OnInspectorGUI(){} }
#endif
public class Touchable:Text
{ protected override void Awake() { base.Awake();} }
使用Unity的普通“创建按钮”编辑器功能
正如您所知,编辑器功能会自动为您添加两个组件。一个是Text
,另一个是Image
...
只需将它们都删除
将上面的脚本Touchable.cs
拖放到按钮上
完成了。就是这样。
它不会随着Unity升级而“腐烂”。
实际上,您可以通过将Touchable
拖放到任何.UI
中来使任何东西都具有按钮效果。
再也不需要“添加透明图像”来制作按钮了。
Unity忘记在OO链中抽象出一个“可触摸”的概念。
因此,我们开发者必须从Unity的类中“制作”自己的Touchable类。
这是面向对象编程(OO)中经典的“回填”问题。
当进行“回填”时,唯一的问题在于:它必须完全自动维护。只有一个好的解决方案Touchable.cs,所有人都在使用。
因此,在所有真实的Unity项目中,按钮看起来像这样:
第一步是使用Unity的 Button.cs
第二步是添加Touchable.cs
有些团队会创建一个编辑器功能“创建更好的按钮”,它仅仅是制作一个带有Button.cs + Touchable.cs的游戏对象。
假设您的UI面板非常复杂。因此它需要调整大小甚至具有动画效果。
事实上,您只需将“Button+Touchable”拖放到任何类似的对象上,它就能正常工作。
只需设置Button+Touchable以扩展填充其父级。就是这样。
在此示例图像中,“resume”和“quit”可以是任何东西。(动画、复杂的带有多个部分、文本、精灵、不可见的东西、堆栈 - 任何东西。)
在所有情况下,只需在其下面放置Button+Touchable,即可获得完美的按钮。
事实上:这种方法非常简单,您可能会将其用于甚至是简单的情况。
假设您的按钮只是一个微不足道的图像。使用图像并将Button+Touchable拖放到它上面要简单得多。(而不是使用编辑器中令人困惑和问题多多的“Button”功能。)
1) Unity的Button.cs
类非常好。
2) 但是
Touchable
的基类更改为 Graphic
并覆盖 protected void UpdateGeometry()
似乎可以很好地工作,同时减少了与 Text
相关的(尽管很小的)开销。public class Touchable:Graphic
{
protected override void UpdateGeometry() { }
}
我启动了Gimp(那个免费的编码器图形工具)。创建了一个新的图像(任何大小,我选择了10像素x 10像素),在创建对话框中从高级选项中选择其背景应该是透明的。保存文件。将其导出为png,并选择保存背景颜色。将其作为精灵拖入Unity中。将其放到按钮图形上。禁用按钮的文本组件。不需要代码...只需在Gimp中不要绘制任何东西(这是最困难的部分)。
我的第一个解决方案是像下面这样启用
和禁用
组件:
void showButton(Button buttonToShow, bool show)
{
Image bImage = buttonToShow.GetComponent<Image>();
Text bText = buttonToShow.GetComponentInChildren<Text>(); //Text is a child of the Button
if (bImage != null)
{
bImage.enabled = show;
}
if (bText != null)
{
bText.enabled = show;
}
}
但是那并没有起作用。如果按钮的image
和text
组件都disabled
,则按钮点击事件不会触发。其中一个必须enabled
才能发送点击事件。
解决方案是将image
和text
组件的alpha值设置为0以隐藏,再设置为1以重新显示。它们将被隐藏但不会被禁用,点击events
将会起作用。
public Button button;
void Start()
{
//Show Button
showButton(button, true);
//Hide Button
//showButton(button, false);
}
void showButton(Button buttonToShow, bool show)
{
Image bImage = buttonToShow.GetComponent<Image>();
Text bText = buttonToShow.GetComponentInChildren<Text>(); //Text is a child of the Button
if (bImage != null)
{
Color tempColor = bImage.color;
if (show)
{
tempColor.a = 1f; //Show
bImage.color = tempColor;
}
else
{
tempColor.a = 0f; //Hide
bImage.color = tempColor;
}
}
if (bText != null)
{
Color tempColor = bText.color;
if (show)
{
tempColor.a = 1f; //Show
bText.color = tempColor;
}
else
{
tempColor.a = 0f; //Hide
bText.color = tempColor;
}
}
}
Touchable
类-这是经典的“回填”OO情况。在“回填”整个问题时,它必须完全自动维护,幸运的是似乎有一个很好的解决方案。 - Fattie