Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Anymeese · Sep 07, 2014 at 12:36 AM · materialmaterialscomparecomparison

Check if Material of a gameObject == a material variable (instance)?

I want to have a function basically like so...

 public Material m;

 private matEnum getWhichMat(GameObject GO)
 {
     if(GO.material is the same as m)
         return matEnum.firstMat;
     else if... (check all mats.  I have 4 or 5 total)
 }

...however I can't figure out how :/ Right now I'm comparing the COLORS of both materials, but I want to be able to compare the materials themselves and the function work. I've tried both == and .equals with various things like MeshRenderer, material, etc

EDIT: Tons of extra details:

I have 4 materials in a folder (which happen to be the same except for different colors, but the whole point of fixing this is so I can use different materials). My script has 4 public Material variables, which I then dragged the materials in my project view to the spots on the inspector.

Then in the script, I have this function to check and see if the gameobject sent in as a parameter is using one of those 4 materials, and if so, which one (just a long if-else chain)

I have tried 1) go.renderer.material == m, 2) go.renderer.material.Equals(m), 3) go.renderer.sharedMarerial == m, and 4) go.renderer.sharedMaterial.Equals(m), and none of them worked

I also added debug.log lines to make sure that nothing is counted as null, and all 5 are showing up as values (not null). However the game object's material says the name of the material it's using followed by "(Instance)" (so "marker_hex_green (Instance)")


EDIT 2:

Okay here is my full work as I have it:

First, context. My game is a tile-based game where units move onto different nodes. Nodes have 4 colors: white (default, should never be shown), green (only used when buying a new unit), blue (used to indicate movement), and orange (used to indicate attacking).

In my script, I have these variables, and the script modeled after your most recent post/edit:

 public enum hexMats { defaultt = 0, landing = 1, move = 2, attack = 3 };
 public Material defaultHexMat; //dragged the white material to this in the inspector
 public Material landingHexMat; //dragged the green material to this in the inspector
 public Material moveHexMat; //dragged the blue material to this in the inspector
 public Material attackHexMat; //dragged the orange material to this in the inspector

 /// <summary> Returns the (scriptName).hexMats enum that the node's material currently is. </summary>
 public hexMats getNodeMatEnum(TileNode n)
 {
     if (n.gameObject.GetComponent<MeshRenderer>())
     {
         if (n.gameObject.renderer.sharedMaterial == defaultHexMat)
             return hexMats.defaultt;
         else if (n.gameObject.renderer.sharedMaterial == landingHexMat)
             return hexMats.landing;
         else if (n.gameObject.renderer.sharedMaterial == moveHexMat)
             return hexMats.move;
         else if (n.gameObject.renderer.sharedMaterial == attackHexMat)
             return hexMats.attack;
         else
         {
             Debug.Log("Found the mesh component, but did not compare to any of the 4 mats.  Returning default");
             Debug.Log("your material is " + n.gameObject.renderer.sharedMaterial);
             return hexMats.defaultt;
         }
     }
     else
     {
         Debug.Log("No Mesh Component Found! Returning default");
         return hexMats.defaultt;
     }
 }

RESULTS: I tried this on a green hex, and my console showed that it DID fine the mesh component, but not any of the 4 mats. It showed "your material is marker-hex-green (Instance) (UnityEngine.Material)". Note that marker-hex-green is the material i dragged to landingHexMat in the inspector. (it's actually two underscores, not hyphens, but the forums have weird formating for underscores..)

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
4

Answer by Eric5h5 · Sep 07, 2014 at 01:05 AM

Use if (go.renderer.sharedMaterial == m). Accessing renderer.material creates an instance so it's not useful for this.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Anymeese · Sep 07, 2014 at 01:53 AM 0
Share

Did not work :(

avatar image
3

Answer by hangemhigh · Sep 07, 2014 at 01:03 AM

You should explain more of what you are trying to do. For me, it seems like you are trying to check if GO object has the same material with M material? To compare a material to a game object, you must use gameobjectName.renderer.material. Code is below.

 public Material m;
 
 bool hasThesameMaterial(GameObject GO){
   if(GO.renderer.material==m){  //checks if they are the same material
    return true;  //returns true if the same material.
   }else{
    return false; //returns false if different material
 }
 }

To call this function, you do

 GameObject myobject; //the object you want to check if the material is the same with 'm'
 
 if(hasThesameMaterial(myobject)){
 //it has the same material
 }else{
 //it DOESNT have the same material
 }


EDIT 1:

Then in the script, I have this function to check and see if the gameobject sent in as a parameter is using one of those 4 materials, and if so, which one (just a long if-else chain)

 public Material m1;
  public Material m2;
  public Material m3;
  public Material m4;
 
     string hasAnyOfTheMaterials(GameObject GO){
    if(GO.GetComponent<MeshRenderer>()){ //Get Mesh Component
   
       if(GO.renderer.sharedMaterial==m1){  //checks if it has material 1 material
        return "m1";  
       }
       else if(GO.renderer.sharedMaterial==m2){    //checks if it has material 2 material
        return "m2";  
       }
       else if(GO.renderer.sharedMaterial==m3){    //checks if it has material 3 material
        return "m3";  
       }
      else if(GO.renderer.sharedMaterial==m4){    //checks if it has material 4 material
        return "m4";  
       }
       else{
       return "none";   //it has none of the materials
       }
     }
 }else{
 Debug.Log("No Mesh Component Found");
 }

To call the function

 GameObject myobject; //the object you want to check if it has the same material.
 if(hasAnyOfTheMaterials(myobject)=="none"){
 Debug.Log("it has none of these materials");
 }

You can also do this.

 string currentMaterial = hasAnyOfTheMaterials(myobject);
 Debug.Log("Game object's material is "+currentMaterial);

What if you want to know the ACTUAL name of the material. The name of given to the material?

Replace

 return "m1";, return "m2";, return "m3";, and return "m4";  

with

 return GO.renderer.sharedMaterial.name;

It will return the exact name the material is using. Leave "none" alone so that you can use it to determine which if the material it is using is not one of those 4 materials. If you want it to return the name of the material when it is none of those 4 materials, then replace

  return "none";

with

  return GO.renderer.sharedMaterial.name;

You can also replace

 return "none";

with

  return null;

so now you can do

 if(!hasAnyOfTheMaterials(myobject)){
 //It doesn't have any of the materials
 }else if(hasAnyOfTheMaterials(myobject)=="m1"){
  //It has Material 1
 }.................... so on


NOTE: When you use renderer.material, it creates a new instance. With renderer.sharedMaterial, it accesses the main material. Even when you read a material with renderer.material, it creates a new instance. When you modify a material's color, texture or other of its properties with renderer.material, it creates a new instance. So use renderer.sharedMaterial when you want to change a material, read or compare material value. I forgot to say that in the beginning.

And the most important change I made here is get the MeshRenderer Component "GO.GetComponent()". That might help. If not, post your code, post what you have now and I will replicate the problem on my side.

EDIT 2:

  It showed "your material is marker-hex-green (Instance) (UnityEngine.Material)". Note that marker-hex-green is the material i dragged to landingHexMat in the inspector. (it's actually two underscores, not hyphens, but the forums have weird formatting for underscores..)

You are correct. Unity doesn't like the underscores and changes it to hyphens. It is not suppose to have 'Instance' in the name. Like I said before, Instance means that that you used something like

 n.gameObject.renderer.Material....

instead of

 n.gameObject.renderer.sharedMaterial....

in your code. Check carefully in all your C# code files.

UnityEngine.Material will normally be there if you use gameObject.renderer.sharedMaterial.

To remove (UnityEngine.Material) from the name in Debug.Log(), use

  Debug.Log("your material is " + n.gameObject.renderer.sharedMaterial.**name**);

instead of

 Debug.Log("your material is " + n.gameObject.renderer.sharedMaterial);

The variable "name" will actually return the name of the object's material.

You need to change your naming Convention

From 50 Tips For Working with unity Use Pascal case, like this: ComplicatedVerySpecificObject. Do not use spaces, underscores, or hyphens

I think that this applies to File Naming too as Unity replaces underscores with hyphens.

So your "marker-hex-green" variable should be named something like markerHexGreen or markerHexGreenMat. Do the same for other Materials. The Mat reminds you that this is a Material.

After doing these above, run it and see if Instance is still showing. If yes, then you must chose one of the following temporary ways to fix it for now and look for a better way after.

Method 1: Create a public GameObject then pass the GameObject to the function. Remove

 gameObject

from

 n.gameObject.renderer.sharedMaterial == attackHexMat

Below is what you are suppose to have. Make sure to assign an object to the GameObject through the Editor.

 public GameObject myColorObject;
 
 public hexMats getNodeMatEnum(GameObject n)
 {
 if (n.GetComponent<MeshRenderer>())
 {
 if (n.renderer.sharedMaterial == defaultHexMat)
 return hexMats.defaultt;
 else if (n.renderer.sharedMaterial == landingHexMat)
 return hexMats.landing;
 else if (n.renderer.sharedMaterial == moveHexMat)
 return hexMats.move;
 else if (n.renderer.sharedMaterial == attackHexMat)
 return hexMats.attack;
 else
 {
 Debug.Log("Found the mesh component, but did not compare to any of the 4 mats. Returning default");
 Debug.Log("your material is " + n.gameObject.renderer.sharedMaterial);
 return hexMats.defaultt;
 }
 }
 else
 {
 Debug.Log("No Mesh Component Found! Returning default");
 return hexMats.defaultt;
 }
 }

The "Instance" word should now disappear. If true, then the program should work. If not, then use Method 2.

Method 2: Revert back to the code you had before you performed Method 1. The "Instance" in the material name is probably the problem. Since the word "(Instance)" appears next to the material name but not before it. You can use string manipulating to counter it. Below is your code.

 string whatToUse = "";
 
 public enum hexMats { defaultt = 0, landing = 1, move = 2, attack = 3 };
 public Material defaultHexMat; //dragged the white material to this in the inspector
 public Material landingHexMat; //dragged the green material to this in the inspector
 public Material moveHexMat; //dragged the blue material to this in the inspector
 public Material attackHexMat; //dragged the orange material to this in the inspector
 
 
 public hexMats getNodeMatEnum(TileNode n)
     {
         if (n.gameObject.GetComponent<MeshRenderer>())
         {
 
             //Call Function and See if it contains the word '(Instance)'
     if(containsInstance(n.gameObject.renderer.sharedMaterial.ToString())){
                 //It has '(Instance in the name)'
                 //Let's modify Our name
                 whatToUse = " (Instance) (UnityEngine.Material)";
     }else{
                 whatToUse = " (UnityEngine.Material)";
             }
 
 if (n.gameObject.renderer.sharedMaterial.ToString() == defaultHexMat.name+whatToUse)
                 return hexMats.defaultt;
 else if (n.gameObject.renderer.sharedMaterial.ToString() == landingHexMat.name+whatToUse)
                 return hexMats.landing;
 else if (n.gameObject.renderer.sharedMaterial.ToString() == moveHexMat.name+whatToUse)
                 return hexMats.move;
 else if (n.gameObject.renderer.sharedMaterial.ToString() == attackHexMat.name+whatToUse)
                 return hexMats.attack;
 else
             {
 Debug.Log("Found the mesh component, but did not compare to any of the 4 mats. Returning default");
 Debug.Log("your material is " + n.gameObject.renderer.sharedMaterial.name);
                 return hexMats.defaultt;
             }
         }
         else
         {
             Debug.Log("No Mesh Component Found! Returning default");
             return hexMats.defaultt;
         }
     }
 
     //Important Function
 //Checks if the word contains an instance or not
     bool containsInstance(string materialName){
         if(materialName.Contains(" (Instance) ")){
             return true;
         }else{
             return false;
         }
     }

That's it. It should work weather there is an Instance or Not.

Logic Behind Method 2:

 Two possible names returned by Unity during run time
 marker-hex-blue (UnityEngine.Material) = GO.renderer.sharedMaterial
 marker-hex-blue (Instance) (UnityEngine.Material) = GO.renderer.sharedMaterial
 We decide which one of these below to use for comparing depending on the value in     the  code above.

 marker-hex-blue (UnityEngine.Material) = m1 
 marker-hex-blue     =  m1.name 

 if go.renderer.sharedMaterial contains Instance
   add space at the end then add '(Instance)' at the end of each all material variable name followed by space then '(UnityEngine.Material)'
  else
   only add space followed by '(UnityEngine.Material)' at the end of all material variable name.
 
 //Remember we are not really modifying the name, we are concatenating it temporary and then comparing it.
   To really modify the name of the variable, we would do m1.name = "modified";
    But we never should do that and that's not what we are doing. It should now work. 

NOTE: I added a Zipped File I used for debugging and the fixing the '(Instance)' problem. You can download to see a working example.

Phew. That took long.

link text


helpdelete.zip (153.1 kB)
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image hangemhigh · Sep 07, 2014 at 01:03 AM 0
Share

And for this to work, you must have material assigned to $$anonymous$$aterial m from the editor or through code so that it wont compare null to GO.renderer.material....

avatar image Anymeese · Sep 07, 2014 at 02:05 AM 0
Share

I have 4 materials in a folder (which happen to be the same except for different colors, but the whole point of fixing this is so I can use different materials). $$anonymous$$y script has 4 public $$anonymous$$aterial variables, which I then dragged the materials in my project view to the spots on the inspector.

Then in the script, I have this function to check and see if the gameobject sent in as a parameter is using one of those 4 materials, and if so, which one (just a long if-else chain)

I have tried 1) go.renderer.material == m, 2) go.renderer.material.Equals(m), 3) go.renderer.shared$$anonymous$$arerial == m, and 4) go.renderer.shared$$anonymous$$aterial.Equals(m), and none of them worked

I also added debug.log lines to make sure that nothing is counted as null, and all 5 are showing up as values (not null). However the game object's material says the name of the material it's using followed by "(Instance)" (so "marker_hex_green (Instance)")

avatar image hangemhigh · Sep 07, 2014 at 04:16 AM 0
Share

I edited the answer. Start from where it says EDIT 1.

avatar image Anymeese · Sep 07, 2014 at 08:56 PM 0
Share

Thank you very very much for your help. I'm still having the issue, so I updated my post with all my work. Start from Edit 2

avatar image hangemhigh · Sep 08, 2014 at 06:11 AM 0
Share

Go To Edit 2. I modified my Answer.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

24 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to compare 2 materials? 2 Answers

My foreach or the Resources.LoadAll Is not getting the information I need 2 Answers

Exporting textures from B2M3 to Unity 5 0 Answers

Is there a shader that cycles through textures 1 Answer

Material Property on Mesh Renderer Glitching in Animation 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges