【Unity】動画の再生-背景透過(クロマキー)でゲームを演出

当サイトで紹介する商品・サービス等の外部リンクは、アフィリエイト広告を含む場合があります。
スポンサーリンク
本記事を読むと以下の実行ができます

タイマーストップの時間に応じて、表示される動画を変える。

ゲーム内で動画を使う場面は、オープニングエンディングのカットシーンチュートリアルの説明プレイヤーの進捗や成績を示すグラフィックスなど
多岐に渡って利用します。

また、アニメ―ションやエフェクトを作成するとUnity内やBlenderで作る必要があるので、
プログラミング以外にもタスクが増えて作品完成までの道のりが遠くなってしまいます。

しかし、これらの効果を動画で補うことで簡単に追加することができます。

本記事はUnityの標準Video Playerの使い方について解説します。

本記事は次の人におすすめ
  • Unityで動画を再生したい。
  • Video Playerの使い方を知りたい。
  • アニメ―ションやエフェクトを追加したい。
Udemyで学習する
スポンサーリンク

Video Player

Unityで動画を再生するためのcomponent「Video Player」があります。
VideoPlayerコンポーネント」と「VideoPlayerスクリプト」を使うことで高度な動画の制御が可能になります。

Raw Image

ゲームオブジェクトを用意する必要があります。
空オブジェクトでもよいですが、動画の比率調整がしやすい「RawImage」をおすすめします。
Hierarchyウィンドウのプラスから「UI>Raw Image」を選択します。

Inspectorウィンドウの「Rect Transform」でPos(xyz)を0にして、
Width(幅)、Height(高さ)を動画のサイズと合わせてください。

動画がゲーム枠に収まらない場合は、Gameビューの項目からサイズ変更をしてください。

Unityの画面のサイズを変更方法を紹介しています。

「RawImage」のInspectorウィンドウ下部にcomponentの項目があるので、
「Video Player」を追加してください。

「Video Clip」に動画をアタッチしてゲームを再生しても動画が再生されません
原因は、RawImageに「Texture」が存在しないからです。

Render Texture

次にprojectウィンドウのプラスから「Render Texture」を追加して、
RawImageにアタッチすると、動画をgameビューに表示できます。

動画の比率はTextureのsizeに依存するので、動画の幅(Raw Image)と同じにしてください。
以上までの工程を進めて、動画を表示することができます。

動画のクロマキー

動画をアニメーションや演出、エフェクトとして使いたい場合は、
映像から背景の色を分離(クロマキー)する必要があります。

Unityは、Shaderを使うことでクロマキーが可能です。
projectウィンドウから「Shader>Standard Surface Shader」と「Material」を追加してください。

Shaderをクリックして、デフォルトから次のコードに編集してください。

Shader "Custom/ChromaKeyShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _ChromaKeyColor ("Chroma Key Color", Color) = (1,1,1,1)
        _Threshold ("Threshold", Range(0, 1)) = 0.1
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float4 _ChromaKeyColor;
            float _Threshold;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                if (distance(col.rgb, _ChromaKeyColor.rgb) < _Threshold)
                {
                    discard;
                }
                return col;
            }
            ENDCG
        }
    }
}

MaterialのInspectorウィンドウからShaderを紐づけます。
Shaderの項目のPassは、上記のコードの先頭になります。
要するに、「”Custom/ChromaKeyShader”」を選択して下さい。

スポイトでクロマキー色を抽出して、Sliderを動かします。
背景色は少し残っていますが、数字が大きすぎると抽出が強くなってしまいます。

完全なクロマキーには限界があり、境界部分はくっきりと色分けする必要があります。
白と黄緑は明度が近いので、緑を濃くするとよりきれいにできるかと思います。

ビデオをスクリプトで制御

動画をスクリプトで制御していきます。
プログラム例として、体内時計ゲームを作成します。

プログラム内容
  • Step1
    Startボタンで時間を進める。

  • Step2
    StartからStopに切り替わったボタンで時間が止まる。

  • Step3
    4.5秒~5秒以内で停止すると成功動画。それ以外は失敗動画。
  • Step4
    2.5秒以降は、表示される文字は非表示。

ソースコード

using UnityEngine;
using TMPro;
using UnityEngine.Video;

public class VideoController : MonoBehaviour
{
    public GameObject[] sets;   // 正解不正解の表示-オブジェクト
    private VideoPlayer[] videoPlayers; // 正解不正解の表示-ビデオ
    public TextMeshProUGUI timeText;
    public TextMeshProUGUI buttonText;
    private float timer = 0f;   // 制限時間
    private bool isTimeUp = true;   //タイマーストップ

    void Start()
    {
        // ビデオを保存しているオブジェクトをビデオにする
        videoPlayers = new VideoPlayer[sets.Length];
        for (int i = 0; i < sets.Length; i++)
        {
            videoPlayers[i] = sets[i].GetComponentInChildren<VideoPlayer>();
            videoPlayers[i].loopPointReached += OnVideoEnd;  // ループしない
        }

        Next();
    }

    void Update()
    {
        if (!isTimeUp)
        {
            timer += Time.deltaTime; // タイマーを更新
            timeText.text = timer.ToString("F1"); // 残り時間を表示

            if (timer > 2.5)
            {
                timeText.gameObject.SetActive(false);
            }
            if (timer > 5)
            {
                timeText.gameObject.SetActive(true);
                isTimeUp = true;
                sets[1].SetActive(true); // 不正解を表示
                videoPlayers[1].Play(); // 動画を再生
            }
        }
    }

    public void ToggleTimer()
    {
        isTimeUp = !isTimeUp; // タイマーの状態を切り替える
        buttonText.text = isTimeUp ? "Start" : "Stop"; // ボタンのテキストを更新
        timeText.gameObject.SetActive(true);

        if (isTimeUp)
        {
            if (timer >= 4.5f && timer <= 5f)
            {
                sets[0].SetActive(true); // 正解を表示
                videoPlayers[0].Play(); // 動画を再生
            }
            else
            {
                sets[1].SetActive(true); // 不正解を表示
                videoPlayers[1].Play(); // 動画を再生
            }
        }
    }

    void OnVideoEnd(VideoPlayer vp)
    {
        Next();
    }

    public void Next()
    {
        buttonText.text = "Start";
        isTimeUp = true; // タイマーを停止
        timer = 0f; // タイマーをリセット
        timeText.text = timer.ToString("F1"); // 残り時間を表示
        // 動画非表示
        foreach (GameObject set in sets)
        {
            set.SetActive(false);
        }
    }
}

UdemyでUnityを学習

Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。

\Unityの学習から収益化の方法はこちらから!/

ビックセール開催中(12月19日まで)
対象のコースが1500円から(最大95%OFF)

多彩な講座から自分に合った講座を探そう!

最大95%OFF

終了まで

時間




解説

  • 名前空間

「using UnityEngine」:Unityのクラスや機能を使用するために必要です。
「using TMPro」:TextMesh Proを使用するために必要です。
「using UnityEngine.Video」:ビデオをスクリプトで扱うために必要です。

TextMesh Proの導入方法や日本語表示など詳しく紹介しています。
  • フィールド(メンバ変数)

「sets」: 正解と不正解の表示に使用されるゲームオブジェクトの配列です。
「videoPlayers」: ゲームオブジェクト内の VideoPlayer コンポーネントを格納する VideoPlayer 配列です。
「timeText」: 制限時間を表示するための TextMeshProUGUI コンポーネントです。
「buttonText」: ボタンのテキストを更新するための TextMeshProUGUI コンポーネントです。
「timer」: 制限時間を保持するための変数です。
「isTimeUp」: タイマーが停止しているかどうかを示すブール値です。

  • Startメソッド

ゲームオブジェクト内の VideoPlayer コンポーネントを取得し、
ループポイントが到達したときに OnVideoEnd メソッドを呼び出すイベントハンドラーを設定します。
Next メソッドを呼び出して最初の設定を行います。

  • Updateメソッド

タイマーが停止していない場合、タイマーを更新し、画面に小数第1位まで表示します。
2.5秒以降は文字を非表示、5秒超えると失敗になります。

  • ToggleTimerメソッド

UIボタンを押すことで処理されます。
タイマーの状態を切り替え、ボタンのテキストを更新します。
タイマーが再開された場合、制限時間が一定の範囲内にあるかどうかを確認し、
それに応じて正解または不正解のビデオを再生します。

  • OnVideoEnd メソッド

ビデオ再生が終了したときに呼び出され、Next メソッドを呼び出して次の設定を行います。

  • Next メソッド

制限時間やタイマーをリセットし、ビデオを非表示にします。

実演

各々の変数にゲームオブジェクトをアタッチします。
規定の時間内でボタンを押すと、成功に相当する動画が再生されます。

対して、時間外にボタンを押す。
5秒超過してしまった場合は失敗に相当する動画が再生されます。

動画再生が終わるとNextメソッドが発動して、
動画は非表示になり、時間は0秒に戻ります。

動画を再生するときに、別の動画が一瞬映ることがあります。
しかし、Hierarchyウィンドウのオブジェクトに注目すると、無効の状態です。

テクスチャーに動画を写すときに、
前の動画最後の1フレームと動画最初が残っていることが原因だと考えられます。

対処法は表示したいものを消して、透過する背景を少し動画に残しておけばよいでしょう。

まとめ

Unityで動画を再生するには、componentからVideo Playerを使います。
また、クロマキーで背景を透過させることでアニメ―ションとして利用できます。

Udemyで学習する

この記事を書いた人

プロフィール

アリッシア

                 

大学4年間で何か胸を張れるスキルを身に着けたくて当サイト運営を始めました。
現在、大学院に進学するか就職するか迷いながら勉強しています。
詳しいプロフィールはこちら

Contact icon

contact

X icon

X

Instagram icon

Instagram

Note icon

Note

スポンサーリンク
Unity
フォローする
タイトルとURLをコピーしました