#if UNITY_EDITOR public class WwiseSetupWizard { public static void RunModify() { try { UnityEngine.Debug.Log("WwiseUnity: Running modify setup..."); UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects); ModifySetup(); UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database."); UnityEditor.AssetDatabase.Refresh(); // IMPORTANT: This log line is parsed by the Launcher. Do not modify it. UnityEngine.Debug.Log("WwiseUnity: End of setup, exiting Unity."); } catch (System.Exception e) { UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e); } } public static void RunSetup() { try { UnityEngine.Debug.Log("WwiseUnity: Running install setup..."); Setup(); UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database."); UnityEditor.AssetDatabase.Refresh(); // IMPORTANT: This log line is parsed by the Launcher. Do not modify it. UnityEngine.Debug.Log("WwiseUnity: End of setup, exiting Unity."); } catch (System.Exception e) { UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e); } } public static void RunDemoSceneSetup() { try { UnityEngine.Debug.Log("WwiseUnity: Running demo scene setup..."); Setup(); UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/WwiseDemoScene/WwiseDemoScene.unity"); UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database."); UnityEditor.AssetDatabase.Refresh(); UnityEngine.Debug.Log("WwiseUnity: End of demo scene setup, exiting Unity."); } catch (System.Exception e) { UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e); } } private static int TotalNumberOfSections = 3; private static void UpdateProgressBar(int sectionIndex, int subSectionIndex = 0, int totalSubSections = 1) { subSectionIndex = UnityEngine.Mathf.Clamp(subSectionIndex, 0, totalSubSections); sectionIndex = UnityEngine.Mathf.Clamp(sectionIndex, 0, TotalNumberOfSections); float progress = ((float)subSectionIndex / totalSubSections + sectionIndex) / TotalNumberOfSections; UnityEditor.EditorUtility.DisplayProgressBar("Wwise Integration", "Migration in progress - Please wait...", progress); } public static void RunMigrate() { try { UnityEngine.Debug.Log("WwiseUnity: Running migration setup..."); UnityEngine.Debug.Log("WwiseUnity: Reading parameters..."); var arguments = System.Environment.GetCommandLineArgs(); string migrateStartString = null; var indexMigrateStart = System.Array.IndexOf(arguments, "-wwiseInstallMigrateStart"); if (indexMigrateStart != -1) migrateStartString = arguments[indexMigrateStart + 1]; else { UnityEngine.Debug.LogError("WwiseUnity: ERROR: Missing parameter wwiseInstallMigrateStart."); return; } int migrateStart; if (!int.TryParse(migrateStartString, out migrateStart)) { UnityEngine.Debug.LogError("WwiseUnity: ERROR: wwiseInstallMigrateStart is not a number."); return; } PerformMigration(migrateStart - 1); UnityEditor.AssetDatabase.SaveAssets(); UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database."); UnityEditor.AssetDatabase.Refresh(); // IMPORTANT: This log line is parsed by the Launcher. Do not modify it. UnityEngine.Debug.Log("WwiseUnity: End of setup, exiting Unity."); } catch (System.Exception e) { UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e); } } private static void MigrateCurrentScene(System.Type[] wwiseComponentTypes) { var objectTypeMap = new System.Collections.Generic.Dictionary(); foreach (var objectType in wwiseComponentTypes) { // Get all objects in the scene with the specified type. var objects = UnityEngine.Object.FindObjectsOfType(objectType); if (objects != null && objects.Length > 0) objectTypeMap[objectType] = objects; } for (var ii = AkUtilities.MigrationStartIndex; ii < AkUtilities.MigrationStopIndex; ++ii) { var migrationMethodName = "Migrate" + ii; var preMigrationMethodName = "PreMigration" + ii; var postMigrationMethodName = "PostMigration" + ii; foreach (var objectTypePair in objectTypeMap) { var objectType = objectTypePair.Key; var objects = objectTypePair.Value; var className = objectType.Name; var preMigrationMethodInfo = objectType.GetMethod(preMigrationMethodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); if (preMigrationMethodInfo != null) { UnityEngine.Debug.Log("WwiseUnity: PreMigration step <" + ii + "> for class <" + className + ">"); preMigrationMethodInfo.Invoke(null, null); } var migrationMethodInfo = objectType.GetMethod(migrationMethodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); if (migrationMethodInfo != null) { UnityEngine.Debug.Log("WwiseUnity: Migration step <" + ii + "> for class <" + className + ">"); // Call the migration method of each object. foreach (var currentObject in objects) migrationMethodInfo.Invoke(currentObject, null); } var postMigrationMethodInfo = objectType.GetMethod(postMigrationMethodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); if (postMigrationMethodInfo != null) { UnityEngine.Debug.Log("WwiseUnity: PostMigration step <" + ii + "> for class <" + className + ">"); postMigrationMethodInfo.Invoke(null, null); } } } } private static System.Type[] GetWwiseComponentTypes() { var wwiseComponentTypes = new System.Collections.Generic.List(); var wwiseComponentFolder = UnityEngine.Application.dataPath + "/Wwise/MonoBehaviour/Runtime"; if (System.IO.Directory.Exists(wwiseComponentFolder)) { var files = new System.IO.DirectoryInfo(wwiseComponentFolder).GetFiles("*.cs", System.IO.SearchOption.AllDirectories); foreach (var file in files) { var className = System.IO.Path.GetFileNameWithoutExtension(file.Name); var objectType = System.Type.GetType(className + ", AK.Wwise.Unity.MonoBehaviour"); if (objectType != null && objectType.IsSubclassOf(typeof(UnityEngine.Object))) { wwiseComponentTypes.Add(objectType); } } } return wwiseComponentTypes.ToArray(); } private static void MigrateObject(UnityEngine.Object obj) { if (obj == null) { UnityEngine.Debug.LogWarning("WwiseUnity: Missing script! Please consider resolving the missing scripts before migrating your Unity project. Any WwiseType on this object will NOT be migrated!"); return; } var migratable = obj as AK.Wwise.IMigratable; if (migratable == null && !AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6)) return; var hasChanged = false; var serializedObject = new UnityEditor.SerializedObject(obj); if (migratable != null) hasChanged = migratable.Migrate(serializedObject); else hasChanged = AK.Wwise.TypeMigration.SearchAndProcessWwiseTypes(serializedObject.GetIterator()); if (hasChanged) serializedObject.ApplyModifiedPropertiesWithoutUndo(); } private static void MigratePrefabs() { var guids = UnityEditor.AssetDatabase.FindAssets("t:Prefab", new[] { "Assets" }); for (var i = 0; i < guids.Length; i++) { UpdateProgressBar(0, i, guids.Length); var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]); UnityEngine.Debug.Log("WwiseUnity: Migrating prefab: " + path); var prefabObject = UnityEditor.AssetDatabase.LoadAssetAtPath(path); if (prefabObject == null) { UnityEngine.Debug.LogWarning("WwiseUnity: Failed to migrate prefab: " + path); continue; } var objects = prefabObject.GetComponents(); #if UNITY_2018_3_OR_NEWER var instanceIds = new System.Collections.Generic.List(); foreach (var obj in objects) { if (obj == null) continue; var id = obj.GetInstanceID(); if (!instanceIds.Contains(id)) instanceIds.Add(id); } for (; instanceIds.Count > 0; instanceIds.RemoveAt(0)) { var id = instanceIds[0]; objects = prefabObject.GetComponents(); foreach (var obj in objects) { if (obj && obj.GetInstanceID() == id) { MigrateObject(obj); break; } } } #else foreach (var obj in objects) MigrateObject(obj); #endif } } private static string[] ScriptableObjectGuids = null; private static bool ShouldProcessScriptableObject(UnityEngine.Object obj) { if (obj == null) return true; if (!(obj is UnityEngine.ScriptableObject)) return false; if (obj is UnityEngine.GUISkin) return false; if (obj is AkWwiseProjectData) return false; if (obj is AkWwiseInitializationSettings) return false; if (obj is AkCommonPlatformSettings) return false; if (obj is WwiseObjectReference) return false; return true; } private static void MigrateScriptableObjects() { var guids = ScriptableObjectGuids; if (guids == null) return; var processedGuids = new System.Collections.Generic.HashSet(); for (var i = 0; i < guids.Length; i++) { UpdateProgressBar(2, i, guids.Length); var guid = guids[i]; if (processedGuids.Contains(guid)) continue; processedGuids.Add(guid); var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid); UnityEngine.Debug.Log("WwiseUnity: Migrating ScriptableObject: " + path); var objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path); foreach (var obj in objects) { if (ShouldProcessScriptableObject(obj)) { MigrateObject(obj); } } } } private static void MigrateScenes() { var wwiseComponentTypes = GetWwiseComponentTypes(); var guids = UnityEditor.AssetDatabase.FindAssets("t:Scene", new[] { "Assets" }); for (var i = 0; i < guids.Length; i++) { UpdateProgressBar(1, i, guids.Length); var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]); UnityEngine.Debug.Log("WwiseUnity: Migrating scene: " + path); UnityEditor.EditorUtility.UnloadUnusedAssetsImmediate(); var scene = UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path); MigrateCurrentScene(wwiseComponentTypes); var objects = UnityEngine.Resources.FindObjectsOfTypeAll(); #if UNITY_2018_3_OR_NEWER var instanceIds = new System.Collections.Generic.List(); foreach (var obj in objects) { if (obj == null) continue; var id = obj.GetInstanceID(); if (!instanceIds.Contains(id)) instanceIds.Add(id); } for (; instanceIds.Count > 0; instanceIds.RemoveAt(0)) { var id = instanceIds[0]; objects = UnityEngine.Resources.FindObjectsOfTypeAll(); foreach (var obj in objects) { if (obj && obj.GetInstanceID() == id) { MigrateObject(obj); break; } } } #else foreach (var obj in objects) { var isPrefabInstance = false; if (obj != null) { #if UNITY_2018_2 isPrefabInstance = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj) != null; #else isPrefabInstance = UnityEditor.PrefabUtility.GetPrefabParent(obj) != null; #endif if (!isPrefabInstance) { var isSceneObject = !UnityEditor.EditorUtility.IsPersistent(obj); var isEditableAndSavable = (obj.hideFlags & (UnityEngine.HideFlags.NotEditable | UnityEngine.HideFlags.DontSave)) == 0; if (!isSceneObject || !isEditableAndSavable) continue; } } MigrateObject(obj); if (isPrefabInstance) UnityEditor.PrefabUtility.RecordPrefabInstancePropertyModifications(obj); } #endif if (UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene)) if (!UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene)) throw new System.Exception("Error occurred while saving migrated scenes."); UnityEditor.SceneManagement.EditorSceneManager.CloseScene(scene, true); } } public static void PerformMigration(int migrateStart) { UpdateProgressBar(0); UnityEngine.Debug.Log("WwiseUnity: Migrating from Unity Integration Version " + migrateStart + " to " + AkUtilities.MigrationStopIndex); AkPluginActivator.DeactivateAllPlugins(); AkPluginActivator.Update(); AkPluginActivator.ActivatePluginsForEditor(); // Get the name of the currently opened scene. var activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); var loadedScenePath = activeScene.path; if (!string.IsNullOrEmpty(loadedScenePath)) AkUtilities.FixSlashes(ref loadedScenePath, '\\', '/', false); UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects); // obtain a list of ScriptableObjects before any migration is performed ScriptableObjectGuids = UnityEditor.AssetDatabase.FindAssets("t:ScriptableObject", new[] { "Assets" }); AkUtilities.BeginMigration(migrateStart); if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.NewScriptableObjectFolder_v2019_2_0)) { var oldScriptableObjectPath = System.IO.Path.Combine(System.IO.Path.Combine("Assets", "Wwise"), "Resources"); AkUtilities.MoveFolder(oldScriptableObjectPath, AkWwiseEditorSettings.WwiseScriptableObjectRelativePath); } AkWwiseProjectInfo.GetData().Migrate(); AkWwiseWWUBuilder.UpdateWwiseObjectReferenceData(); MigratePrefabs(); MigrateScenes(); MigrateScriptableObjects(); UnityEditor.EditorUtility.UnloadUnusedAssetsImmediate(); UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects); AkUtilities.EndMigration(); UpdateProgressBar(TotalNumberOfSections); // Reopen the scene that was opened before the migration process started. if (!string.IsNullOrEmpty(loadedScenePath)) UnityEditor.SceneManagement.EditorSceneManager.OpenScene(loadedScenePath); UnityEngine.Debug.Log("WwiseUnity: Removing lock for launcher."); // TODO: Moving one folder up is not nice at all. How to find the current project path? try { System.IO.File.Delete(UnityEngine.Application.dataPath + "/../.WwiseLauncherLockFile"); } catch { // Ignore if not present. } UnityEditor.EditorUtility.ClearProgressBar(); } public static void ModifySetup() { var currentConfig = AkPluginActivator.GetCurrentConfig(); if (string.IsNullOrEmpty(currentConfig)) currentConfig = AkPluginActivator.CONFIG_PROFILE; AkPluginActivator.DeactivateAllPlugins(); AkPluginActivator.Update(); AkPluginActivator.ActivatePluginsForEditor(); } // Perform all necessary steps to use the Wwise Unity integration. private static void Setup() { UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects); AkPluginActivator.DeactivateAllPlugins(); // 0. Make sure the SoundBank directory exists var sbPath = AkUtilities.GetFullPath(UnityEngine.Application.streamingAssetsPath, AkWwiseEditorSettings.Instance.SoundbankPath); if (!System.IO.Directory.Exists(sbPath)) System.IO.Directory.CreateDirectory(sbPath); // 1. Disable built-in audio if (!DisableBuiltInAudio()) { UnityEngine.Debug.LogWarning( "WwiseUnity: Could not disable built-in audio. Please disable built-in audio by going to Project->Project Settings->Audio, and check \"Disable Audio\"."); } // 2. Create a "WwiseGlobal" game object and set the AkSoundEngineInitializer and terminator scripts // 3. Set the SoundBank path property on AkSoundEngineInitializer CreateWwiseGlobalObject(); // 5. Disable the built-in audio listener, and add AkAudioListener component to camera if (AkWwiseEditorSettings.Instance.CreateWwiseListener) { AddAkAudioListenerToMainCamera(); } // 6. Enable "Run In Background" in PlayerSettings (PlayerSettings.runInbackground property) UnityEditor.PlayerSettings.runInBackground = true; AkPluginActivator.Update(); AkPluginActivator.ActivatePluginsForEditor(); // 9. Activate WwiseIDs file generation, and point Wwise to the Assets/Wwise folder // 10. Change the SoundBanks options so it adds Max Radius information in the Wwise project if (!SetSoundbankSettings()) UnityEngine.Debug.LogWarning("WwiseUnity: Could not modify Wwise Project to generate the header file!"); // 11. Activate XboxOne network sockets. AkXboxOneUtils.EnableXboxOneNetworkSockets(); } // Create a Wwise Global object containing the initializer and terminator scripts. Set the SoundBank path of the initializer script. // This game object will live for the whole project; there is no need to instanciate one per scene. private static void CreateWwiseGlobalObject() { // Look for a game object which has the initializer component var AkInitializers = UnityEngine.Object.FindObjectsOfType(); if (AkInitializers.Length > 0) UnityEditor.Undo.DestroyObjectImmediate(AkInitializers[0].gameObject); var WwiseGlobalGameObject = new UnityEngine.GameObject("WwiseGlobal"); // attach initializer component UnityEditor.Undo.AddComponent(WwiseGlobalGameObject); // Set focus on WwiseGlobal UnityEditor.Selection.activeGameObject = WwiseGlobalGameObject; } private static bool DisableBuiltInAudio() { UnityEditor.SerializedObject audioSettingsAsset = null; UnityEditor.SerializedProperty disableAudioProperty = null; var assets = UnityEditor.AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/AudioManager.asset"); if (assets.Length > 0) audioSettingsAsset = new UnityEditor.SerializedObject(assets[0]); if (audioSettingsAsset != null) disableAudioProperty = audioSettingsAsset.FindProperty("m_DisableAudio"); if (disableAudioProperty == null) return false; disableAudioProperty.boolValue = true; audioSettingsAsset.ApplyModifiedProperties(); return true; } // Modify the .wproj file to set needed SoundBank settings private static bool SetSoundbankSettings() { var settings = AkWwiseEditorSettings.Instance; if (string.IsNullOrEmpty(settings.WwiseProjectPath)) return true; var r = new System.Text.RegularExpressions.Regex("_WwiseIntegrationTemp.*?([/\\\\])"); var SoundbankPath = AkUtilities.GetFullPath(r.Replace(UnityEngine.Application.streamingAssetsPath, "$1"), settings.SoundbankPath); var WprojPath = AkUtilities.GetFullPath(UnityEngine.Application.dataPath, settings.WwiseProjectPath); #if UNITY_EDITOR_OSX SoundbankPath = "Z:" + SoundbankPath; #endif SoundbankPath = AkUtilities.MakeRelativePath(System.IO.Path.GetDirectoryName(WprojPath), SoundbankPath); if (AkUtilities.EnableBoolSoundbankSettingInWproj("SoundBankGenerateHeaderFile", WprojPath)) if (AkUtilities.SetSoundbankHeaderFilePath(WprojPath, SoundbankPath)) return AkUtilities.EnableBoolSoundbankSettingInWproj("SoundBankGenerateMaxAttenuationInfo", WprojPath); return false; } public static void AddAkAudioListenerToMainCamera(bool logWarning = false) { UnityEngine.Camera camera = UnityEngine.Camera.main; // Workaround for some versions of Unity not setting properly the MainCamera tag // on the first scene of a new project if (camera == null) { var cameraArray = UnityEngine.Object.FindObjectsOfType(); if (cameraArray.Length > 0) { foreach (var entry in cameraArray) { if (entry.name == "Main Camera") { camera = entry; break; } } } if (camera == null) { return; } } if (camera.GetComponentInChildren()) { return; } var oldListener = camera.gameObject.GetComponent(); if (oldListener != null) { UnityEditor.Undo.DestroyObjectImmediate(oldListener); } var akAudioListener = UnityEditor.Undo.AddComponent(camera.gameObject); if (!akAudioListener) { return; } var akGameObj = akAudioListener.GetComponentInChildren(); if (akGameObj) { akGameObj.isEnvironmentAware = false; } if (logWarning) { UnityEngine.Debug.LogWarning("Automatically added AkAudioListener to Main Camera. Go to \"Edit > Wwise Settings...\" to disable this functionality."); } } } #endif // UNITY_EDITOR