Skip to content

Instantly share code, notes, and snippets.

@JavadocMD
Last active June 23, 2023 18:39
Show Gist options
  • Save JavadocMD/39c2197c2b4970ed06a5247bee386c72 to your computer and use it in GitHub Desktop.
Save JavadocMD/39c2197c2b4970ed06a5247bee386c72 to your computer and use it in GitHub Desktop.
A Unity script to play a sound effect when script compiling starts and ends.
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
// I recommend dropping this script in an Editor folder.
// You should have two audio clips somewhere in the project.
// You'll need to edit-in the paths of those clips (from your project root folder) in the static initializer below.
// Example path: "Assets/Editor/CompileIndicator/start.mp3"
namespace Assets.Editor {
/// <summary>
/// Plays a sound effect when script compiling starts and ends.
/// </summary>
[InitializeOnLoad]
public static class CompileIndicator {
private const string CompileStatePrefsKey = "CompileIndicator.WasCompiling";
private static readonly AudioClip StartClip;
private static readonly AudioClip EndClip;
static CompileIndicator() {
EditorApplication.update += OnUpdate;
StartClip = AssetDatabase.LoadAssetAtPath<AudioClip>("REPLACE_WITH_PATH_TO_YOUR_START_CLIP");
EndClip = AssetDatabase.LoadAssetAtPath<AudioClip>("REPLACE_WITH_PATH_TO_YOUR_END_CLIP");
}
private static void OnUpdate() {
var wasCompiling = EditorPrefs.GetBool(CompileStatePrefsKey);
var isCompiling = EditorApplication.isCompiling;
// Return early if compile status hasn't changed.
if (wasCompiling == isCompiling)
return;
if (isCompiling)
OnStartCompiling();
else
OnEndCompiling();
EditorPrefs.SetBool(CompileStatePrefsKey, isCompiling);
}
private static void OnStartCompiling() {
PlayClip(StartClip);
}
private static void OnEndCompiling() {
PlayClip(EndClip);
}
private static void PlayClip(AudioClip clip) {
Assembly unityEditorAssembly = typeof(AudioImporter).Assembly;
Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
MethodInfo method = audioUtilClass.GetMethod(
"PlayClip",
BindingFlags.Static | BindingFlags.Public,
null,
new []{typeof(AudioClip)},
null
);
method.Invoke(null, new object[]{clip});
}
}
}
@Yourstress
Copy link

Awesome script. Thanks for the effort. I've modified it a quick-and-dirty way to load AudioClips not in the Resources folder. It might be useful to others that don't want to move clips between folders.

static CompileIndicator() {
EditorApplication.update = OnUpdate;
string guid = AssetDatabase.FindAssets("t:AudioClip YOUR_START_CLIP_NAME")[0];
StartClip = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid));
guid = AssetDatabase.FindAssets("t:AudioClip YOUR_END_CLIP_NAME")[0];
EndClip = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid));
}

@JavadocMD
Copy link
Author

DietChugg on reddit suggests using AssetDatabase rather than Resources is preferable to avoid bloating your builds. Script updated to reflect that. Or you can use Yourstress' advice above to find the clips by name. 👍

@dylanh724
Copy link

dylanh724 commented Jun 16, 2018

Do I actually need the

namespace Assets.Editor {

Getting some errs saying it's unexpected (5.6). It's in the editor dir.

@ChrisNZL
Copy link

ChrisNZL commented Jul 9, 2019

Works in Unity 2019.1.9f1, thanks for posting this 👍

One suggestion I'd make -- to not interfere with other scripts that subscribe to editor update event, I'd advise changing:

EditorApplication.update = OnUpdate;

to

EditorApplication.update += OnUpdate;

@JavadocMD
Copy link
Author

Great catch @ChrisNZL! Updated.

@manotone
Copy link

manotone commented Jul 8, 2020

Hey, is this working in Unity 2019.3 onwards? I'm using 2019.3.11 and I can't get the sound to play. I added a null check to make sure it was finding the audio clip, so I know the audio is in the right place.

Thanks!

@nicmar
Copy link

nicmar commented Nov 19, 2020

@manotone Since 2019 you need to use this instead:

		public static void PlayClip(AudioClip clip, int startSample = 0, bool loop = false)
		{
			System.Reflection.Assembly unityEditorAssembly = typeof(AudioImporter).Assembly;
			System.Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
			System.Reflection.MethodInfo method = audioUtilClass.GetMethod(
				"PlayClip",
				System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public,
				null,
				new System.Type[] { typeof(AudioClip), typeof(int), typeof(bool) },
				null
			);
			method.Invoke(
				null,
				new object[] { clip, startSample, loop }
			);
		}

(Found here: https://forum.unity.com/threads/way-to-play-audio-in-editor-using-an-editor-script.132042/?_ga=2.71159570.364268315.1605429586-738984339.1602493717#post-4767824)

@lreeves
Copy link

lreeves commented May 19, 2022

If anyone comes here in 2022 the reflected method is now named "PlayPreviewClip".

@bezoro
Copy link

bezoro commented Feb 13, 2023

Use the following in Unity 2021

private static void PlayClip(AudioClip clip, int startSample = 0, bool loop = false)
{
	var unityEditorAssembly = typeof(AudioImporter).Assembly;
	var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
	var method = audioUtilClass.GetMethod("PlayPreviewClip",
					       BindingFlags.Static | BindingFlags.Public,
					       null,
					       new[]
					     {
						typeof(AudioClip), typeof(int),
						typeof(bool)
					     },
						null);

         method.Invoke(null, new object[] { clip, startSample, loop });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment