Reputation: 219
Just started learning C# on Unity, been playing for awhile with mouseover and got it working to change objects color however.
I'm having problems trying to understand, how can i apply this to color AND textures AT THE SAME TIME, here's what i have been trying while following Unity´s material.texture and MouseOver
The following code works flawlesly
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseOver : MonoBehaviour
{
Color m_MouseOverColor = Color.yellow;
Color m_OriginalColor;
MeshRenderer m_Renderer;
void Start()
{
m_Renderer = GetComponent<MeshRenderer>();
m_OriginalColor = m_Renderer.material.color;
}
void OnMouseOver()
{
m_Renderer.material.color = m_MouseOverColor;
}
void OnMouseExit()
{
m_Renderer.material.color = m_OriginalColor;
}
}
The following code doesn't work at all, Notice Im not using any click/keyboard events so I attempted to remove the fors and this is what i came up with
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseOver : MonoBehaviour
{
Color m_MouseOverColor = Color.yellow;
Color m_OriginalColor;
MeshRenderer m_Renderer;
public Texture[] textures; //Create an array for the 2 textures
public Renderer rend; //Renderer required
void Start()
{
m_Renderer = GetComponent<MeshRenderer>();
m_OriginalColor = m_Renderer.material.color;
rend = GetComponent<Renderer>();
}
void OnMouseOver()
{
int index = 1;
index = index % textures.Length; //Limit array
rend.material.mainTexture = textures[index]; //Set texture Number 1 m_Renderer.material.color = m_MouseOverColor;
}
void OnMouseExit()
{
m_Renderer.material.color = m_OriginalColor;
int index = 2;
index = index % textures.Length; //Limit array
rend.material.mainTexture = textures[index]; //Set texture Number 2
}
}
I'm also setting 2 different textures for the object in the properties named as 1 and 2 so i'm quite sure im just not understanding how material.mainTexture works.
Upvotes: 1
Views: 1275
Reputation: 219
I finally fixed this by placing the textures in the Resources model and using the function Resources.Load , not it works as intended,
//https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseOver : MonoBehaviour
{
public Texture TexturaSencillaBlanca;
public Texture TexturaSencillaBlanca2;
//When the mouse hovers over the GameObject, it turns to this color (red)
Color m_MouseOverColor = Color.yellow;
//This stores the GameObject’s original color
Color m_OriginalColor;
//Get the GameObject’s mesh renderer to access the GameObject’s material and color
MeshRenderer m_Renderer;
void Start()
{
//Fetch the mesh renderer component from the GameObject
m_Renderer = GetComponent<MeshRenderer>();
//Fetch the original color of the GameObject
m_OriginalColor = m_Renderer.material.color;
}
void OnMouseOver()
{
Debug.Log("El color del objeto es AMARILLO.");
//Change the color of the GameObject to red when the mouse is over GameObject
if (m_Renderer.isVisible)
{ //Change Color of object on mouseHover
m_Renderer.material.color = m_MouseOverColor;
//Load Resources directly from folder
GetComponent<Renderer>().material.mainTexture = (Texture)Resources.Load("TexturaSencillaBlanca");
}
}
void OnMouseExit()
{
Debug.Log("El color del objeto es BLANCO.");
//Reset the color of the GameObject back to normal
m_Renderer.material.color = m_OriginalColor;
GetComponent<Renderer>().material.mainTexture = (Texture)Resources.Load("TexturaSencillaBlanca2");
}
}
Upvotes: 0
Reputation: 15941
So, there's a couple of things here:
1) Arrays are 0 indexed. Your index % textures.Length
will avoid an ArrayIndexOutOfBounds error, but you will constantly be confused why the first texture in your array is for mouse over when you told it to use the second (and vice versa). You should be using int index = 0;
and int index = 1;
respectively.
2) As mentioned in the comments by Eddge, Both GetComponent<MeshRenderer>()
and GetComponent<Renderer>()
are going to be pulling back the same component. MeshRenderer extends Renderer
.
However...
When you modify a material (either by changing the color or changing the texture) you create a new material instance. This might be messing your code up, but I don't think it should be (as you are not storing a reference to the material, but the renderer, which doesn't change, and your code looks very similar to the sample code in the docs). In either case, there's a nicer, cleaner way of doing things:
Simply create two materials you want to switch between, assign them to (new) fields in your class, and just change the material the renderer has.
rend.material = material[index];
MaterialPropertyBlock
MaterialPropertyBlock
allow you to use a single material and change the details for that one object without causing a new material instance to be created (and thereby cause less garbage collection, as well as keeping batches for the renderer: your game spends less time cleaning up RAM and it draws faster and you can have more than one object with this script attached without problems!)
There isn't any sample code on the documentation page, but it's pretty straight forward. The hard thing to figure out is the name of the first parameter for the setter functions (they are all of the format public void Set____(string name, T value);
). I can never remember off the top of my head which way it goes, but I'm pretty sure that it wants the name as seen by the shader ("_MainTex"
) rather than it's more friendly name ("MainTex"
), though it is not what you see in the editor ("Main Tex"
, with a space) and I don't currently have access to any of my projects where I've used it before.
Upvotes: 1