Newb Variable Accessibility Question

The unity docs say that the alpha component of the Color struct is public:

Shouldn’t this mean that I can set the alpha as below? Instead I get the error in editor: “Cannot modify a value type return value of `UnityEngine.UI.Graphic.color’. Consider storing the value in a temporary variable”

Methinks I am missing something basic - thanks in advance for letting me know.

public class FadeInOut : MonoBehaviour {

public Image panel;
public float StartTime;
public float EndTime;
public float FadeDuration;

void Start () {
panel.color.a = 1.0f;
StartCoroutine (RunFadeInOut (StartTime, FadeDuration, EndTime));
}

}

@johan21

Hi there, you have to set the whole color value at once as it’s a struct, then pass it your color field:

Color newColor = new Color(1f,0f,0f,1f); // red color with alpha of one

panel.color = newColor;
1 Like

Try this (out of my head, might be wrong):

Color panelColor = panel.color;
panelColor.a = 1.0f;
panelImage.color = panelColor;

Should work. When you have a compound object like this color that has lots of parameters, it’s best to create a temporary variable copying that object, changing temporary variable’s parameters to your liking and then assigning it back to where you want it.

1 Like

Thanks eses - I worked out that would solve the problem.

But I’m not understanding the principle of why I can’t set it as shown. The example in the unity docs below even shows the alpha being set individually. Its a public variable?

I’ve got my two C# textbooks on hand and looking up structs and access, and I’m still not getting it.

public class ExampleClass : MonoBehaviour {
    public Color color = Color.white;
    void Example() {
        color.a = 0;
    }
}

@johan21

Actually in this case it’s more related to fact that Unity material color is getter/setter that only accepts Color as parameters .

So you have to take color (which is a struct), then modify it, and pass it back to material color. You can manipulate struct like like in you example, but you can’t modify (set) material color (one channel at time) like that, you have to first modify color struct, then pass it back to material.

  void Start ()
  {
  renderer = GetComponent<Renderer>();

  // Get color struct
  Color col = renderer.material.color;

  // Manipulate color struct
  col.r = 0f;
  col.g = 0.7f;
  col.b = 0f;
  col.a = 1.0f;

  // Reassign color - works
  renderer.material.color = col;

  // Try to change material's color - won't work
  // renderer.material.color.a = 0f;
  }

You can absolutely set the value of alpha on a Color variable. However, as the error you mentioned says you cannot modify the Color directly off an Image.
This is because Color is a struct, meaning when you access panel.color you don’t get a reference to the Color variable, you get a copy of it.
So, as @eses and @Meri said, you have to create a temporary variable to copy it to, modify the values of that, and then re-assign it.

In short, you can do

color.a = 0f;

you can’t do

panel.color.a = 0f;

Too see the same behaviour from your own code, try this:

public class TestScript : MonoBehaviour {

    public struct TestStruct {
        public int a;
    }

    public TestStruct testStruct { get; set; }

    void Start() {
        testStruct.a = 15;
    }
}

It won’t compile!

In the background, that property would turn into pretty much this:

public class TestScript : MonoBehaviour {

    public struct TestStruct {
        public int a;
    }

    privateTestStruct testStruct_backer;
    public TestStruct testStruct_Getter() {
        return testStruct_backer;
    }
    public TestStruct testStruct_Setter() {
        testStruct_backer = testStruct_Setter;
    }

    void Start() {
        testStruct_Getter().a = 15;
    }
}

Structs are passed by value. This means that the getter (and in the same way, panel.color) sends you a copy of the struct. Changing a value on the copy will, of course, not do anything to the original.

C# could have let your code compile, and just let you set the .a on the copy of panel.color. Of course, then your code would do nothing, and it would be really hard to understand why it didn’t do anything. So this is much better.

1 Like

Baste, Gizmoi, Eses and Meri

Thank you so much for taking the time to explain this - you guys rock.

I kept thinking that structs are passed by value and that must somehow be relevant - the penny has finally dropped that even in attempting to access/modify/read the original struct in any way shape or form I am only ever getting a copy.

Baste particular thanks for explaining the logic about why it prevents the code from compiling.

Cheers fellas.

1 Like