- Home /
Else isn't working on material change
I'm referencing a Renderer variable called hsrend which is located in the HeaterStat script. On collision with the Power button, this PwrToggle script checks to see if the material on the Heater is Green [0] or Red [1] and toggles it. The materials Green, Red, and Gray (future use) are assigned to the array in this script through the Inspector window.
I get no errors on either script, but when I click Play and do a collision, only the IF is executed. It seems to be ignoring the ELSE. Any suggestions?
using UnityEngine;
public class PwrToggle : MonoBehaviour { public HeaterStat otherScript; public Material[] material;
private void OnTriggerEnter(Collider other)
{
// Green is 0, Red is 1, Gray is 3
if (otherScript.hsrend.material = material[1])
{
otherScript.hsrend.sharedMaterial = material[0];
Debug.Log("show Green");
}
else if (otherScript.hsrend.material = material[0])
{
otherScript.hsrend.sharedMaterial = material[1];
Debug.Log("show Red");
}
}
}
Answer by Bunny83 · Dec 10, 2019 at 09:01 PM
this line:
if (otherScript.hsrend.material = material[1])
actually assigns material[1] to your hsrend.material property since you used the assignment operator =
and not the comparison operator ==
. Anyways this comparison will not work either with the comparison operator since you read the material property. Reading or writing from / to the material property will automatically create an instance of the material which will be used by the renderer from now on. So that instance will never be equal to the material you originally stored in your materials array. Note that you correctly used sharedMaterial when you intentionally assign the material in the if body. However since you use material in the if statement you will create an instance anyways. So make sure you do always use sharedMaterial everywhere if you want to prevent the material instantiation.
if (otherScript.hsrend.sharedMaterial == material[1])
{
otherScript.hsrend.sharedMaterial = material[0];
Debug.Log("show Green");
}
else if (otherScript.hsrend.sharedMaterial == material[0])
{
otherScript.hsrend.sharedMaterial = material[1];
Debug.Log("show Red");
}
Note that instead of checking the actual material you might just store which material index you currently use. If you just want to cycle through all available materials you can simply do
int currentMat = 0;
private void OnTriggerEnter(Collider other)
{
currentMat = (currentMat + 1) % material.Length;
otherScript.hsrend.sharedMaterial = material[currentMat];
}
This line currentMat = (currentMat + 1) % material.Length;
will increase the currentMat index by 1 and wraps the index back to 0 if it exceeds the length of your material array. So if you only have 2 materials it will simply switch between 0 and 1. If you have 3 materials it would go 0, 1, 2, 0, 1, 2, 0, ... each time OnTriggerEnter is called.
Note that even when you do not simply want to cycle through the array but you need some kind of logic and the material represents the current state, using an integer or enum which you check is generally a better approach. So you can do things like
if (current$$anonymous$$at == 0)
{
current$$anonymous$$at = 1;
}
elseif (current$$anonymous$$at == 1)
{
current$$anonymous$$at = 0;
}
else
{
// maybe some other logic
}
otherScript.hsrend.shared$$anonymous$$aterial = material[current$$anonymous$$at];
I just realised that your variable is called "otherScript" (which btw is a terrible non descriptive name). If that script, the renderer and the "state" actually belongs to a different gameobject, you may want to rethink your logic here. If there's a script attached to that other gameobject, you want to handle the material / state change on that object itself and just have the trigger tell that script what to do / what happend and have the object react to it. So think about your responsibilities of your different objects. Having a completely seperate object hold a list of materials for a completely other object is just strange.