Image.color stays White even though different color is set

Hey there,

in my project I’m creating several player characters for a turn-based couch game (think offline version of Super Mario Party). The most important stats of each player are displayed at the right side of the screen. That includes the name, current points, and its color. To do so, after creating the players, I generate the UI via code. For each player I generate an Info Panel and set its corresponding values.
The name and the initial points are displayed correctly, but the color always shows white. I’ve logged the code and the code line receives the correct color values, but the Image.color either doesn’t take the values or resets them to white at the end of the frame. Can someone explain to me why this happens and how I can solve this problem?

I’ll add some code elements below but because the “start off” signal is somewhere else entirely and a chain reaction of events eventually leads to this moment, I’ll skip some parts that seem irrelevant to me. I cann add them though, if necessary.

// PlayerManager
    private void CreatePlayers()
    {
        for (int i = 0; i < players.Length; i++)
        {
            GameObject playerGO = Instantiate(playerPrefab, position, rotation, parent);
            playerGO.GetComponent<PlayerInfo>().SetInfos(id, playerNames[i], color);
            playerGO.SetActive(false);

            playerCharactersByName.Add(playerNames[i], playerGO);
        }
        OnPlayersCreated?.Invoke(new List<GameObject>(playerCharactersByName.Values));
    }
// InfoDisplayManager is called by the OnPlayersCreated event
    private void InitWalletDisplays(List<GameObject> playerCharacters)
    {
        foreach (GameObject character in playerCharacters)
        {
            GameObject infoDisplay = Instantiate(infoDisplayPrefab, infoGrid);
            infoDisplay.GetComponent<InfoDisplay>().Setup(character);
        }
    }
// InfoDisplay
    public void Setup(GameObject playerCharacter)
    {
        nameText.text = playerCharacter.name; // this displays the correct name
        // grabbing the color from the material...
        Color c = playerCharacter.GetComponentInChildren<MeshRenderer>().material.color;
        // ... or the Info class leads to the same results
        Color c = playerCharacter.GetComponent<PlayerInfo>().PlayerColor;
        Debug.Log(c); // this prints the correct color RGBA values
        colorImage.color = c; // this image stays white
    }

The result looks like this. Capsule color and Player Info color are correct. The small bar on the left-hand side of the info panel is still white.

That’s an awful lot of GetComponent()-ing going on there… I’ll bet that somewhere in there you have a bug.

One example of a common bug with this crazy Ninja getcomponent stuff is you are changing the color of the Prefab on disk rather than the instance you created, or perhaps attempting to change a Material that is built in, for example, rather than setting a new instance on your character.

Either way, start printing names of what you’re operating against, and use the second argument of Debug.Log() so you can click on the thing and see what is being highlighted and changed.

Sounds like you wrote a bug… and that means… time to start debugging!

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.

Meanwhile…

Keep in mind that using GetComponent() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

Here’s the bare minimum of stuff you absolutely MUST keep track of if you insist on using these crazy Ninja methods:

  • what you’re looking for:
    → one particular thing?
    → many things?
  • where it might be located (what GameObject?)
  • where the Get/Find command will look:
    → on one GameObject? Which one? Do you have a reference to it?
    → on every GameObject?
    → on a subset of GameObjects?
  • what criteria must be met for something to be found (enabled, named, etc.)
  • if your code expects one instance and later you have many (intentional or accidental), does it handle it?

If you are missing knowledge about even ONE of the things above, your call is likely to FAIL.

This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

If you run into an issue with any of these calls, start with the documentation to understand why.

There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

It is ALWAYS better to go The Unity Way™ and make dedicated public fields and drag in the references you want.

Got it to work. For anyone wondering, it was something else entirely. To indicate who’s turn it is, I highlight the currently active player by highlighting his Info Panel. That includes scaling it up and making it a bit brighter. You can see that in the picture in the original post.
To achieve these effects, I’m using an external Tweening library: LeanTween. I just learned that by default, the library’s methods are called recursively on the objects children so by slightly changing the color of the panel it applied the same color to the player color image. To prevent this, you need to explicitly need to call setRecursive(false) at the end of your tween call.

1 Like