Material not being detected as part of my gameobject

I have a script that sends a raycast from a camera to my mouseposition. This ray then collides with moving gameobjects. I want the material for these gameobjects to darken when the objects are clicked so i wrote this if statement:

        if (hit.transform.gameObject.tag == "correct" && Input.GetKey(KeyCode.Mouse0))
        {
            hit.transform.gameObject.GetComponent<Renderer>().material.color = new Color(hit.transform.gameObject.GetComponent<Material>().color.r/2f, hit.transform.gameObject.GetComponent<Material>().color.g/2f, hit.transform.gameObject.GetComponent<Material>().color.b/2f, hit.transform.gameObject.GetComponent<Material>().color.a);
            var col3 = hit.transform.gameObject.GetComponent<MeshCollider>();
            col3.enabled = false;
            score++;
            validsources.text = "Valid Sources: " + score.ToString();
        }

Despite all of my gameobjects having materials assigned to them, this error is yielded every time I try and click on a gameObject:

When I looked at the documentation, gameObject.GetComponent().material was the correct way to reference a material, so I’m not entirely sure what is going wrong.

This is what is wrong, this doesn’t exist.

If you want to modify a color of the existing material, it is a reference type, which you get with

var mat = gameObject.GetComponent<MeshRenderer>().sharedMaterial;

(mat is of type Material so you can type Material mat = as well)
Then you can change its properties

mat.color = getMultipliedColor(mat.color, .5f, alpha: 1f);

where

Color getMultipliedColor(Color color, float value, float? alpha = null)
   => new(color.r * value, color.g * value, color.b * value, alpha.HasValue? alpha.Value : color.a * value);
4 Likes

I’m so sorry to waste your time with this, It works perfectly once I replicate how I referenced the material property in the first part of line 3. Error on my part :frowning:

Please don’t write ultra-verbose code like this!

Use variables to avoid repeating yourself (and needlessly causing the CPU to do the same thing over and over again) to keep the code readable:

    var hitGo = hit.transform.gameObject;
    if (hitGo.tag == "correct" && Input.GetKey(KeyCode.Mouse0))
    {
        var color = hitGo.GetComponent<Material>().color;
        color = new Color(color.r / 2f, color.g / 2f, color.b / 2f, color.a);
        hitGo.GetComponent<Renderer>().sharedMaterial.color = color;
       
        var collider = hitGo.GetComponent<MeshCollider>();
        collider.enabled = false;
        score++;
        validsources.text = "Valid Sources: " + score.ToString();
    }

The IDE actually helps you do this sort of thing. Select something like hit.transform.gameObject and use the “refactor” feature to “introduce variable” and it should do the right thing and replace all identical occurances with the variable.

1 Like

@CodeSmile You’ve neatly unpacked an error that was living there :slight_smile: Yes verbosity is bad.

2 Likes

Thanks for letting me know :slight_smile:

I’m still pretty new to Unity and C# and haven’t been paying attention to almost anything to do with optimization, how does not storing what I write in a variable put more pressure on the CPU? I was under the impression it was just a quality of life thing until now. I thought variables were just keywords that represent the value/thing assigned to them, but do the same thing as what they are assigned to be.

Say you need some info from Patrick but as you call your friend Sandy picks up the phone. She then runs to the garden, asks Patrick, and returns with that info.

You hang up.

Then you call again, ask Sandy to ask Patrick to give you the same information again. She can’t recall for certain either so she walks in the garden, asks Patrick, returns to you with that info.

You hang up.

Then you call again, asking for the same information …

You can see how repeatedly asking for the same information is putting pressure on anything or anyone? :wink:
You could have simply wrote it down, and look it up when you forgot again. That is much faster than calling someone to fetch something that isn’t readily available to them either. It also doesn’t have your friends worry about your mental health.

That’s only the information query and storage aspect. More importantly is exactly the quality of life: readability and maintainability of your code.

Aaaannd “debuggability”. Having such a long single statement, any error or issue in that line will just point you to that line and any of the 20 things you do in that line could cause the issue.

2 Likes

OMG… don’t do this to yourself!!

That is pure madness! MADNESS I say!!

If you have more than one or two dots (.) in a single statement, you’re just being mean to yourself.

Putting lots of code on one line DOES NOT make it any faster. That’s not how compiled code works.

The longer your lines of code are, the harder they will be for you to understand them.

How to break down hairy lines of code:

http://plbm.com/?p=248

Break it up, practice social distancing in your code, one thing per line please.

“Programming is hard enough without making it harder for ourselves.” - angrypenguin on Unity3D forums

“Combining a bunch of stuff into one line always feels satisfying, but it’s always a PITA to debug.” - StarManta on the Unity3D forums

I think i see what your saying, so a variable doesn’t really represent the exact reference, but rather the value or thing returned by it? And that it’s in both my CPU and my best interests to consolidate references down to variables?

You may want to ask AI about this. They give good answers for fundamental questions like these, probably better than most.

Because it’s a bit more tricky.
A variable holds a value. It’s always just a value. It could be “true” (a bool) or literally a string containing the text “true” or it could be the value 1 where “true” is actually a keyword that internally has the value of 1.

But then there’s this thing called pointers (references). This is more or less and index into memory for the CPU to look up where that data is. Anything that is a class in C# will be a reference when assigned to a variable, components for instance. You can have multiple variables referencing the same component, and you can modify that single instance of the component through each variable.

But then you have value types, which are struct types. Here, each variable is actually a copy of the original.

I’ll stop here, AI can do a better job. Much better than perhaps a complete technical rundown of what variables are.