はじめに
マテリアルの色はインスペクターから変更させることができますが、ゲーム中にスクリプトから動的に変更させる方法について解説します。
マテリアルとは?
金属やプラスチック、木や絵柄など、物体の材質・見た目を決めるのがマテリアルです。このパラメーターを変化させることで、物体の見た目を自由に変化させられます。
Unityアセットストアでは、さまざまなマテリアルが用意されています。
マテリアルを作成しよう
マテリアルは、プロジェクトビューで右クリック > Create > Material から作成できます。
マテリアルをオブジェクトに設定する
作成したマテリアルをオブジェクトにドラッグ&ドロップします。ヒエラルキーか、インスペクターか、シーンビューに直接ドラッグ&ドロップするだけです。
マテリアルの色をインスペクターから変えてみよう
マテリアルのインスペクターのAlbedoから、色を変えることができます。
このように、エディター上では色を自由に変えられますが、スクリプトからどのように変えるのかを紹介します。
マテリアルをスクリプトから切り替えるには
スクリプトからマテリアルを切り替える方法を紹介します。色だけではなく、テクスチャーや質感自体も簡単に変えることができるのがメリットです。
以下は、マテリアルを切り替えるスクリプトの例です。スペースキーを押したら、あらかじめインスペクターで設定しておいたマテリアルに切り替わります。
using UnityEngine;
public class ColorChange : MonoBehaviour
{
[SerializeField] Material mat = default;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
this.GetComponent<MeshRenderer>().material = mat;
}
}
}
メリットとしては、色だけでなく、マテリアルのプロパティ全てを変えられることです。ただし、さまざまな色に変えたいとなったら、マテリアルの数もその分増えてしまうので、ゲームの容量が大きくなってしまいます。
複数のマテリアルに切り替えるには
先ほどは、マテリアルを1度切り替えるだけでしたが、今度は配列を使って複数のマテリアルに切り替えてみます。
スペースキーを押すたびに順番に異なるマテリアルに変更します。
using UnityEngine;
public class ColorChange : MonoBehaviour
{
[SerializeField] Material[] mat = new Material[3];
private int count = 0;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
this.GetComponent<MeshRenderer>().material = mat[count];
count++;
if(count == mat.Length)
{
count = 0;
}
}
}
}
マテリアルを3種類用意し、インスペクターに設定します。
実行すると、順番にマテリアルが変わっていきます。
マテリアルの色だけをスクリプトから動的に変えるには
色を変えるだけであれば、マテリアル自体を切り替えなくても実現できます。
色のプロパティを直接変更する(SetColor)
マテリアルの色プロパティを直接スクリプトで変更する方法です。これなら、マテリアル数を増やさずに色を変えることができます。
スクリプトから変えるには、MeshRendererコンポーネントを取得して、material.SetColor関数を使います。スペースキーを押したらマテリアルのプロパティから色を変えます。
using UnityEngine;
public class ColorChange : MonoBehaviour
{
[SerializeField] Material mat = default;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
this.GetComponent<MeshRenderer>().material.SetColor("_Color", Color.blue);
}
}
}
色の指定方法
色はColor.blueなどで簡単に指定できますが、詳しくはこちらをご覧ください。
RGBA値で設定したい場合は、あらかじめ色を定義しておき、それを使いましょう。
Color customColor = new Color(0.4f, 0.9f, 0.7f, 1.0f);
SetColorの第一引数について
上記の例では、SetColorの第一引数に、”_Color” と設定されていますが、マテリアルに設定されているシェーダーによって変わります。
確認するには、マテリアルのインスペクターから、右上にある設定をクリックし、Select Shaderを開きます。
すると、シェーダーが開き、色を設定するプロパティ名(_Color)が出てきます。
“_Color”でうまくいかなかったら、こちらを確認しよう!
.material の注意点
ここまで、.materialを使ってきましたが、これには一点気をつけるポイントがあります。
.materialは、元のマテリアルをコピーして自動的にマテリアルを新規作成しています。自動的に作成されたマテリアルはゲームオブジェクトを削除しても残り続けるため、そのままにしておくとメモリリークの原因となります。
メモリリーク (英: memory leak) とは、プログラミングにおけるバグの一種。プログラムが確保したメモリの一部、または全部を解放するのを忘れ、確保したままになってしまうことを言う。プログラマによる単純なミスやプログラムの論理的欠陥によって発生することが多い。
Wikipedia
メモリリーク対策1
対策としては、オブジェクト削除時にマテリアルもOnDestroyメソッドで削除します。
using UnityEngine;
public class ColorChange : MonoBehaviour
{
[SerializeField] Material mat = default;
Material material;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
material = this.GetComponent<MeshRenderer>().material;
material.SetColor("_Color", Color.blue);
}
}
private void OnDestroy()
{
if (material != null)
{
Destroy(material);
material = null;
}
}
}
メモリリーク対策2
いちいち毎回OnDestroy()でマテリアルを削除するのがめんどくさいという方もいるかと思います。
その場合は、.sharedMaterial を使うことで対策できます。”.material” を”sharedMaterial” に置き換えるだけです。これを使うと、コピーのマテリアルは作成せず、大元のマテリアルのパラメーターをいじることができます。
using UnityEngine;
public class ColorChange : MonoBehaviour
{
[SerializeField] Material mat = default;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
this.GetComponent<MeshRenderer>().sharedMaterial = mat;
}
}
}
マテリアルのテクスチャを変更するには
マテリアルのテクスチャをスクリプトから変更することもできます。詳しくはこちらをご覧ください。
おわりに
マテリアルの色を変える方法の紹介でした!スクリプトから1行で簡単に色を変えることができますが、”.material” を使う際はマテリアルが自動的にコピーされて作成されるので、多用する場合は注意して使いましょう。