作るもの
UnityのTimelineで、クリップやトラックを右クリックでできる操作を追加します。
環境
Unity2022.3.4f1 Timeline1.7.4
Timelineバージョン1.4.0以降なら問題無いです。
自作クリップ
Color
とfloat
を設定するようなクリップがあったとします。
ここで、あるクリップに設定されてるfloat
の値だけを他の沢山あるSampleClip
にコピペしたいな~と思ったとします。
シナリオ
実際にコピペする際の操作は、
- 1つだけ
SampleClip
を選択し、右クリックでメニューを表示。コピーコマンドを実行すると、float
だけコピーしてどこかに保存する。 - 1つ以上の
SampleClip
を選択し、右クリックでメニューを表示。貼り付けコマンドを実行すると、コピーされたfloat
があれば選択されている全てのSampleClip
のfloat
に貼り付ける。
というものになります。
TimelineAction
こういった、クリップやトラックに対する動作はTimelineAction
というクラスを継承して作成できます。
さきほどのコピーのクラスは以下のようになります。
using System.Linq; using UnityEditor.Timeline.Actions; [MenuEntry("SampleClip/ValueCopy")] public sealed class SampleClipOnlyValueCopy : TimelineAction { public static float? ClipBoard { get; private set; } public override bool Execute(ActionContext context) { // バリデーションで、1つSampleClipが選択されていることは保証されてる var sampleClip = context.clips.First().asset as SampleClip; ClipBoard = sampleClip.Value; return true; } public override ActionValidity Validate(ActionContext context) { // トラックは選択されてなくて、 // クリップは1つだけ SampleClip が選択されてたら表示 // それ以外は表示しない var hasTracks = context.tracks.Any(); var isOnlyOneSampleClip = context.clips.Count() == 1 && context.clips.All(clip => clip.asset is SampleClip); return !hasTracks && isOnlyOneSampleClip ? ActionValidity.Valid : ActionValidity.NotApplicable; } }
Execute
で選択されているトラックやクリップに対しての操作を定義し、
Validate
で、コマンドを表示するか、非表示にするか切り替えます。
今はSampleClip
にだけ行う操作なので、それ以外のクリップを右クリックした際には表示すらさせないようにNotApplicable
とします。
MenuEntryAttribute
でどんな名前で表示するかを決めます。
次に、貼り付ける方のコマンドは以下のようになります。
using System.Linq; using UnityEditor.Timeline.Actions; [MenuEntry("SampleClip/ValuePaste")] [ApplyDefaultUndo("SampleClipValuePaste")] public sealed class SampleClipValuePaste : TimelineAction { public override bool Execute(ActionContext context) { var copyValue = SampleClipOnlyValueCopy.ClipBoard.Value; foreach (var clip in context.clips) { var sampleClip = clip.asset as SampleClip; sampleClip.SetValue(copyValue); } return false; } public override ActionValidity Validate(ActionContext context) { // トラックは選択されてなくて、 // クリップはSampleClipだけ選択されてたら表示 // クリップボードに値が無い場合は表示はするけど選べない var hasTracks = context.tracks.Any(); var isOnlySampleClip = context.clips.All(clip => clip.asset is SampleClip); var hasValue = SampleClipOnlyValueCopy.ClipBoard.HasValue; if (hasTracks || !isOnlySampleClip) { return ActionValidity.NotApplicable; } return hasValue ? ActionValidity.Valid : ActionValidity.Invalid; } }
コピーと同じくValidate
とExecute
、MenuEntry
がありますが、少し増えているものがあります。
まず、Validate
の結果にInvalid
が増えました。このとき、表示はするけど実行できない状態になります。
今ですと、SampleClip
を選択してるけどコピーされてる値が無い場合は貼り付けられませんから、実行だけ禁止します。
また、クラスの属性にApplyDefaultUndoAttribute
が追加されました。これは、Execute
した場合に勝手にその操作をCtrl + Z
でUndo
できるよう登録してくれるものです。
コピーの際にはどうでもよかったですが、貼り付けはUndo
できてほしいので付けました。
終わり
Timelineは一般的に非プログラマが触ることが多いと思いますので、手軽に扱えるように環境を整えてあげたいですね。
それにしても、割と活用頻度が多そうなAPIなのですが、調べても全然ユーザーの資料が出てこず、不思議です。
(ApplyDefaultUndo
なんか便利なのに、後述Qiita記事のInvoker
の中身を追わないと存在に気付かなかった)
参考資料
公式のAPIリファレンス
docs.unity3d.com
TimelineActionについてまとめてくださっているQiita記事 qiita.com