Highlighting a Selected 3D Object in Unity

September 3, 2019

Highlight and Selection

Materials and Color Change

REFERENCES:

Unity – Color.Lerp

By: Unity


Unity – Mathf.PingPong

By: Unity


Youtube – Mini Unity Tutorial – How To Select And Highlight Objects In Game Realtime With C#

Tutorial #1

By: Jimmy Vegas


Youtube – Color.Lerp Unity Once using Coroutines | No Update Function Beginner Tutorial

Tutorial #2

By: iUnity3Dtutorials


Unity Answers – Change color to multiple Materials in one gameObject?

By: Unity (lachesis)


I wanted to create a generic object highlight/selection feature for a project, so I turned to a method I found searching for highligting techniques online where you just change the material color of the currently selected object over time. This is a very simple (conceptually) and often used feature for showing a user what object is currently in focus. It would turn out that it’s a bit more complicated when you are working with models that have many different materials on separate children objects throughout them.

I started with the “Mini Unity Tutorial – How To Select And Highlight Objects In Game Realtime With C#” tutorial as the basis for this system. This was a good inspiration point, but not much more than that. Our project immediately had several major differences so the setup was quite a bit different. To start, we already had a reference to the Interface of the object to highlight, so we wanted to work with this same setup to determine which object is being selected. Our objects are also much more detailed models which are made up of many individual gameobjects which can have several materials each themselves.

Using this as a base, I decided I would setup a basic system that would change the color of an object from its original color to pure white, and then back to its original color. This would then loop until the object was deselected. Conceptually, this is exactly like the tutorial referenced above, but implementing it would take a lot more steps with our current setup.

Casting Interface as Monobehaviour for Gameobject Reference

I first looked into how to reference a gameobject with an existing reference to one of its used interfaces. I found that as long as the script implementing the interface inherits from Monobehaviour on some level, you can cast that interface reference as a Monobehaviour. You can then use this Monobehaviour reference to access that specific gameobject. I could then use this gameobject reference to access the Renderer component to alter the material color.

Looping Color Change for a Single Material

To test the base line of this feature, I wanted to get it working on one object with a single material. I did not like the way Tutorial #1 approached this, so I looked into some other ways to alter the color of a material and came across a Lerp interpretation. I have used Lerp a lot for positional systems, but I had not thought to use it with color, so this seemed perfect. This also makes it very easy to set a final color for the selected object to turn to which can be changed in the design process.

The standard Unity documentation for Lerp with Color also showed me a new Mathf method, which was PingPong. This lets you take a value and constrain it to a specific range between 0 and [length], where [length] is another input parameter. Once that value goes past the input [length], it begins to come back to 0 (as opposed to continuing to increase past [length]). This creates the “ping pong” effect where the input value goes back and forth between 0 and the given length. This works perfectly when lerping back and forth between two colors with an overall range of 0 to 1, where 0 is completely the first color and 1 is completely the second color.

Here is Unity’s basic color Lerp example:
using UnityEngine;

public class Example : MonoBehaviour
{
Color lerpedColor = Color.white;

void Update()
{
lerpedColor = Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time, 1));
}
}

Accessing Multiple Materials on a Single Gameobject

So now that I could change the color of a single material, I found that I would actually need to change the color of many materials at once, given the types of models we were working with. I have normally used Renderer.material in Unity to grab the single material on an object, but I found that there is also Renderer.materials, which returns all the instantiated materials of a single object in a single Material array. This is what I would need to get started on accessing all the materials I needed to control.

Since there are many children objects within these models, which can each have several materials of their own, I figured I would need to create some conglomerated Material array that could take on all of the materials while going through a large loop. This loop would need to be able to go through all of the children objects, and grab all the materials from each of those objects as it went through. Then finally, once all of the material references were obtained, we could Lerp all of the materials within this single combined array. Theoretically, it should give the intended result of becoming all white even with all of these materials because they should all be lerping with the same time input and the same final material color.

FINAL NOTES

  • Try Color.Lerp for changing an object’s color
  • Use Mathf.PingPong to have a value go back and forth within a range of 0 to some value
  • Renderer.Materials returns a Material array of all the materials on an object
  • An interface can be cast as a MonoBehaviour to access its gameobject if the interface inherits from MonoBehaviour
  • Complex models can use many different materials, so some basic Unity material techniques can be much more complicated to apply in these cases