Last active
May 2, 2024 14:17
-
-
Save FleshMobProductions/4521073482d9bf9c937e5b71b9c9cd80 to your computer and use it in GitHub Desktop.
Play an AudioClip asset in Unity by double clicking on it without external applications being opened
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using UnityEditor; | |
using UnityEditor.Callbacks; | |
using UnityEngine; | |
// Source and Credit: FREE Audio Preview Tool For Unity Tutorial (by Warped Imagination) 2022-12-05 | |
// https://www.youtube.com/watch?v=Gd8M1Ychis8 | |
public static class AudioPreviewer | |
{ | |
// Reference for AudioUtil method information: | |
// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/Audio/Bindings/AudioUtil.bindings.cs | |
#if UNITY_2020_2_OR_NEWER | |
private static readonly string methodNamePlayClip = "PlayPreviewClip"; | |
private static readonly string methodNameIsClipPlaying = "IsPreviewClipPlaying"; | |
private static readonly string methodNameStopAllClips = "StopAllPreviewClips"; | |
#else | |
private static readonly string methodNamePlayClip = "PlayClip"; | |
private static readonly string methodNameIsClipPlaying = "IsClipPlaying"; | |
private static readonly string methodNameStopAllClips = "StopAllClips"; | |
#endif | |
private static AudioClip lastActiveClip; | |
[OnOpenAsset] | |
public static bool OnOpenAsset(int instanceId, int line) | |
{ | |
UnityEngine.Object obj = EditorUtility.InstanceIDToObject(instanceId); | |
if (obj is AudioClip audioClip) | |
{ | |
Debug.Log($"Open Audio Preview for \"{obj.name}\""); | |
PlayOrStopPreviewClip(audioClip); | |
return true; // Prevent Unity from further processing the opening task | |
} | |
return false; // Continue builtin handling | |
} | |
// If a clip is clicked again that is already playing, stop it. Otherwise play the new selected clip | |
// and stop previous clips from playing | |
private static void PlayOrStopPreviewClip(AudioClip audioClip) | |
{ | |
Assembly unityAssembly = typeof(AudioImporter).Assembly; | |
Type audioUtil = unityAssembly.GetType("UnityEditor.AudioUtil"); | |
#if UNITY_2020_2_OR_NEWER | |
MethodInfo isPreviewClipPlayingInfo = audioUtil.GetMethod( | |
methodNameIsClipPlaying, | |
BindingFlags.Static | BindingFlags.Public); | |
bool isCurrentClipPlaying = (bool)isPreviewClipPlayingInfo.Invoke(null, null) && audioClip == lastActiveClip; | |
#else | |
MethodInfo isPreviewClipPlayingInfo = audioUtil.GetMethod( | |
methodNameIsClipPlaying, | |
BindingFlags.Static | BindingFlags.Public, | |
null, | |
new System.Type[] { typeof(AudioClip) }, | |
null); | |
bool isCurrentClipPlaying = (bool)isPreviewClipPlayingInfo.Invoke(null, new object[] { audioClip }); | |
// I don't know why following line is necessary but without it, regardless of which audio file is | |
// double clicked the playback will always just stop instead of playing the new file | |
isCurrentClipPlaying &= audioClip == lastActiveClip; | |
#endif | |
MethodInfo stopAllPreviewClipsInfo = audioUtil.GetMethod( | |
methodNameStopAllClips, BindingFlags.Static | BindingFlags.Public); | |
stopAllPreviewClipsInfo.Invoke(null, null); | |
if (!isCurrentClipPlaying) | |
{ | |
PlayPreviewClip(audioUtil, audioClip); | |
} | |
} | |
private static void PlayPreviewClip(Type audioUtil, AudioClip audioClip) | |
{ | |
MethodInfo playPreviewClipInfo = audioUtil.GetMethod( | |
methodNamePlayClip, | |
BindingFlags.Static | BindingFlags.Public, | |
null, | |
new System.Type[] { typeof(AudioClip), typeof(Int32), typeof(Boolean) }, | |
null); | |
playPreviewClipInfo.Invoke(null, new object[] { audioClip, 0, false }); | |
lastActiveClip = audioClip; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment