Files
tools/Unity C++脚本/PlayableDirectorContextMenu.cs
2025-08-01 10:50:57 +08:00

107 lines
3.9 KiB
C#

using UnityEngine;
using UnityEngine.Playables;
using UnityEditor;
using System.Collections.Generic;
using UnityEngine.Timeline;
using System.Linq;
public class TimelineBindingCopier : Editor
{
private const string SourcePlayableDirectorKey = "SourcePlayableDirector"; // EditorPrefs 存储源 PlayableDirector 的键
[MenuItem("CONTEXT/PlayableDirector/Copy Bindings")]
public static void CopyBindings()
{
PlayableDirector source = Selection.activeGameObject?.GetComponent<PlayableDirector>();
if (source == null)
{
Debug.LogError("Please select a PlayableDirector to copy bindings from.");
return;
}
// 保存当前选择的 PlayableDirector 到 EditorPrefs
EditorPrefs.SetString(SourcePlayableDirectorKey, source.gameObject.name);
Debug.Log($"Source PlayableDirector '{source.name}' saved. Now select the target PlayableDirector.");
}
[MenuItem("CONTEXT/PlayableDirector/Paste Bindings")]
public static void PasteBindings()
{
PlayableDirector target = Selection.activeGameObject?.GetComponent<PlayableDirector>();
if (target == null)
{
Debug.LogError("Please select a PlayableDirector to paste bindings to.");
return;
}
string sourceObjectName = EditorPrefs.GetString(SourcePlayableDirectorKey, "");
if (string.IsNullOrEmpty(sourceObjectName))
{
Debug.LogError("No source PlayableDirector saved. Please use 'Copy Bindings' first.");
return;
}
GameObject sourceObject = GameObject.Find(sourceObjectName);
if (sourceObject == null)
{
Debug.LogError($"Source PlayableDirector '{sourceObjectName}' not found. Please copy bindings again.");
return;
}
PlayableDirector source = sourceObject.GetComponent<PlayableDirector>();
if (source == null)
{
Debug.LogError($"Source PlayableDirector '{sourceObjectName}' does not have a PlayableDirector component.");
return;
}
var sourceAsset = source.playableAsset as TimelineAsset;
var targetAsset = target.playableAsset as TimelineAsset;
if (sourceAsset == null || targetAsset == null)
{
Debug.LogError("Source or Target PlayableDirector does not contain a valid Timeline.");
return;
}
// Paste bindings based on track indices
PasteBindingsInternal(source, target, sourceAsset, targetAsset);
}
private static void PasteBindingsInternal(PlayableDirector source, PlayableDirector target, TimelineAsset sourceAsset, TimelineAsset targetAsset)
{
var sourceTracks = sourceAsset.GetOutputTracks().ToArray(); // Convert to array
var targetTracks = targetAsset.GetOutputTracks().ToArray(); // Convert to array
if (sourceTracks.Length != targetTracks.Length)
{
Debug.LogError("Source and Target timelines have different number of tracks.");
return;
}
for (int i = 0; i < sourceTracks.Length; i++)
{
TrackAsset sourceTrack = sourceTracks[i];
TrackAsset targetTrack = targetTracks[i];
if (sourceTrack == null || targetTrack == null)
{
Debug.Log($"Skipping track at index {i} because it is null.");
continue;
}
var sourceBinding = source.GetGenericBinding(sourceTrack);
if (sourceBinding != null)
{
// Set the binding for the target PlayableDirector
target.SetGenericBinding(targetTrack, sourceBinding);
Debug.Log($"Binding pasted for track '{sourceTrack.name}' (Index {i}).");
}
else
{
Debug.Log($"No binding found for track '{sourceTrack.name}' (Index {i}), skipping...");
}
}
}
}