剧情场景后处理Timeline拷贝绑定

main
Yurui 2025-08-07 16:19:51 +08:00
parent f2ebad85d1
commit 169fcb7197
1 changed files with 77 additions and 19 deletions

View File

@ -8,6 +8,8 @@ using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using PhxhSDK.Editor.FileChecker;
using Object = UnityEngine.Object;
using UnityEngine.Timeline;
using Cysharp.Threading.Tasks;
public abstract class PostProcessor
{
@ -245,7 +247,7 @@ public abstract class PostProcessor
/// <param name="postProcessInstructor"></param>
/// <param name="destroyAfterPostProcess"></param>
/// <param name="defaultCameraParam">是否为默认相机</param>
public void PostProcess(PostProcessInstructor postProcessInstructor, bool destroyAfterPostProcess = false,
public async void PostProcess(PostProcessInstructor postProcessInstructor, bool destroyAfterPostProcess = false,
bool defaultCameraParam = true)
{
if (!CheckPostProcessInstructor(postProcessInstructor))
@ -268,7 +270,7 @@ public abstract class PostProcessor
GameObject combineRootObj = BakeCombinedGameObject(0);
_PrepareForBake(combineRootObj.transform);
await SetTimeline();
// 如果Art为预制体先进行解包
UnpackPostSceneArt();
@ -294,7 +296,6 @@ public abstract class PostProcessor
UnpackPostSceneArt();
RemoveRedundant();
HideCamera();
SetTimeline();
DestroyUselessObject();
AfterAll(destroyAfterPostProcess);
@ -813,30 +814,87 @@ public abstract class PostProcessor
/// <summary>
/// 设置剧情timeline
/// </summary>
private void SetTimeline()
private async UniTask SetTimeline()
{
/*GameObject goTimeline = PostProcessInstructor.timeline;
if (null == goTimeline)
GameObject goOld = PostProcessInstructor.timeline;
if (null == goOld)
return;
PlayableDirector playableDirector = goTimeline.GetComponent<PlayableDirector>();
if (null == playableDirector)
PlayableDirector oldDirector = goOld.GetComponent<PlayableDirector>();
if (null == oldDirector)
{
Debug.LogError("获取PlayableDirector失败");
return;
}
if (null == playableDirector.playableAsset)
if (null == oldDirector.playableAsset)
{
Debug.LogError("获取PlayableAsset失败");
return;
}
string timelinePath = AssetDatabase.GetAssetPath(playableDirector.playableAsset);
string outputPath = $"{ProcessedResourceDir}/{playableDirector.playableAsset.name}.playable";
AssetDatabase.CopyAsset(timelinePath, outputPath);
PlayableAsset newPlayableAsset = (PlayableAsset)AssetDatabase.LoadAssetAtPath(outputPath, typeof(PlayableAsset));
playableDirector.playableAsset = newPlayableAsset;
string oldPath = AssetDatabase.GetAssetPath(oldDirector.playableAsset);
string newPath = $"{ProcessedResourceDir}/{oldDirector.playableAsset.name}.playable";
if (!AssetDatabase.CopyAsset(oldPath, newPath))
{
Debug.LogError("Timeline拷贝失败");
return;
}
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();*/
GameObject goNew = new("Timeline_PostProcess");
goNew.transform.parent = goOld.transform.parent;
goNew.transform.position = Vector3.zero;
PlayableDirector newDirector = goNew.AddComponent<PlayableDirector>();
newDirector.timeUpdateMode = oldDirector.timeUpdateMode;
newDirector.playOnAwake = oldDirector.playOnAwake;
newDirector.extrapolationMode = oldDirector.extrapolationMode;
newDirector.initialTime = oldDirector.initialTime;
// 新预制体绑定新Playable资源
newDirector.playableAsset = AssetDatabase.LoadAssetAtPath<TimelineAsset>(newPath);
newDirector.playableAsset.name = System.IO.Path.GetFileNameWithoutExtension(newPath);
SerializedObject directorSO = new(oldDirector);
SerializedProperty sceneBindings = directorSO.FindProperty("m_SceneBindings");
newDirector.Play();
await UniTask.NextFrame();
// 删除PlayableDirector.Bindgins的空Key项并把原Timeline文件的轨道Key替换到当前Timeline文件的轨道对象
Dictionary<Object, Object> bindingsKV = new();
for (int i = 0; i < sceneBindings.arraySize; ++i)
{
SerializedProperty bindingElement = sceneBindings.GetArrayElementAtIndex(i);
// key是源文件的轨道对象value是当前文件的绑定value
Object key = bindingElement.FindPropertyRelative("key").objectReferenceValue;
Object value = bindingElement.FindPropertyRelative("value").objectReferenceValue;
if (null == key)
continue;
bindingsKV.Add(key, value);
}
// 删除无用绑定
while (sceneBindings.arraySize > 0)
{
sceneBindings.DeleteArrayElementAtIndex(0);
}
directorSO.ApplyModifiedProperties();
// 设置有效绑定新老timeline资源outputs顺序完全一致
List<PlayableBinding> listOldBinding = oldDirector.playableAsset.outputs.ToList();
List<PlayableBinding> listNewBinding = newDirector.playableAsset.outputs.ToList();
for (int i = 0; i < listOldBinding.Count; ++i)
{
TrackAsset oldTrackAsset = listOldBinding[i].sourceObject as TrackAsset;
TrackAsset newTrackAsset = listNewBinding[i].sourceObject as TrackAsset;
if (bindingsKV.TryGetValue(oldTrackAsset, out Object value))
newDirector.SetGenericBinding(newTrackAsset, value);
}
GameObject.DestroyImmediate(PostProcessInstructor.timeline);
AssetDatabase.SaveAssetIfDirty(newDirector);
}
#endregion
}