【Unity】 マテリアルの色をスクリプトから変更させる方法!

はじめに

マテリアルの色はインスペクターから変更させることができますが、ゲーム中にスクリプトから動的に変更させる方法について解説します。

マテリアルとは?

金属やプラスチック、木や絵柄など、物体の材質・見た目を決めるのがマテリアルです。このパラメーターを変化させることで、物体の見た目を自由に変化させられます。

プロジェクトビューを右クリックして、Create > Materialから新規作成できます。

Unityのヒエラルキーから新規作成したオブジェクトにもマテリアルが割り当てられていますが、デフォルトでは色の変更ができないようになっています。新規作成したマテリアルをドラッグ&ドロップして設定しておきましょう。

マテリアルの色を変える方法

方法1. マテリアルを切り替える

わかりやすい方法としては、色を変えたマテリアルを別途作成しておき、マテリアルごと切り替えるという方法です。

以下は、切り替えるスクリプトの例です。スペースキーを押したら、あらかじめインスペクターで設定しておいたマテリアルに切り替わります。

using UnityEngine;

public class ColorChange : MonoBehaviour
{
    [SerializeField] Material mat = default;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            this.GetComponent<MeshRenderer>().material = mat;
        }
    }
}

メリットとしては、色だけでなく、マテリアルのプロパティ全てを変えられることです。ただし、さまざまな色に変えたいとなったら、マテリアルの数もその分増えてしまうので、容量が大きくなってしまいます。

方法2. プロパティを直接変更する

マテリアルのプロパティを直接スクリプトで変更する方法です。これなら、マテリアル数を増やさずに色を変えることができます。

スクリプトから変えるには、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);
        }
    }
}

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” を使う際はマテリアルが自動的にコピーされて作成されるので、注意して使いましょう。

ゲーム作りがゼロから学べるおすすめ動画はこちら
3D
umiをフォローする
umi studio blog
タイトルとURLをコピーしました