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

【PR Unityアセットストア】パブリッシャーセール開催中!

凍った川や湖が表現できるマテリアルやシェーダーのアセットIce World がクーポンコード「NATUREMANUFACTURE2024」で無料でゲットできます
7月25日 23:59まで

Ice World

はじめに

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

マテリアルとは?

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

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

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

マテリアルを作成しよう

マテリアルは、プロジェクトビューで右クリック > Create > Material から作成できます。

Screenshot

マテリアルをオブジェクトに設定する

作成したマテリアルをオブジェクトにドラッグ&ドロップします。ヒエラルキーか、インスペクターか、シーンビューに直接ドラッグ&ドロップするだけです。

マテリアルの色をインスペクターから変えてみよう

マテリアルのインスペクターのAlbedoから、色を変えることができます。

このように、エディター上では色を自由に変えられますが、スクリプトからどのように変えるのかを紹介します。

マテリアルの色をスクリプトから変える方法

方法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);
        }
    }
}

色の指定方法

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

タイトルとURLをコピーしました