Unityでイベントシーンの作り方④タイムラインでローカライズされた字幕をつくる


前々々回の記事の内容を踏まえたうえでこの記事をご覧ください。

前々々回の記事でヒエラルキー上でcanvasをつくりその中にTextMeshProを作りました。このTextMeshProに文字を入れるとこのように書いた文字が表示されます。この文字をスクリプトから動的に変えることで字幕の数だけTextMeshProを用意しなくて済みます。ヒエラルキー上のオブジェクトが減るためゲームも多少軽くなることでしょう。まずは適当な文字を入れてTextMeshProでお好きな位置やフォント、大きさ、色になるように字幕をカスタマイズして、終わったら文字は消しておいてください。TextMeshProには2025年1月現在日本語フォントがデフォルトで含まれていないため、ご自身で日本語フォントをImportする必要があります

前々々回の記事ではLocalization Tablesも用意しました。TextMeshProにKeyを指定することで設定された言語の文字をTextMeshProに表示させることができます。

まずはプロジェクトウィンドウで任意のスクリプトフォルダに以下の3つのスクリプトを作ってください。右クリック→Create→Scripting→Empty Scriptでスクリプトをつくれます。クラス名とスクリプト名が一緒じゃないとエラーが出るので注意してください。

//SubtitleTrack.cs
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

[TrackColor(0.8f, 0.8f, 0.2f)] // トラックの色
[TrackClipType(typeof(SubtitlePlayableAsset))] // 使用するクリップタイプ
public class SubtitleTrack : TrackAsset
{
    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    {
        return ScriptPlayable<SubtitlePlayableBehaviour>.Create(graph, inputCount);
    }
}
//SubtitlePlayableAsset.cs
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Localization;
using TMPro;
[System.Serializable]
public class SubtitlePlayableAsset : PlayableAsset
{
    public LocalizedString localizedSubtitle; // ローカライズされた字幕
    public ExposedReference<TextMeshProUGUI> subtitleText; // TextMeshProUGUIの参照
    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var playable = ScriptPlayable<SubtitlePlayableBehaviour>.Create(graph);


        var behaviour = playable.GetBehaviour();
        behaviour.localizedSubtitle = localizedSubtitle;
        behaviour.subtitleText = subtitleText.Resolve(graph.GetResolver());
        return playable;
    }
}
//SubtitlePlayableBehaviour.cs
using UnityEngine;
using UnityEngine.Playables;
using TMPro;
using UnityEngine.Localization;

public class SubtitlePlayableBehaviour : PlayableBehaviour
{
    public LocalizedString localizedSubtitle;
    public TextMeshProUGUI subtitleText;
    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        if (subtitleText == null)
        {
            Debug.LogError("字幕テキストオブジェクトが設定されていません!");
            return;
        }
        if (localizedSubtitle != null)
        {
            localizedSubtitle.StringChanged += OnStringChanged;
            localizedSubtitle.RefreshString();
        }
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        if (subtitleText != null)
        {
            subtitleText.text = ""; // 停止時に字幕を消す
        }
        if (localizedSubtitle != null)
        {
            localizedSubtitle.StringChanged -= OnStringChanged; // イベント解除
        }
    }

    private void OnStringChanged(string newText)
    {
        if (subtitleText != null)
        {
            subtitleText.text = newText;
        }
    }
}

そしたらタイムラインウィンドウに開いて左上の+ボタンを押したら新しくSubtitle Trackというものが追加されていると思いますのでそれをクリックしてください。

Trackがつくられましたら、そのTrackの右側で右クリック→Add Subtitle Playable Assetをクリックしてください。

追加されたクリップを選択した状態でInspectorウィンドウを開いてください一番下にSubtitle Textとい欄がありますのでヒエラルキー上に作成した字幕のTextMeshProをDrag and Dropします。

次にLocalized SubtitleというところがNoneになっているのでそこをクリックしてください。

このようにKeyが表示されますので任意のKeyを選択してください。

ゲームウィンドウを見てみるとこんにちわと字幕が表示されるのを確認できます。

Consoleウィンドウを見ると字幕が表示される度にエラーが発生されますが、動作に支障がなく、面倒くさいので放っておいています(笑)。気になる方は修正してみてください。

これだけで字幕表示ができました。次は言語設定の仕方です。
またスクリプトフォルダで空のスクリプトファイルを作り、下のコードをコピペ保存してください。

//LanguageInitializer.cs
using UnityEngine;
using UnityEngine.Localization.Settings;

public class LanguageInitializer : MonoBehaviour
{
    void Start()
    {
        // デフォルトで日本語を設定
        SetDefaultLanguage("ja");
    }

    public void SetDefaultLanguage(string localeCode)
    {
        var locale = LocalizationSettings.AvailableLocales.GetLocale(localeCode);
        if (locale != null)
        {
            LocalizationSettings.SelectedLocale = locale;
            Debug.Log($"初期言語が設定されました: {locale.LocaleName}");
        }
        else
        {
            Debug.LogWarning($"指定された初期言語コードが見つかりません: {localeCode}");
        }
    }
}

ヒエラルキー上で空オブジェクトをつくり、こちらのスクリプトをコンポーネントに入れてください。Start関数を使っているため、ヒエラルキー上にこのスクリプトがあり、かつゲームをスタートしないとこのスクリプトが動かないことに注意してください。

SetDefaultLanguage("ja");

このスクリプトではStart関数でこの関数を呼び出してますが、UI上のボタンをクリックしたらこの関数に任意の言語のコードを引数で渡すような形にすれば言語設定をUI上で行うことができます。任意の言語のコードの確認の仕方は前々々回の記事で説明しています。英語の場合は"en"などです。

最後に任意のタイミングでタイムラインを呼び出す方法を紹介します。こちらのスクリプトをコピペしてください。

//TimelineController.cs
using UnityEngine;
using UnityEngine.Playables;

public class TimelineController : MonoBehaviour
{
    public PlayableDirector playableDirector;
    void Start()
    {
        // もしプレイアブルディレクターがアタッチされていない場合、このコンポーネントがアタッチされているゲームオブジェクトから探す
        if (playableDirector == null)
            playableDirector = GetComponent<PlayableDirector>();
    }


    void Update()
    {
        // 例: スペースキーが押されたらTimelineを再生
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartTimeline();
        }
    }
    public void StartTimeline()
    {
        // PlayableDirectorを使用してTimelineを再生
        playableDirector.Play();
    }
}

こちらのスクリプトをヒエラルキー上のオブジェクトのコンポーネントに追加して任意のタイムラインのPlayable Directorのnoneという欄にDrag and Dropしてください。

ここのコードでスペースボタンが押されたらStartTimeline()という関数が呼び出されるようにしています。任意のタイミングでStartTimeline()を呼び出せば任意のタイミングでタイムラインを始められます。

// 例: スペースキーが押されたらTimelineを再生
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartTimeline();
        }