【Unity】RenderTextureを使わないで等倍サイズで動画を再生する【VideoPlayer】


はじめに

現在作成中のスクリプトエンジンに動画再生機能を付けようとしてVideoPlayerを調べていたところ、等倍サイズで描画するのに少し手間取ったのでやり方を紹介します。

VideoPlayerにRenderTexture は必要ない

VideoPlayerをアタッチするとデフォルトでRenderModeがRenderTextureになっているのですが、これをAPI Onlyに変えることでVideoPlayer内部のtextureにレンダリングすることができます。
(ただしスクリプトを書くのが必須になってきます)
あと、スクリプトから再生するのでPlay On Awakeのチェックは外しておきます。

スクリプトを書く

RenderModeをAPI OnlyにしたVideoPlayerを使うにはスクリプトが必要なので作成します。
とりあえず名前はMovieImageにしました。

追加するパラメーター

動画を再生するVideoPlayerと、その描画先であるRawImageが必要です。

MovieImage.cs
[SerializeField]VideoPlayer videoPlayer = null;
[SerializeField]RawImage rawImage = null;

動画サイズにイメージサイズを合わせる

イメージのサイズを動画サイズと一致させるために、まずは動画サイズを取得できる状態にします。
それにはPrepareメソッドを使って、再生準備を行います。
VideoPlayerには再生準備が終わると呼び出されるprepareCompletedというイベントがあるのでそれを使用します。

MovieImage.cs
public void Play(VideoClip videoClip)
{
    // 動画の設定
    videoPlayer.source = VideoSource.VideoClip;
    videoPlayer.clip = videoClip;

    // 再生準備の開始
    videoPlayer.prepareCompleted += OnPrepareCompleted;
    videoPlayer.Prepare();
}

再生準備が終わったらVideoPlayerのtextureが使えるようになります。
rawImageにtextureをセットし、RectTransformのサイズをテクスチャのサイズに合わせます。

MovieImage.cs
void OnPrepareCompleted(VideoPlayer vp)
{
    // イメージに動画テクスチャをセットする
    rawImage.texture = videoPlayer.texture;

    // イメージサイズを動画と同じ大きさにする
    RectTransform rt = GetComponent<RectTransform>();
    rt.sizeDelta = new Vector2(videoPlayer.texture.width, videoPlayer.texture.height);
}

ちらつきの防止

このままでは再生準備の間RawImageの素の状態で描画されるため白くちらついてしまいます。
VideoPlayerには再生開始時に呼び出されるstartedというイベントがあるのでそれを利用して再生開始までrawImageを非表示にします。

MovieImage.cs
private void Awake()
{
    // 最初はイメージを表示しない
    rawImage.enabled = false;
}
MovieImage.cs
void OnPrepareCompleted(VideoPlayer vp)
{
    // イベントハンドラをセットして再生する
    videoPlayer.started += OnMovieStarted;
    videoPlayer.Play();
}
MovieImage.cs
void OnMovieStarted(VideoPlayer vp)
{
    // 再生が開始されたらイメージを表示する
    rawImage.enabled = true;
}

再生する

再生するには作成したスクリプトのPlayメソッドを呼びます。

MovieTest.cs
public class MovieTest : MonoBehaviour
{
    [SerializeField]MovieImage movieImage = null;
    [SerializeField]VideoClip videoClip = null;

    public void Start()
    {   // 動画を再生する
        movieImage.Play(videoClip);
    }
}

最後に

MovieImage.csの全文を添付しておきます

MovieImage.cs
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;

public class MovieImage : MonoBehaviour
{
    [SerializeField]RawImage rawImage = null;
    [SerializeField]VideoPlayer videoPlayer = null;

    private void Awake()
    {   // 最初は表示しない
        rawImage.enabled = false;
    }

    /// <summary>
    /// URLを指定して再生する
    /// </summary>
    public void Play(string url)
    {
        // 動画の設定
        videoPlayer.source = VideoSource.Url;
        videoPlayer.url = url;

        // 再生準備の開始
        videoPlayer.prepareCompleted += OnPrepareCompleted;
        videoPlayer.Prepare();
    }

    /// <summary>
    /// ビデオクリップを指定して再生する
    /// </summary>
    public void Play(VideoClip videoClip)
    {
        // 動画の設定
        videoPlayer.source = VideoSource.VideoClip;
        videoPlayer.clip = videoClip;

        // 再生準備の開始
        videoPlayer.prepareCompleted += OnPrepareCompleted;
        videoPlayer.Prepare();
    }

    /// <summary>
    /// 再生準備が完了した
    /// </summary>
    void OnPrepareCompleted(VideoPlayer vp)
    {
        // イメージに動画テクスチャをセットする
        rawImage.texture = videoPlayer.texture;

        // イメージサイズを動画と同じ大きさにする
        RectTransform rt = GetComponent<RectTransform>();
        rt.sizeDelta = new Vector2(videoPlayer.texture.width, videoPlayer.texture.height);

        // イベントハンドラをセットして再生する
        videoPlayer.started += OnMovieStarted;
        videoPlayer.Play();
    }

    /// <summary>
    /// 再生が開始されたときに呼ばれるイベント
    /// </summary>
    void OnMovieStarted(VideoPlayer vp)
    {
        // 再生が開始されたらイメージを表示する
        rawImage.enabled = true;
    }
}