search
LoginSignup
5

More than 1 year has passed since last update.

posted at

updated at

Organization

Unity Timeline 1.4で追加されたTimelineActionの使い方

この記事はUnity #3 Advent Calendar 2020の12/12(土)の記事です。

はじめに

この記事ではUnityのTimeline機能に存在するTimelineActionとそれに関連する機能について解説します。

ターゲット

Unityを使った開発を行っておりTimeline機能を拡張して実装を進めているエンジニアがメインターゲットです。
Unityの基礎的な内容やTimeline、Editor拡張などで頻出する単語・機能などに関しての詳細な説明は省略しますので予めご了承ください。

またここで解説する機能はUnity Timeline 1.4.0以降から使えるようになるものです。
詳しくはchangelogを参照してください。

得られるもの

UnityEditor.Timeline.Actions.TimelineActionの基本的な使い方を知ることができます。

この機能は主にTimelineウィンドウ上のコンテキストメニューに独自の処理を追加することを可能とします。

1.4.0以前のバージョンではTimelineウィンドウに関わるクラス群がほとんどinternalな宣言になっていたこともあり、独自の処理をTimelineウィンドウ内に追加することは現実的ではなく、オリジナルのEditorWindowを定義して利用者にはTimelineウィンドウとその独自ウィンドウを一緒に開いてもらって編集をするようなワークフローを組んでいた方も多いと思います。

今回登場したこのTimelineActionの機能によりコンテキストメニューを使えるようになったので、そのような独自ウィンドウをわざわざ作らなくても済むことが大幅に増えました。

本題

Timeline機能も昔と比べてサポートが充実してきました。
公式のTimelineActionに関するAPIドキュメントを見に行くとしっかりとサンプルコードが載っています。
今回はこのサンプルコードを軸に解説を進めます。

SampleTimelineAction.cs
[MenuEntry("Custom Actions/Sample Timeline Action")]
public class SampleTimelineAction : TimelineAction
{
    public override ActionValidity Validate(ActionContext context)
    {
        return ActionValidity.Valid;
    }

    public override bool Execute(ActionContext context)
    {
        Debug.Log("Test Action");
        return true;
    }

    [TimelineShortcut("SampleTimelineAction", KeyCode.Q)]
    public static void HandleShortCut(ShortcutArguments args)
    {
        Invoker.InvokeWithSelected<SampleTimelineAction>();
    }
}

TimelineAction

TimelineActionの機能を使うためにはTimelineActionクラスを継承します。
詳細は後述するそれぞれの項目で解説しますが、このクラスを継承しただけではTimelineウィンドウ上では動作せず、MenuEntryAttributeTimelineShortcutAttributeと組み合わせて使用することでTimelineウィンドウ上で処理を実行できるようになります。

public override ActionValidity Validate(ActionContext context)

後述のExecuteメソッドを実行するかどうかを検証するメソッドです。

ActionValidity

戻り値のActionValidityによって動作が変わります。

ActionValidityの種別 Executeメソッドが実行されるかどうか MenuEntryAttributeを使用している場合の挙動
ActionValidity.Valid 実行されます。 コンテキストメニューに選択可能な状態で表示されます。
ActionValidity.NotApplicable 実行されません。 コンテキストメニューには表示されません。
ActionValidity.Inavlid 実行されません。 コンテキストメニューに選択不可能な状態で表示されます。

特殊なのがActionValidity.NotApplicableで、これはメニューにも表示されなくなります。
使い分けの仕方としては、条件によって使用可能な処理はActionValidity.Invalidを、そもそもその編集状態では使用することができない処理はActionValidity.NotApplicableという風にするのが良いと思います。
これは、1つのUnityプロジェクトの中で性質の違う複数のTimelineを編集する必要があるような環境で使えそうです。
(ゲーム開発で例えると、ガチャ演出のTimeline編集専用のActionと奥義演出のTimeline編集専用のAction機能が同居しているなどのケース)

逆に言えば、そこまで規模の大きくない編集環境であれば、基本的にはActionValidity.ValidActionValidity.Invalidの2つを使えばよいと思います。

ActionContext

このActionが動作する際のTimelineウィンドウ上の様々な情報がActionContextとして引数に入ってきます。

それぞれのプロパティ(フィールド)の詳細は以下の通りです。

プロパティ(フィールド)名 注意事項など
PlayableDirector director TimelineEditor.inspectedDirectorと同様の内容が入ります。Projectウィンドウで直接TimelineAssetを選択した状態だとnullが入ります。
TimelineAsset timeline TimelineEditor.inspectedAssetと同様の内容が入ります。
double? invocationTime コンテキストメニュー経由で実行した場合、右クリックした場所から時間を算出して秒数が入ります。※1 ショートカット経由での実行の場合はnullが入ります。
IEnumerable<TrackAsset> tracks SelectionManager.SelectedTracks()と同様の内容が入ります。※2
IEnumerable<TimelineClip> clips SelectionManager.SelectedClips()と同様の内容が入ります。※2
IEnumerable<IMarker> markers SelectionManager.SelectedMarkers()と同様の内容が入ります。※2

※1 クリップが置かれる場所を右クリックした際はその位置の再生時間が入ってきましたが、左側にあるトラックリストの部分を右クリックしてコンテキストメニューから実行した際に入る時間がよく分からない値になっていました。調査中です。
※2 SelectionManagerinternal classです。

public override bool Execute(ActionContext context)

実際に処理したい内容をここに記述します。
引数にはValidateメソッドのときと同様にActionContextが入ってきます。

戻り値には処理の成否を返却します。

実行されるActionのインスタンスはActionManagerという内部クラスでキャッシュされて使い回すため、フィールドに値を持ったりする場合は注意してください。

MenuEntryAttribute

TimelineActionを継承したクラスにこのAttributeをつけることで、Timelineウィンドウ上のコンテキストメニューに処理を追加することができます。

機能としてはTimelineウィンドウの中でしか動作しないという点以外はUnityEditor.MenuItemとほぼ同様の内容です。

標準機能のプライオリティに関しては MenuPriorityクラスで確認することができます。

TimelineActionの場合、マーカー、トラック、クリップ(クリップが置かれていない場所を含む)を右クリックした際のコンテキストメニューに表示されます。

※マーカーのみ、トラックのみ、クリップのみに対応したい場合はそれぞれMarkerAction,TrackAction,ClipActionが存在します。

TimelineShortcutAttribute

Timelineウィンドウ上でショートカットキーを使えるようにします。

機能としてはUnity2019から追加されたShortcuts Managerと同様ですが、このAttributeを使うことで自動的にTimelineのカテゴリに振り分けてくれます。

コンテキストメニューで処理する内容はショートカットキーでも同様に使いたいケースが多いことから、このTimelineActionのサンプルで紹介されていますが、このAttribute自体はTimelineActionと関係なく単独で動作します。

ショートカットキー周りは時間があれば別途記事を作って紹介するかもしれません。。

Invoker

とてもシンプルな名前ですが、TimelineActionを含む各種Actionクラスの処理を外から手軽に呼び出せるようにしたユーティリティクラスです。

TimelineActionの場合、bool InvokeWithSelected<T>() where T : TimelineActionメソッドを使用することで、任意の独自Actionを呼び出すこと(ValidateしてExecuteするまで)が可能です。

引数に渡すActionContextの用意やUndo処理なども含めて内部でやってくれるので、よほど特殊な事情がなければこのInvokerクラスを経由して各種Actionクラスを実行したほうがよいでしょう。

オマケ

APIドキュメントにサンプルコードが書かれているのはとても有り難いことですが、内容は最低限しかないためイマイチどのように使うのかピンとこない人もいると思います。

実は標準的な機能(コピー&ペーストや削除など)も、このActionを使って定義されています。
※場所は↓(@の後ろは自分の使っているTimelineのバージョン)
com.unity.timeline@1.4.0/Editor/Actions/TimelineActions.cs

internalなクラスを多用しているのでそのまま参考にできるわけではありませんが、それらの実装を見ることでイメージがかなり掴めるようになると思いますので、そちらも合わせて見てから自分の実装を進めると良いと思います。

おわりに

今回はTimelineActionについて解説してみました。
これ以外にも機能を限定したMarkerAction,TrackAction,ClipActionも存在しますが、基本的な仕様はTimelineActionと同様なので、この記事だけでも使えると思います。

Timelineもようやくコンテキストメニューも使えるようになり、拡張の幅もかなり広がってきました。
みなさんが開発しているツールが少しでも便利になってもらえれば幸いです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
5