简体   繁体   English

在 Unity (C#) 中隐藏和显示按钮

[英]Hide and show a button in Unity (C#)

I have a button (in UI), that I want to hide sometimes (but show again later), which means that it shouldn't show anymore and I shouldn't be able to click it.我有一个按钮(在 UI 中),有时我想隐藏它(但稍后再显示),这意味着它不应该再显示并且我不应该能够单击它。 The only solution I found (that has actually managed to hide the button), is SetActive() .我找到的唯一解决方案(实际上已经设法隐藏了按钮)是SetActive()

But in Update() , when I do SetActive(false) (the true/false is controlled with the variable wave_happening in my script), Update() doesn't run anymore, so I can't set it to true again.但是在Update()中,当我执行SetActive(false) (真/假由脚本中的变量wave_happening控制)时, Update()不再运行,因此我无法再次将其设置为 true。 When I do GameObject.Find("Start Button").SetActive(true) in another script, it just gives me a NullReferenceException (Object reference not set to an instance of an object).当我在另一个脚本中执行GameObject.Find("Start Button").SetActive(true)时,它只会给我一个 NullReferenceException (对象引用未设置为对象的实例)。

This is my Update() function:这是我的Update() function:

void Update() {
    wave_happening = enemy_spawner_script.wave_happening;
    Debug.Log(wave_happening);
    transform.gameObject.SetActive(wave_happening);
}

Is there a solution to stop this problem, or another way to hide a button?是否有解决此问题的解决方案,或其他隐藏按钮的方法?

I'm fairly new to Unity and C#, so I don't know very much.我对 Unity 和 C# 还很陌生,所以我不太了解。

You can try disabling the button's rendering and functionality components:您可以尝试禁用按钮的呈现和功能组件:

GetComponent<Button>().enabled = false; // remove functionality

GetComponent<Image>().enabled = false; // remove rendering

Now, adding that to your Update function, plus a few changes for performance so you are not enabling/disabling every single frame, only when needed:现在,将其添加到您的更新 function 中,加上一些性能更改,因此您不会仅在需要时启用/禁用每一帧:

private bool isShowing = true; // or whatever your default value is

void Update() {
    wave_happening = enemy_spawner_script.wave_happening;
    Debug.Log(wave_happening);
    
    if(wave_happening != isShowing) {
        show(wave_happening);
        isShowing = wave_happening;
    }
}

void show(bool isShow) {
    GetComponent<Button>().enabled = isShow; // remove functionality

    GetComponent<Image>().enabled = isShow; // remove rendering
}

It's really difficult to do this well.要做好这件事真的很难。 Lots of issues arise:会出现很多问题:

  • Inevitably the button will be in a H or V layout group, and, as a basic software engineering issue of course you want it to work whether or not it is in a layout group, as that layout detail may be changed by your designers as the project goes on.不可避免地,按钮将位于 H 或 V 布局组中,并且,作为一个基本的软件工程问题,您当然希望它无论是否在布局组中都能正常工作,因为您的设计师可能会更改布局细节作为项目继续进行。 For this reason it is a really good idea, as the OP initially guessed, to simply use .SetActive出于这个原因,正如 OP 最初猜测的那样,简单地使用.SetActive是一个非常好的主意

  • But then you have the problem of the button being off so Update is not running.但是你遇到了按钮关闭的问题,因此Update没有运行。 A simple solution is just to put the button in a wrapper.一个简单的解决方案是将按钮放入包装器中。 That is to say, simply in a UI Panel .也就是说,只是在一个 UI Panel中。 Have the button manager script on that wrapper rather than on the button per se.在该包装器上而不是在按钮本身上拥有按钮管理器脚本。

Then you just have a pretty Property on the manager script,然后你在管理器脚本上有一个漂亮的属性,

public bool Showme
{
    etc...

and then you can just go...然后你就可以 go ...

void Update()
{
    Showme = enemy_spawner_script.wave_happening;
}

Can't get simpler looking code.无法获得更简单的代码。

  • However, if you use a wrapper Panel.但是,如果您使用包装面板。 It is true that you have to be pretty expert at using the UI (particularly the auto sizing stuff) to make it work just the way you want.确实,您必须非常擅长使用 UI(尤其是自动调整大小的东西)才能使其按照您想要的方式工作。 But, that's part of building Unity expertise unfortunately.但是,不幸的是,这是构建 Unity 专业知识的一部分。 :/ :/

  • The concerns about performance is... truly ridiculous.对性能的担忧……真的很荒谬。 There's no difference between Unity's raw code "checking a boolean" and yourself "checking a boolean". Unity 的原始代码“检查布尔值”和您自己的“检查布尔值”没有区别。 However for sure as a matter of style it's crap to poll it in Update.但是,可以肯定的是,在更新中轮询它是一种风格问题。 (Note that in point "B" just above, if you're going to have heinously ugly "anti-polling" code, bury it in that Property.) (请注意,在上面的“B”点中,如果您要使用极其丑陋的“反轮询”代码,请将其埋在该属性中。)

And then...接着...

"Trick" solution “绝招”解决方案

  • A tip in Unity UI is you can add a CanvasGroup anywhere. Unity UI 中的一个提示是您可以在任何地方添加CanvasGroup Why would you do this?你为什么要这样做? It allows you to FADE the whole thing, which, is often a quick solution to achieve what you want.它使您可以淡化整个事物,这通常是实现您想要的快速解决方案。

Hence..因此..

public CanvasGroup fader;

and then..接着..

void Update()
{
    fader.alpha = enemy_spawner_script.wave_happening ? 1f : 0f;
}

and you're done!你就完成了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM