using System; using System.Collections.Generic; using System.Linq; using UnityEditor.Timeline; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Timeline; using UnityEngine.Video; namespace UnityEditor { [Serializable] public class KeyCodeDefine { public KeyCode keyCode; //public string audioName; public int maxCount; //public float duration; [Tooltip("存在资源取资源名和时间")] public AssetReferenceT audioAsset; } [Serializable] public class KeyCodeDefineStrint { public KeyCode keyCode; //public string audioName; public int maxCount; //public float duration; public string audioAsset; } [Serializable] public class AudioDefine { public string audioName; public int index; public List time = new List(); } [Serializable] public class TimelineAudioDefine { [Tooltip("自动生成or手动修改")] public List audioDefines = new List(); } public class TimelineAudioEditor : EditorWindow { [MenuItem("Tools/Timeline Audio Editor", false, 120)] public static void ShowWindow() { EditorWindow thisWindow = GetWindow(typeof(TimelineAudioEditor)); thisWindow.titleContent = new GUIContent("Timeline Audio Editor"); thisWindow.position = new Rect(Screen.width / 2, Screen.height / 2, 600, 800); } //视频播放编辑器 VideoPlayer videoPlayer; GameObject videoPlayerGo; VideoClip videoClip; [Tooltip("按键==》音效name")] public KeyCodeDefine[] keyCodeDefines = new KeyCodeDefine[1]; [Tooltip("自动生成or手动修改")] public List audioDefines = new List(); [Tooltip("保存文件名")] string saveJsonName; [Tooltip("自动生成or手动选取读到上方列表然后修改")] TextAsset jsonAsset; string audioPath = "Assets/ABPackage/pkgFirstPackage/Audio/building/{0}.mp3"; TimelineAsset timelineAsset; private SerializedObject serObj; //private SerializedProperty videoClipPty; private SerializedProperty gosPty; private SerializedProperty audioDefinesPty; //private SerializedProperty jsonAssetPty; //private SerializedProperty timelineAssetPty; //输出json文本 private string jsonText; private string jsonPath = "Assets/Editor/VideoTool/{0}.json"; float sliderValue; Vector2 scrollPosition; private void OnEnable() { videoPlayerGo = new GameObject("VideoPlayer"); videoPlayer = videoPlayerGo.AddComponent(); //切换场景 videoPlayer.playOnAwake = false; videoPlayer.renderMode = VideoRenderMode.CameraNearPlane; videoPlayer.targetCamera = videoPlayerGo.AddComponent(); videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource; videoPlayer.EnableAudioTrack(0, true); videoPlayer.SetTargetAudioSource(0, videoPlayerGo.AddComponent()); serObj = new SerializedObject(this); //videoClipPty = serObj.FindProperty("videoClip"); gosPty = serObj.FindProperty("keyCodeDefines"); audioDefinesPty = serObj.FindProperty("audioDefines"); //jsonAssetPty = serObj.FindProperty("jsonAsset"); //timelineAssetPty = serObj.FindProperty("timelineAsset"); var keyCodeDefinesAsset = AssetDatabase.LoadAssetAtPath(string.Format(jsonPath, "keyCodeDefinesstring")); if (keyCodeDefinesAsset != null) { KeyCodeDefineStrint[] keyCodeDefineStrints = Newtonsoft.Json.JsonConvert.DeserializeObject(keyCodeDefinesAsset.text); keyCodeDefines = keyCodeDefineStrints.Select(c => new KeyCodeDefine() { keyCode = c.keyCode, maxCount = c.maxCount, audioAsset = new AssetReferenceT(c.audioAsset) }).ToArray(); } serObj.Update(); serObj.ApplyModifiedProperties(); } void OnGUI() { Event e = Event.current; if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Space) { //停止所有输入框的输入 GUI.FocusControl(null); if (videoPlayer.isPlaying) { videoPlayer.Pause(); } else { videoPlayer.Play(); } } //视频剪辑 videoClip = EditorGUILayout.ObjectField("VideoClip", videoClip, typeof(VideoClip), false) as VideoClip; //当videoClip修改时,将其赋值给videoPlayer.clip //EditorGUILayout.PropertyField(videoClipPty, true); if (videoClip != null) { videoPlayer.clip = videoClip; if (!videoPlayer.isPlaying) { sliderValue = EditorGUILayout.Slider(sliderValue, 0, (float)videoClip.length); //滑动条控制视频播放进度 videoPlayer.time = sliderValue; } else { sliderValue = (float)videoPlayer.time; sliderValue = EditorGUILayout.Slider(sliderValue, 0, (float)videoClip.length); } } // videoPlayer 可拖动进度条 //当点击keyCodeDefines.keyCode 记录视频播放时间 if (keyCodeDefines != null && e.type == EventType.KeyDown && videoPlayer.isPlaying) { var item = keyCodeDefines.FirstOrDefault(c => c.keyCode == e.keyCode); if (item != null) { if (item.audioAsset.editorAsset != null) { string audioName = item.audioAsset.editorAsset.name; float duration = item.audioAsset.editorAsset.length; var curAudioDefines = audioDefines.Where(c => c.audioName == audioName).ToArray(); int index = curAudioDefines.Length; var audioDefine = index < item.maxCount ? null : curAudioDefines[0]; foreach (var audioDefineItem in curAudioDefines) { if (audioDefineItem.time[^1] < videoPlayer.time - (double)duration) { audioDefine = audioDefineItem; break; } } if (audioDefine == null) { audioDefine = new AudioDefine() { audioName = audioName, index = index }; audioDefines.Add(audioDefine); } audioDefine.time.Add(videoPlayer.time); //刷新timelinePty serObj.Update(); SystemSoundsPlay(); } else { Debug.LogError("音频不存在"); } } } scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); EditorGUILayout.PropertyField(gosPty, true); saveJsonName = EditorGUILayout.TextField("SaveJsonName", saveJsonName); EditorGUILayout.PropertyField(audioDefinesPty, true); EditorGUILayout.EndScrollView(); serObj.ApplyModifiedProperties(); if (GUILayout.Button("Save")) { Save(); jsonAsset = AssetDatabase.LoadAssetAtPath(string.Format(jsonPath, saveJsonName)); serObj.Update(); } if (GUILayout.Button("Read")) { if (jsonAsset != null) { jsonText = jsonAsset.text; audioDefines = Newtonsoft.Json.JsonConvert.DeserializeObject>(jsonText); serObj.Update(); } } jsonAsset = EditorGUILayout.ObjectField("JsonAsset", jsonAsset, typeof(TextAsset), false) as TextAsset; //EditorGUILayout.PropertyField(jsonAssetPty, true); if (GUILayout.Button("Change")) { if (jsonAsset != null) { jsonText = jsonAsset.text; audioDefines = Newtonsoft.Json.JsonConvert.DeserializeObject>(jsonText); //获取所有的音频轨道 var audioTracks = timelineAsset.GetOutputTracks().ToList(); //List audioDefines = audioDefines; foreach (var item in audioDefines) { AudioTrack audioTrack = (AudioTrack)audioTracks.FirstOrDefault(c => c.name == item.audioName + item.index && c is AudioTrack); if (audioTrack != null) { var audioClip = audioTrack.GetClips(); foreach (var clip in audioClip) { audioTrack.DeleteClip(clip); } } else { audioTrack = timelineAsset.CreateTrack(null, item.audioName + item.index); } foreach (var time in item.time) { //在time时间点创建一个音频片段 AudioClip audioClip1 = AssetDatabase.LoadAssetAtPath(string.Format(audioPath, item.audioName)); if (audioClip1 != null) { var audioClip = audioTrack.CreateClip(audioClip1); audioClip.start = time; } else { Debug.LogError("音频不存在:" + item.audioName); } } } EditorUtility.SetDirty(timelineAsset); AssetDatabase.SaveAssets(); // Timeline窗口刷新 TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved); } } audioPath = EditorGUILayout.TextField("AudioPath", audioPath); timelineAsset = EditorGUILayout.ObjectField("TimelineAsset", timelineAsset, typeof(TimelineAsset), false) as TimelineAsset; //EditorGUILayout.PropertyField(timelineAssetPty, true); // 刷新界面 Repaint(); //按按钮响应各种系统提示音 //if (GUILayout.Button("Beep")) //{ // System.Media.SystemSounds.Beep.Play(); //} //if (GUILayout.Button("Asterisk")) //{ // System.Media.SystemSounds.Asterisk.Play(); //} //if (GUILayout.Button("Exclamation")) //{ // System.Media.SystemSounds.Exclamation.Play(); //} //if (GUILayout.Button("Hand")) //{ // System.Media.SystemSounds.Hand.Play(); //} //if (GUILayout.Button("Question")) //{ // System.Media.SystemSounds.Question.Play(); //} } void SystemSoundsPlay() { System.Media.SystemSounds.Exclamation.Play(); } void Save() { jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(audioDefines); string path = string.Format(jsonPath, saveJsonName); System.IO.File.WriteAllText(path, jsonText); KeyCodeDefineStrint[] keyCodeDefineStrints = keyCodeDefines.Select(c => new KeyCodeDefineStrint() { keyCode = c.keyCode, maxCount = c.maxCount, audioAsset = c.audioAsset.AssetGUID }).ToArray(); string keyCodeDefinesstring = Newtonsoft.Json.JsonConvert.SerializeObject(keyCodeDefineStrints); path = string.Format(jsonPath, "keyCodeDefinesstring"); System.IO.File.WriteAllText(path, keyCodeDefinesstring); AssetDatabase.Refresh(); } private void OnDisable() { DestroyImmediate(videoPlayerGo); } } }