Hi, I’m still pretty new to unity and I am having a bit of an issue. I’m trying to get a list of objects to fade out by setting the alpha value in their TextMeshPro component’s color to 0 by doing a loop to lower the value of it by 0.01 every loop. This is what I have:
foreach (var btn in _titlebuttons) // iterate through the objects
{
var tmp = btn.transform.GetChild(0).GetComponent<TextMeshPro>(); // get the textmeshpro components
var a = tmp.color.a; // get the current alpha value
if (a > 0) // check if alpha is bigger than 0
{
a -= 0.01f; // subtract 0.01 from alpha
tmp.color = new Color32(1, 1, 1, (byte)a); // set the new color value
Debug.Log(a); // log output of a
}
This code is in a function that checks what game the state is in and manages code for when in that state, and that function is called every frame.
(looks like this):
The way I imagine this working is once the state is changed, the title screen buttons fade out and that’s that, however in the game they just disappear immediately and the console outputs 0.99 4 times before stopping.
I know I could just use a canvas group to do the same thing but I find the unity GUI system a hassle to work with, and some effects I want to do like simply moving an on screen spinning cursor to the button being hovered over doesn’t work because I can’t get the name of the object I’m hovering over no matter how hard I try, so I’m trying to just instantiate everything inside of code.
I’d really appreciate either an easier way to do menu GUI or help solving this issue because I’ve been trying to get the menus working for weeks to no avail.
The gui isn’t that hard to work with, especially compared to the old days.
The issue is you’re using a foreach loop and from what I can see, possibly not within a coroutine, since you don’t have any yields in there.
If you don’t have a yield inside a loop, the loop is going to run until complete. It will never yield to allow any visual updates. Which means it enters the loop, does it’s thing until the loop ends, exits the loop before it allows any visual changes, which from the viewers point of view is not a gradual fade.
You can do exactly what I said and add a yield, but I suggest a tweening engine such as LeanTween or DoTween. Both are free on the asset store and learning one will help you so much when dealing with stuff like fades, gui animation, etc.
As for the other issue. Implementing OnMouseOver or OnPointerEnter, should help make those sorts of thing much easier.
Issue with OnMouseOver/OnPointerEnter is I need the object’s name in order to reference the object later in the code to move the visual cursor next to it. Every time I attempted to do that I got null. I’ll try putting it in a coroutine and adding a yield though and see if that works.
Also my issue with seeing the GUI as a hassle in the editor is the fact that things are reliant on said object not only being in the editor but also enabled. When I was trying to make the transition from the title screen to the game setup screen for example it’d fail due to the canvas not being enabled when I tried to enable it. Issues like that is why I decided to make everything instantiate inside the code, so I’d always have a reference to the object even if its disabled in the scene.
I tried everything I could think of but couldn’t fix it. Anyways that was another issue entirely that lead to me instantiating everything in code, not the problem I’m looking to solve here.
I tried making the fade into a coroutine that looks like this:
[...]
foreach (var btn in _titlebuttons)
{
var tmp = btn.transform.GetChild(0).GetComponent<TextMeshPro>();
StartCourotine(FadeText(tmp, tmp.color.a, false));
}
[...]
private static IEnumerator FadeText(TextMeshPro obj, float a, bool up) // get object, get whether it should fade in or out
{
// fade in
if (up)
{
if (a < 1)
{
a += 0.01f;
obj.color = new Color32(1, 1, 1, (byte)a);
Debug.Log(a); // log
}
}
else
{
if (a > 0)
{
a -= 0.01f;
obj.color = new Color32(1, 1, 1, (byte)a);
Debug.Log(a); // log
}
}
yield return null; // no idea if this is why it is not working
}
I’m probably doing this wrong but its still disappearing instantly and I’m still seeing 0.99 in the console a couple of times before it stops.
You’re welcome to keep trying combinations, and when you have exhausted all the mis-implementations of coroutines (which aren’t even suitable in the first place) and finished “thinking of everything,” the actual steps you need to fix your actual problem are awaiting you in this post.
Oh that’s… actually really simple. But wasn’t the point of the coroutine to get it to fade while in a foreach loop? Do I need to find a way to somehow fade each one without a foreach loop?
private static void FadeText(TextMeshPro obj, float a, bool up)
{
float end;
if (up)
end = 1;
else
end = 0;
obj.color = new Color32(1,1,1,(byte)Mathf.MoveTowards(a, end, 2.0f * Time.deltaTime));
}
but its still disappearing instantly due to that foreach loop, but I don’t know any other way to fade out all the objects other than manually referencing every single one which seems tedious and inefficient
Also I apologize if I seem a bit dense, I’m trying my best to understand here.
Great, set that aside gently, go back to my post and implement the basic three parts:
currentValue
desiredValue
an Update() function to move them together every frame.
Seriously. Just get that working FIRST.
NOW: use Debug.Log() to PROVE that the value smoothly goes from 0 to 1 and back to 0, and test for debug keypresses (such as A, B) to trigger desired to 0 and 1.
Until that works, don’t even CONSIDER your buttons. Just put them out of your mind.
Once you have actually implemented the three parts above, only then can you now route the current value over to where you need it.
Okay so I instantiated a test object that has a TextMeshPro component, and set it to where pressing A would try to fade it in with the FadeText function, and D would fade it out.
Despite this not being in a foreach loop, the text disappears instantly as well, and attempting to fade it back in with A fails. It would also seem that pressing A before pressing D also makes it disappear. Not sure what is causing this.
The way I’m trying to do current and desired is by just using the current alpha value (obj.color.a) and the desired value being set by whether the function is called with a true or false parameter. (true = desired value is 1, false = desired value is 0, A calls it with true, D calls it with false.)
Pressing A does increase the value to 1, although it happens instantly and again for some reason does not make the object reappear…
I’ve been stuck on this for the past hour, I can’t seem to get the fade in/out to work at all for anything. I keep rewriting how I’m setting the initial current value, how its checking for what to set it to, how it actually sets the value to the desired value, no matter what I try the console output either is complete random numbers that aren’t even close to what they should be, 0.99, 0.01, and never does it just smoothly transition to the number. I don’t get what I’m doing wrong here.
You’re only calling FadeTest once, when the key is down, so MoveTowards is also only going to fire once as well. You need to move logic that you want to execute every frame to an appropriate place, like Update.
I managed to sort of get it working but i think i’m just going to attempt to get it working with unity’s gui system again rather than instantiating everything via code.