Feat : Wwise Integration
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using AK.Wwise.Unity.Logging;
|
||||
|
||||
public partial class AkBuildPreprocessor
|
||||
{
|
||||
/// <summary>
|
||||
/// User hook called to retrieve the custom platform name used to determine the base path. Do not modify platformName
|
||||
/// to use default platform names.
|
||||
/// </summary>
|
||||
/// <param name="platformName">The custom platform name.</param>
|
||||
public delegate void CustomPlatformNameGetter(ref string platformName, UnityEditor.BuildTarget target);
|
||||
|
||||
public static CustomPlatformNameGetter GetCustomPlatformName;
|
||||
|
||||
public delegate void OnBuildCallback(string path);
|
||||
|
||||
public static void BuildCallbackNoOp(string path)
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
public class PlatformConfiguration
|
||||
{
|
||||
public string WwisePlatformName;
|
||||
public OnBuildCallback OnPreprocessBuild = BuildCallbackNoOp;
|
||||
public OnBuildCallback OnPostprocessBuild = BuildCallbackNoOp;
|
||||
}
|
||||
|
||||
private static Dictionary<UnityEditor.BuildTarget, PlatformConfiguration> PlatformConfigurations = new Dictionary<UnityEditor.BuildTarget, PlatformConfiguration>();
|
||||
|
||||
public static void RegisterBuildTarget(UnityEditor.BuildTarget target, PlatformConfiguration config)
|
||||
{
|
||||
PlatformConfigurations.Add(target, config);
|
||||
}
|
||||
|
||||
public static string GetPlatformName(UnityEditor.BuildTarget target)
|
||||
{
|
||||
var platformSubDir = string.Empty;
|
||||
GetCustomPlatformName?.Invoke(ref platformSubDir, target);
|
||||
|
||||
if (!string.IsNullOrEmpty(platformSubDir))
|
||||
return platformSubDir;
|
||||
|
||||
//New way to access target platform name
|
||||
string platformName = AkBasePathGetter.GetTargetPlatformName(target);
|
||||
if (platformName != string.Empty)
|
||||
{
|
||||
return platformName;
|
||||
}
|
||||
|
||||
//For legacy code compatibility. Should maybe remove in 26.1 or 27.1 to give time to adjust
|
||||
if (PlatformConfigurations.ContainsKey(target))
|
||||
{
|
||||
if (platformName == string.Empty)
|
||||
{
|
||||
platformName = PlatformConfigurations[target].WwisePlatformName;
|
||||
}
|
||||
return platformName;
|
||||
}
|
||||
//Keeping the old fallback of using the Unity target name.
|
||||
return target.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
public partial class AkBuildPreprocessor : UnityEditor.Build.IPreprocessBuildWithReport, UnityEditor.Build.IPostprocessBuildWithReport
|
||||
#else
|
||||
public partial class AkBuildPreprocessor : UnityEditor.Build.IPreprocessBuild, UnityEditor.Build.IPostprocessBuild
|
||||
#endif
|
||||
{
|
||||
public int callbackOrder
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
private string destinationSoundBankFolder = string.Empty;
|
||||
|
||||
public static bool CopySoundbanks(bool generate, string platformName, ref string destinationFolder)
|
||||
{
|
||||
if (string.IsNullOrEmpty(platformName))
|
||||
{
|
||||
WwiseLogger.ErrorFormat("Could not determine platform name for <{0}> platform", platformName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (generate)
|
||||
{
|
||||
var platforms = new System.Collections.Generic.List<string> { platformName };
|
||||
string wwiseInstallationPath = "";
|
||||
#if UNITY_EDITOR_WIN
|
||||
wwiseInstallationPath = AkWwiseEditorSettings.Instance.WwiseInstallationPathWindows;
|
||||
#elif UNITY_EDITOR_OSX
|
||||
wwiseInstallationPath = AkWwiseEditorSettings.Instance.WwiseInstallationPathMac;
|
||||
#endif
|
||||
AkUtilities.GenerateSoundbanks(wwiseInstallationPath, AkWwiseEditorSettings.WwiseProjectAbsolutePath, platforms);
|
||||
}
|
||||
|
||||
string sourceFolder;
|
||||
if (!AkBasePathGetter.GetSoundBankPaths(platformName, out sourceFolder, out destinationFolder))
|
||||
return false;
|
||||
|
||||
if (!AkUtilities.DirectoryCopy(sourceFolder, destinationFolder, true))
|
||||
{
|
||||
destinationFolder = null;
|
||||
WwiseLogger.ErrorFormat("Could not copy SoundBank folder for <{0}> platform", platformName);
|
||||
return false;
|
||||
}
|
||||
|
||||
WwiseLogger.Log($"Copied SoundBank folder from <{sourceFolder}> to streaming assets folder <{destinationFolder}> for <{platformName}> platform build");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static void DeleteSoundbanks(string destinationFolder)
|
||||
{
|
||||
if (string.IsNullOrEmpty(destinationFolder))
|
||||
return;
|
||||
|
||||
System.IO.Directory.Delete(destinationFolder, true);
|
||||
WwiseLogger.LogFormat("Deleting streaming assets folder <{0}>", destinationFolder);
|
||||
}
|
||||
|
||||
public void OnPreprocessBuildInternal(UnityEditor.BuildTarget target, string path)
|
||||
{
|
||||
var platformName = GetPlatformName(target);
|
||||
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
|
||||
if (AkWwiseEditorSettings.Instance.CopySoundBanksAsPreBuildStep)
|
||||
{
|
||||
if (!CopySoundbanks(AkWwiseEditorSettings.Instance.GenerateSoundBanksAsPreBuildStep, platformName, ref destinationSoundBankFolder))
|
||||
{
|
||||
WwiseLogger.ErrorFormat("SoundBank folder has not been copied for <{0}> target at <{1}>. This will likely result in a build without sound!!!", target, path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (PlatformConfigurations.TryGetValue(target, out var config))
|
||||
{
|
||||
config.OnPreprocessBuild(path);
|
||||
}
|
||||
|
||||
// Init ProjectDB for platform being built
|
||||
WwiseProjectDatabase.Init(AkWwiseEditorSettings.GetRootOutputPath(), platformName);
|
||||
AkPluginActivator.ForceUpdate();
|
||||
AkPluginActivator.ActivatePluginsForDeployment(target, true);
|
||||
}
|
||||
|
||||
public void OnPostprocessBuildInternal(UnityEditor.BuildTarget target, string path)
|
||||
{
|
||||
AkPluginActivator.ActivatePluginsForDeployment(target, false);
|
||||
if (PlatformConfigurations.TryGetValue(target, out var config))
|
||||
{
|
||||
config.OnPostprocessBuild(path);
|
||||
}
|
||||
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
|
||||
DeleteSoundbanks(destinationSoundBankFolder);
|
||||
#endif
|
||||
destinationSoundBankFolder = string.Empty;
|
||||
|
||||
// Point the ProjectDB back on the current editor platform
|
||||
WwiseProjectDatabase.Init(AkWwiseEditorSettings.GetRootOutputPath(), AkBasePathGetter.GetPlatformName());
|
||||
}
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
|
||||
{
|
||||
OnPreprocessBuildInternal(report.summary.platform, report.summary.outputPath);
|
||||
}
|
||||
|
||||
public void OnPostprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
|
||||
{
|
||||
OnPostprocessBuildInternal(report.summary.platform, report.summary.outputPath);
|
||||
}
|
||||
#else
|
||||
public void OnPreprocessBuild(UnityEditor.BuildTarget target, string path)
|
||||
{
|
||||
OnPreprocessBuildInternal(target, path);
|
||||
}
|
||||
|
||||
public void OnPostprocessBuild(UnityEditor.BuildTarget target, string path)
|
||||
{
|
||||
OnPostprocessBuildInternal(target, path);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // #if UNITY_EDITOR
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5cf5d16f083391b4a8681b007ca2f85c
|
||||
@@ -0,0 +1,142 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
|
||||
// Note, this code was only written to parse the AudioManager.asset file.
|
||||
// It has been written to try to be as generic as possible, but might not
|
||||
// work on other .asset settings files.
|
||||
public class AkUnitySettingsParser
|
||||
{
|
||||
public static bool SetBoolValue(string ValueName, bool ValueToSet, string ConfigFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var SettingsPath = UnityEngine.Application.dataPath.Remove(UnityEngine.Application.dataPath.LastIndexOf("/")) +
|
||||
"/ProjectSettings/" + ConfigFileName + ".asset";
|
||||
|
||||
System.IO.FileStream fs;
|
||||
System.IO.BinaryReader br;
|
||||
fs = System.IO.File.Open(SettingsPath, System.IO.FileMode.Open);
|
||||
br = new System.IO.BinaryReader(fs);
|
||||
|
||||
// Read the unsigned int at offset 0x0C in the file.
|
||||
// This contains the offset at which the setting's numerical values are stored.
|
||||
br.BaseStream.Seek(0x0C, System.IO.SeekOrigin.Begin);
|
||||
|
||||
// For some reason, the offset is Big Endian in the file.
|
||||
var SettingsOffset = GetBigEndianIntFromBinaryReader(br);
|
||||
|
||||
// In the file, we start with 0x14 bytes, then a string containing the unity version,
|
||||
// then 0x0C bytes, then a string containing the base class name, followed by a string containing "base".
|
||||
string tempStr;
|
||||
br.BaseStream.Seek(0x14, System.IO.SeekOrigin.Begin);
|
||||
tempStr = GetStringFromBinaryReader(br); // Unity Version
|
||||
br.BaseStream.Seek(0x0C, System.IO.SeekOrigin.Current);
|
||||
tempStr = GetStringFromBinaryReader(br); // Config file Name
|
||||
if (tempStr != ConfigFileName)
|
||||
return false;
|
||||
|
||||
tempStr = GetStringFromBinaryReader(br); // "Base"
|
||||
if (tempStr != "Base")
|
||||
return false;
|
||||
|
||||
// This string is then followed by 24 bytes
|
||||
br.BaseStream.Seek(24, System.IO.SeekOrigin.Current);
|
||||
|
||||
// We then have a series of String (type), String (variable name), and 24 bytes
|
||||
// We can use the type of the settings before the field we are looking for to
|
||||
// find its offset after SettingsOffset.
|
||||
while (br.BaseStream.Position < br.BaseStream.Length)
|
||||
{
|
||||
var SettingType = GetStringFromBinaryReader(br);
|
||||
var SettingName = GetStringFromBinaryReader(br);
|
||||
|
||||
if (SettingName == ValueName)
|
||||
break;
|
||||
|
||||
br.BaseStream.Seek(24, System.IO.SeekOrigin.Current);
|
||||
|
||||
if (GetSizeofTypeByString(SettingType) == -1)
|
||||
return false;
|
||||
|
||||
SettingsOffset += GetSizeofTypeByString(SettingType);
|
||||
}
|
||||
|
||||
// Set the setting in the file
|
||||
var bw = new System.IO.BinaryWriter(fs);
|
||||
bw.Seek(SettingsOffset, System.IO.SeekOrigin.Begin);
|
||||
bw.Write(ValueToSet ? (byte) 1 : (byte) 0);
|
||||
bw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
// Error happened
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success!
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read a big endian Int, and advances the BinaryReader's position
|
||||
private static int GetBigEndianIntFromBinaryReader(System.IO.BinaryReader br)
|
||||
{
|
||||
var tempBytes = new byte[4];
|
||||
tempBytes = br.ReadBytes(4);
|
||||
return (tempBytes[0] << 24) | (tempBytes[1] << 16) | (tempBytes[2] << 8) | tempBytes[3];
|
||||
}
|
||||
|
||||
// Reads a zero-terminated string at the BinaryReader's current position, and advances position
|
||||
private static string GetStringFromBinaryReader(System.IO.BinaryReader br)
|
||||
{
|
||||
var list = new System.Collections.Generic.List<byte>();
|
||||
|
||||
// Do not add the \0 in the string, because comparison won't work
|
||||
var currentByte = br.ReadByte();
|
||||
while (currentByte != 0)
|
||||
{
|
||||
list.Add(currentByte);
|
||||
currentByte = br.ReadByte();
|
||||
}
|
||||
|
||||
return System.Text.Encoding.Default.GetString(list.ToArray());
|
||||
}
|
||||
|
||||
// Returns the size in bytes of a type, as specified in the .asset file
|
||||
// NOTE: this function only supports types found in AudioManager.asset.
|
||||
private static int GetSizeofTypeByString(string typeStr)
|
||||
{
|
||||
switch (typeStr)
|
||||
{
|
||||
case "int":
|
||||
case "unsigned int":
|
||||
case "float":
|
||||
case "UInt32":
|
||||
case "SInt32":
|
||||
return 4;
|
||||
case "bool":
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UNITY_EDITOR
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0e5c350f4eb2c541afb59c6c7203386
|
||||
@@ -0,0 +1,403 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using AK.Wwise.Unity.Logging;
|
||||
|
||||
[UnityEditor.InitializeOnLoad]
|
||||
public class AkWwisePostImportCallbackSetup
|
||||
{
|
||||
private static int m_scheduledMigrationStart;
|
||||
private static bool m_scheduledReturnToLauncher;
|
||||
private static bool m_pendingExecuteMethodCalled;
|
||||
private static string s_CurrentScene;
|
||||
|
||||
static AkWwisePostImportCallbackSetup()
|
||||
{
|
||||
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var arguments = System.Environment.GetCommandLineArgs();
|
||||
if (UnityEngine.Application.isBatchMode
|
||||
&& System.Array.IndexOf(arguments, "-wwiseEnableWithNoGraphics") == -1)
|
||||
return;
|
||||
|
||||
UnityEditor.EditorApplication.delayCall += CheckMigrationStatus;
|
||||
|
||||
AkUtilities.GetEventDurations = (uint eventID, ref float maximum, ref float minimum) =>
|
||||
{
|
||||
var eventInfo = AkWwiseProjectInfo.GetData().GetEventInfo(eventID);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
minimum = eventInfo.minDuration;
|
||||
maximum = eventInfo.maxDuration;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void CheckMigrationStatus()
|
||||
{
|
||||
try
|
||||
{
|
||||
int migrationStart;
|
||||
bool returnToLauncher;
|
||||
if (IsMigrationPending(out migrationStart, out returnToLauncher))
|
||||
{
|
||||
m_scheduledMigrationStart = migrationStart;
|
||||
m_scheduledReturnToLauncher = returnToLauncher;
|
||||
ScheduleMigration();
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshCallback();
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
WwiseLogger.Error("Error during migration: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ScheduleMigration()
|
||||
{
|
||||
// TODO: Is delayCall wiped out during a script reload?
|
||||
// If not, guard against having a delayCall from a previously loaded code being run after the new loading.
|
||||
|
||||
if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || UnityEditor.EditorApplication.isCompiling)
|
||||
{
|
||||
// Skip if not in the right mode, wait for the next callback to see if we can proceed then.
|
||||
UnityEditor.EditorApplication.delayCall += ScheduleMigration;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
WwiseSetupWizard.PerformMigration(m_scheduledMigrationStart);
|
||||
|
||||
// Force the user to return to the launcher to perform the post-installation process if necessary
|
||||
if (m_scheduledReturnToLauncher)
|
||||
{
|
||||
if (UnityEditor.EditorUtility.DisplayDialog("Wwise Migration Successful!",
|
||||
"Please close Unity and go back to the Wwise Launcher to complete the installation.", "Quit"))
|
||||
UnityEditor.EditorApplication.Exit(0);
|
||||
}
|
||||
else
|
||||
UnityEditor.EditorApplication.delayCall += RefreshCallback;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
WwiseLogger.Error("Error during migration: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsMigrationPending(out int migrationStart, out bool returnToLauncher)
|
||||
{
|
||||
migrationStart = 0;
|
||||
returnToLauncher = false;
|
||||
|
||||
var filename = UnityEngine.Application.dataPath + "/../.WwiseLauncherLockFile";
|
||||
|
||||
if (!System.IO.File.Exists(filename))
|
||||
return false;
|
||||
|
||||
var fileContent = System.IO.File.ReadAllText(filename);
|
||||
|
||||
// Instantiate the regular expression object.
|
||||
var r = new System.Text.RegularExpressions.Regex(
|
||||
"{\"migrateStart\":(\\d+),\"migrateStop\":(\\d+)(,\"returnToLauncher\":(true|false))?,.*}",
|
||||
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
|
||||
// Match the regular expression pattern against a text string.
|
||||
var m = r.Match(fileContent);
|
||||
|
||||
if (!m.Success || m.Groups.Count < 2 || m.Groups[1].Captures.Count < 1 || m.Groups[2].Captures.Count < 1 ||
|
||||
!int.TryParse(m.Groups[1].Captures[0].ToString(), out migrationStart))
|
||||
throw new System.Exception("Error in the file format of .WwiseLauncherLockFile.");
|
||||
|
||||
// Handle optional properties
|
||||
if (m.Groups.Count > 3 && m.Groups[4].Captures.Count > 0)
|
||||
bool.TryParse(m.Groups[4].Captures[0].ToString(), out returnToLauncher);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void RefreshCallback()
|
||||
{
|
||||
PostImportFunction();
|
||||
if (WwiseSettings.Exists)
|
||||
{
|
||||
AkPluginActivator.Update();
|
||||
AkPluginActivator.ActivatePluginsForEditor();
|
||||
}
|
||||
}
|
||||
|
||||
private static void PostImportFunction()
|
||||
{
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
UnityEditor.EditorApplication.hierarchyChanged += CheckWwiseGlobalExistance;
|
||||
#else
|
||||
UnityEditor.EditorApplication.hierarchyWindowChanged += CheckWwiseGlobalExistance;
|
||||
#endif
|
||||
UnityEditor.EditorApplication.delayCall += CheckPicker;
|
||||
|
||||
if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || UnityEditor.EditorApplication.isCompiling)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(AkWwiseEditorSettings.Instance.WwiseProjectPath))
|
||||
{
|
||||
AkWwiseBrowser.Refresh(ignoreIfWaapi: true);
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
WwiseLogger.Log(e.ToString());
|
||||
}
|
||||
|
||||
//Check if a WwiseGlobal object exists in the current scene
|
||||
CheckWwiseGlobalExistance();
|
||||
}
|
||||
|
||||
private static void RefreshPlugins()
|
||||
{
|
||||
if (string.IsNullOrEmpty(AkWwiseProjectInfo.GetData().CurrentPluginConfig))
|
||||
AkWwiseProjectInfo.GetData().CurrentPluginConfig = AkPluginActivatorConstants.CONFIG_PROFILE;
|
||||
|
||||
AkPluginActivator.ActivatePluginsForEditor();
|
||||
}
|
||||
|
||||
public static void CheckPicker()
|
||||
{
|
||||
if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || UnityEditor.EditorApplication.isCompiling)
|
||||
{
|
||||
// Skip if not in the right mode, wait for the next callback to see if we can proceed then.
|
||||
UnityEditor.EditorApplication.delayCall += CheckPicker;
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = AkWwiseEditorSettings.Instance;
|
||||
if (!settings.CreatedPicker)
|
||||
{
|
||||
// Delete all the ghost tabs (Failed to load).
|
||||
var windows = UnityEngine.Resources.FindObjectsOfTypeAll<UnityEditor.EditorWindow>();
|
||||
if (windows != null && windows.Length > 0)
|
||||
{
|
||||
foreach (var window in windows)
|
||||
{
|
||||
var windowTitle = window.titleContent.text;
|
||||
|
||||
if (windowTitle.Equals("Failed to load") || windowTitle.Equals("AkWwisePicker"))
|
||||
{
|
||||
try
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Do nothing here, this shouldn't cause any problem, however there has been
|
||||
// occurrences of Unity crashing on a null reference inside that method.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: If no scene is loaded and we are using the demo scene, automatically load it to display it.
|
||||
|
||||
// Populate the picker
|
||||
AkWwiseProjectInfo.GetData(); // Load data
|
||||
if (!string.IsNullOrEmpty(settings.WwiseProjectPath))
|
||||
{
|
||||
AkWwiseProjectInfo.Populate();
|
||||
AkWwiseBrowser.InitBrowserWindow();
|
||||
|
||||
settings.CreatedPicker = true;
|
||||
settings.SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
UnityEditor.EditorApplication.delayCall += CheckPendingExecuteMethod;
|
||||
}
|
||||
|
||||
// TODO: Put this in AkUtilities?
|
||||
private static void ExecuteMethod(string method)
|
||||
{
|
||||
string className = null;
|
||||
string methodName = null;
|
||||
|
||||
var regex = new System.Text.RegularExpressions.Regex("(.+)\\.(.+)",
|
||||
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
|
||||
var regexMatchResult = regex.Match(method);
|
||||
|
||||
if (!regexMatchResult.Success || regexMatchResult.Groups.Count < 3 || regexMatchResult.Groups[1].Captures.Count < 1 || regexMatchResult.Groups[2].Captures.Count < 1)
|
||||
{
|
||||
WwiseLogger.Error("Error parsing wwiseExecuteMethod parameter: " + method);
|
||||
return;
|
||||
}
|
||||
|
||||
className = regexMatchResult.Groups[1].Captures[0].ToString();
|
||||
methodName = regexMatchResult.Groups[2].Captures[0].ToString();
|
||||
|
||||
try
|
||||
{
|
||||
System.Reflection.MethodInfo methodToExecute = null;
|
||||
|
||||
if (className == "AkTestUtilities")
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.Load("Ak.Wwise.IntegrationTestsEditor");
|
||||
methodToExecute = assembly.GetType(className).GetMethod(methodName,
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = System.Type.GetType(className);
|
||||
if (type == null)
|
||||
{
|
||||
type = System.Type.GetType(className + ", Assembly-CSharp-Editor");
|
||||
}
|
||||
methodToExecute = type.GetMethod(methodName,
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
|
||||
}
|
||||
|
||||
if (methodToExecute == null)
|
||||
{
|
||||
WwiseLogger.Error("Error in AkWwisePostImportCallbackSetup::ExecuteMethod(): Could not find method: " + method);
|
||||
return;
|
||||
}
|
||||
|
||||
methodToExecute.Invoke(null, null);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
WwiseLogger.Error("Exception caught when calling " + method + ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckPendingExecuteMethod()
|
||||
{
|
||||
var arguments = System.Environment.GetCommandLineArgs();
|
||||
var indexOfCommand = System.Array.IndexOf(arguments, "-wwiseExecuteMethod");
|
||||
|
||||
if (!m_pendingExecuteMethodCalled && indexOfCommand != -1 && arguments.Length > indexOfCommand + 1)
|
||||
{
|
||||
var methodToExecute = arguments[indexOfCommand + 1];
|
||||
|
||||
ExecuteMethod(methodToExecute);
|
||||
m_pendingExecuteMethodCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Called when changes are made to the scene and when a new scene is created.
|
||||
public static void CheckWwiseGlobalExistance()
|
||||
{
|
||||
var activeSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
|
||||
if (!string.IsNullOrEmpty(s_CurrentScene) && s_CurrentScene.Equals(activeSceneName))
|
||||
return;
|
||||
|
||||
var settings = AkWwiseEditorSettings.Instance;
|
||||
// Look for a game object which has the initializer component
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
var AkInitializers = Object.FindObjectsByType<AkInitializer>(FindObjectsSortMode.None);
|
||||
#else
|
||||
var AkInitializers = Object.FindObjectsOfType<AkInitializer>();
|
||||
#endif
|
||||
if (AkInitializers.Length == 0)
|
||||
{
|
||||
if (settings.CreateWwiseGlobal)
|
||||
{
|
||||
WwiseLogger.LogFormat("No Wwise object in the scene ({0}), creating one.", s_CurrentScene);
|
||||
//No Wwise object in this scene, create one so that the sound engine is initialized and terminated properly even if the scenes are loaded
|
||||
//in the wrong order.
|
||||
var objWwise = new UnityEngine.GameObject("WwiseGlobal");
|
||||
|
||||
//Attach initializer and terminator components
|
||||
AkInitializer akInitializer;
|
||||
if (AkUtilities.IsRunningTest())
|
||||
{
|
||||
akInitializer = objWwise.AddComponent<AkInitializer>();
|
||||
}
|
||||
else
|
||||
{
|
||||
akInitializer = UnityEditor.Undo.AddComponent<AkInitializer>(objWwise);
|
||||
}
|
||||
akInitializer.InitializeInitializationSettings();
|
||||
|
||||
}
|
||||
}
|
||||
else if (AkInitializers.Length > 0)
|
||||
{
|
||||
foreach(AkInitializer Initializer in AkInitializers)
|
||||
{
|
||||
if (!Initializer.InitializationSettings)
|
||||
{
|
||||
WwiseLogger.LogFormat("Initializing {0} (GO {1}).", Initializer.name, Initializer.gameObject.name);
|
||||
Initializer.InitializeInitializationSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (settings.CreateWwiseGlobal == false && AkInitializers[0].gameObject.name == "WwiseGlobal")
|
||||
{
|
||||
WwiseLogger.LogFormat("CreateWwiseGlobal is false. Removing the AkInitializer in scene ({0}).", s_CurrentScene);
|
||||
UnityEditor.Undo.DestroyObjectImmediate(AkInitializers[0].gameObject);
|
||||
}
|
||||
|
||||
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
|
||||
var bankHolder = UnityEngine.Object.FindObjectOfType<AK.Wwise.Unity.WwiseAddressables.InitBankHolder>();
|
||||
if (bankHolder == null)
|
||||
{
|
||||
UnityEngine.GameObject wwiseGlobalObject = UnityEngine.GameObject.Find("WwiseGlobal");
|
||||
if (wwiseGlobalObject != null)
|
||||
{
|
||||
bankHolder = UnityEditor.Undo.AddComponent<AK.Wwise.Unity.WwiseAddressables.InitBankHolder>(wwiseGlobalObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (bankHolder!=null && bankHolder.InitBank == null)
|
||||
{
|
||||
#if WWISE_ADDRESABLES_2022_1_0_OR_NEWER
|
||||
var initBankPath = System.IO.Path.Combine(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath, "InitBank.asset");
|
||||
var initbank = UnityEditor.AssetDatabase.LoadAssetAtPath<AK.Wwise.Unity.WwiseAddressables.WwiseInitBankReference>(initBankPath);
|
||||
if (initbank)
|
||||
{
|
||||
bankHolder.InitBank = initbank;
|
||||
EditorUtility.SetDirty(bankHolder);
|
||||
}
|
||||
#else
|
||||
var initBankPath = System.IO.Path.Combine("Assets",settings.RootOutputPath,"Init.asset");
|
||||
var initbank = UnityEditor.AssetDatabase.LoadAssetAtPath<AK.Wwise.Unity.WwiseAddressables.WwiseAddressableSoundBank>(initBankPath);
|
||||
bankHolder.InitBank = initbank;
|
||||
EditorUtility.SetDirty(bankHolder);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if (settings.CreateWwiseListener)
|
||||
{
|
||||
WwiseSetupWizard.AddAkAudioListenerToMainCamera(true);
|
||||
}
|
||||
|
||||
s_CurrentScene = activeSceneName;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UNITY_EDITOR
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 159bb4fd4c40a30499af5da93084cf22
|
||||
@@ -0,0 +1,858 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEngine;
|
||||
|
||||
public class WwiseSetupWizard
|
||||
{
|
||||
static Dictionary<int, string> WwiseAddressableDefines = new Dictionary<int, string>()
|
||||
{
|
||||
{2023, "WWISE_ADDRESSABLES_23_1_OR_LATER"},
|
||||
{2024, "WWISE_ADDRESSABLES_24_1_OR_LATER"}
|
||||
};
|
||||
|
||||
static Dictionary<int, string> WwiseVersionDefines = new Dictionary<int, string>()
|
||||
{
|
||||
{2024, "WWISE_2024_OR_LATER"}
|
||||
};
|
||||
|
||||
//Change this when an API change is introduced that would break older version of the addrerssables package
|
||||
private static string WwiseAddressableAPIDefine = "ADDRESSABLES_API_BROWSER_TREE_VIEW";
|
||||
|
||||
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<System.Type, UnityEngine.Object[]>();
|
||||
|
||||
foreach (var objectType in wwiseComponentTypes)
|
||||
{
|
||||
// Get all objects in the scene with the specified type.
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
var objects = UnityEngine.Object.FindObjectsByType(objectType, FindObjectsSortMode.None);
|
||||
#else
|
||||
var objects = UnityEngine.Object.FindObjectsOfType(objectType);
|
||||
#endif
|
||||
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<System.Type>();
|
||||
|
||||
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()
|
||||
{
|
||||
// The only migration operation done in this method is to call MigrateObject on MonoBehaviours attached to prefabs.
|
||||
// MigrateObject only runs if a migration is required for the "WwiseTypes_v2018_1_6" migration step.
|
||||
// Add an early return here to avoid lots of potentially slow code if we are in a case where MigrateObject would
|
||||
// do nothing.
|
||||
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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<UnityEngine.GameObject>(path);
|
||||
if (prefabObject == null)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("WwiseUnity: Failed to migrate prefab: " + path);
|
||||
continue;
|
||||
}
|
||||
|
||||
var objects = prefabObject.GetComponents<UnityEngine.MonoBehaviour>();
|
||||
// The rather convoluted way of iterating through all objects here has a very specific reason.
|
||||
// The call to MigrateObject ends up calling SerializedObject.ApplyModifiedPropertiesWithoutUndo.
|
||||
// This function call will invalidate all references that are held by the code that is running
|
||||
// (the objects array here).
|
||||
// In order to iterate properly on all MonoBehaviours available, we get their instance IDs,
|
||||
// which do not change when Applying modified properties. Then, for each iteration of the
|
||||
// migration loop, we need to get a valid array of MonoBehaviours again, because it might
|
||||
// have been invalidated by the call to MigrateObject. We then migrate the objects that
|
||||
// need migration by making sure their InstanceID is in the list of unmigrated MonoBehaviours.
|
||||
var instanceIds = new System.Collections.Generic.List<int>();
|
||||
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];
|
||||
var obj = UnityEditor.EditorUtility.InstanceIDToObject(id);
|
||||
if (obj && obj.GetInstanceID() == id)
|
||||
{
|
||||
MigrateObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 AkWwiseInitializationSettings)
|
||||
return false;
|
||||
|
||||
if (obj is AkCommonPlatformSettings)
|
||||
return false;
|
||||
|
||||
if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.AutoDefinedSoundBanks_v2023_1_0) &&
|
||||
obj is WwiseEventReference)
|
||||
return true;
|
||||
|
||||
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<string>();
|
||||
|
||||
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);
|
||||
|
||||
var objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (ShouldProcessScriptableObject(obj))
|
||||
{
|
||||
UnityEngine.Debug.Log("WwiseUnity: Migrating ScriptableObject: " + path);
|
||||
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);
|
||||
|
||||
// From this point on, the only migration operation done in this loop is to call MigrateObject on MonoBehaviours.
|
||||
// MigrateObject only runs if a migration is required for the "WwiseTypes_v2018_1_6" migration step. Simply
|
||||
// continue the loop here to avoid lots of potentially slow code if we are in a case where MigrateObject would
|
||||
// do nothing.
|
||||
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var objects = UnityEngine.Resources.FindObjectsOfTypeAll<UnityEngine.MonoBehaviour>();
|
||||
|
||||
// The rather convoluted way of iterating through all objects here has a very specific reason.
|
||||
// The call to MigrateObject ends up calling SerializedObject.ApplyModifiedPropertiesWithoutUndo.
|
||||
// This function call will invalidate all references that are held by the code that is running
|
||||
// (the objects array here).
|
||||
// In order to iterate properly on all MonoBehaviours available, we get their instance IDs,
|
||||
// which do not change when Applying modified properties. Then, for each iteration of the
|
||||
// migration loop, we need to get a valid array of MonoBehaviours again, because it might
|
||||
// have been invalidated by the call to MigrateObject. We then migrate the objects that
|
||||
// need migration by making sure their InstanceID is in the list of unmigrated MonoBehaviours.
|
||||
var instanceIds = new System.Collections.Generic.List<int>();
|
||||
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];
|
||||
var obj = UnityEditor.EditorUtility.InstanceIDToObject(id);
|
||||
if (obj && obj.GetInstanceID() == id)
|
||||
{
|
||||
MigrateObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
AkUtilities.BeginMigration(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" });
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (!UnityEditor.AssetDatabase.IsValidFolder(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath))
|
||||
{
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Creating ScriptableObjects folder at <{0}>", AkWwiseEditorSettings.WwiseScriptableObjectRelativePath);
|
||||
AkUtilities.CreateFolder(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath);
|
||||
}
|
||||
|
||||
AkWwiseEditorSettings.GetRootOutputPath();
|
||||
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Migrating Prefabs...");
|
||||
MigratePrefabs();
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Done migrating Prefabs");
|
||||
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Migrating Scenes...");
|
||||
MigrateScenes();
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Done migrating Scenes");
|
||||
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Migrating ScriptableObjects...");
|
||||
MigrateScriptableObjects();
|
||||
UnityEngine.Debug.LogFormat("WwiseUnity: Done migrating ScriptableObjects");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
SetWwiseVersionDefines(WwiseAddressableDefines, true, "com.audiokinetic.wwise.addressables");
|
||||
SetWwiseVersionDefines(WwiseVersionDefines);
|
||||
SetSoundbankSettings();
|
||||
|
||||
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 = AkPluginActivatorConstants.CONFIG_PROFILE;
|
||||
|
||||
AkPluginActivator.DeactivateAllPlugins();
|
||||
AkPluginActivator.Update();
|
||||
AkPluginActivator.ActivatePluginsForEditor();
|
||||
|
||||
SetWwiseVersionDefines(WwiseAddressableDefines, true, "com.audiokinetic.wwise.addressables");
|
||||
SetWwiseVersionDefines(WwiseVersionDefines);
|
||||
}
|
||||
|
||||
// Perform all necessary steps to use the Wwise Unity integration.
|
||||
private static void Setup()
|
||||
{
|
||||
UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects);
|
||||
|
||||
UnityEngine.Debug.Log("WwiseUnity: Deactivating all plugins...");
|
||||
AkPluginActivator.DeactivateAllPlugins();
|
||||
|
||||
// 0. Make sure the SoundBank directory exists
|
||||
var sbPath = AkWwiseEditorSettings.GetRootOutputPath();
|
||||
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;
|
||||
|
||||
UnityEngine.Debug.Log("WwiseUnity: Updating PluginActivator...");
|
||||
AkPluginActivator.Update();
|
||||
UnityEngine.Debug.Log("WwiseUnity: Activating plugins for editor...");
|
||||
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!");
|
||||
|
||||
#if !UNITY_2021_1_OR_NEWER
|
||||
// 11. Activate XboxOne network sockets.
|
||||
AkXboxOneUtils.EnableXboxOneNetworkSockets();
|
||||
#endif
|
||||
|
||||
// 12. Add addressables version define
|
||||
SetWwiseVersionDefines(WwiseAddressableDefines, true, "com.audiokinetic.wwise.addressables");
|
||||
|
||||
// 13. Set Wwise version defines
|
||||
SetWwiseVersionDefines(WwiseVersionDefines);
|
||||
}
|
||||
|
||||
private static HashSet<BuildTargetGroup> AvailableBuildTargetGroups = new HashSet<BuildTargetGroup>();
|
||||
|
||||
public static void AddBuildTargetGroup(BuildTargetGroup NewGroup)
|
||||
{
|
||||
AvailableBuildTargetGroups.Add(NewGroup);
|
||||
}
|
||||
private static void SetWwiseVersionDefines(Dictionary<int,string> versionDefines, bool isPackageDependent = false, string packageName ="")
|
||||
{
|
||||
string wwiseVersion = AkUnitySoundEngine.WwiseVersion;
|
||||
string shortWwiseVersion = wwiseVersion.Substring(0, 4);
|
||||
int wwiseVersionAsInteger = int.Parse(shortWwiseVersion);
|
||||
|
||||
int minimalVersion = wwiseVersionAsInteger;
|
||||
if (isPackageDependent)
|
||||
{
|
||||
var listRequest = Client.List();
|
||||
while (!listRequest.IsCompleted) { }
|
||||
if (listRequest.Status == StatusCode.Success)
|
||||
{
|
||||
foreach (var package in listRequest.Result)
|
||||
{
|
||||
if (package.name == packageName)
|
||||
{
|
||||
string[] versionParts = package.version.Split('.');
|
||||
int.TryParse(versionParts[0], out int packageMajorVersion);
|
||||
if (packageMajorVersion < minimalVersion)
|
||||
{
|
||||
minimalVersion = packageMajorVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add version defines with the wwise version as key if a new define is needed.
|
||||
|
||||
if (wwiseVersionAsInteger >= 2023)
|
||||
{
|
||||
foreach (BuildTargetGroup targetGroup in GetNonObsoleteTargetGroups())
|
||||
{
|
||||
#if UNITY_5_4_OR_NEWER
|
||||
if (targetGroup == BuildTargetGroup.Unknown)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
var namedTarget = UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(targetGroup);
|
||||
string defines = PlayerSettings.GetScriptingDefineSymbols(namedTarget);
|
||||
for (int i = 2023; i <= minimalVersion; ++i)
|
||||
{
|
||||
if (versionDefines.ContainsKey(i))
|
||||
{
|
||||
Match match = Regex.Match(defines, versionDefines[i]);
|
||||
if (!match.Success)
|
||||
{
|
||||
defines += ";" + versionDefines[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayerSettings.SetScriptingDefineSymbols(namedTarget, defines);
|
||||
}
|
||||
}
|
||||
|
||||
SetAddressableAdapterSymbol();
|
||||
}
|
||||
|
||||
// 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
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
var AkInitializers = UnityEngine.Object.FindObjectsByType<AkInitializer>(FindObjectsSortMode.None);
|
||||
#else
|
||||
var AkInitializers = UnityEngine.Object.FindObjectsOfType<AkInitializer>();
|
||||
#endif
|
||||
if (AkInitializers.Length > 0)
|
||||
UnityEditor.Undo.DestroyObjectImmediate(AkInitializers[0].gameObject);
|
||||
|
||||
var WwiseGlobalGameObject = new UnityEngine.GameObject("WwiseGlobal");
|
||||
|
||||
// attach initializer component
|
||||
UnityEditor.Undo.AddComponent<AkInitializer>(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;
|
||||
}
|
||||
|
||||
private static void MigrateRootOutputPath(string wprojPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(AkWwiseEditorSettings.Instance.RootOutputPath))
|
||||
{
|
||||
var defaultRootOutputPath = AkBasePathGetter.GetDefaultRootOutputPath();
|
||||
var pathRelativeToApplicationDataPath = AkUtilities.MakeRelativePath(UnityEngine.Application.dataPath, defaultRootOutputPath);
|
||||
AkWwiseEditorSettings.Instance.RootOutputPath = pathRelativeToApplicationDataPath;
|
||||
AkWwiseEditorSettings.Instance.SaveSettings();
|
||||
}
|
||||
if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.RootOutputPath_v2025_1_0))
|
||||
{
|
||||
AkWwiseEditorSettings.MigrateRootOutputPath(wprojPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 SoundbankPath = AkBasePathGetter.GetDefaultRootOutputPath();
|
||||
if (AkWwiseEditorSettings.Instance.RootOutputPath != null)
|
||||
{
|
||||
var rootOutputPath = AkWwiseEditorSettings.GetRootOutputPath();
|
||||
var r = new Regex(Regex.Escape("_WwiseIntegrationTemp"));
|
||||
SoundbankPath = r.Replace(rootOutputPath, "", 1);
|
||||
}
|
||||
if (SoundbankPath == null)
|
||||
{
|
||||
Debug.LogWarning("Could not get Default Root Output Path.");
|
||||
return false;
|
||||
}
|
||||
var WprojPath = AkUtilities.GetFullPath(UnityEngine.Application.dataPath, settings.WwiseProjectPath);
|
||||
#if UNITY_EDITOR_OSX
|
||||
SoundbankPath = "Z:" + SoundbankPath;
|
||||
#endif
|
||||
MigrateRootOutputPath(WprojPath);
|
||||
string[] settingsToDisable = {"GenerateSoundBankXML"};
|
||||
string[] settingsToEnable = {"SoundBankGenerateHeaderFile", "SoundBankGenerateMaxAttenuationInfo", "GenerateSoundBankJSON", "SoundBankGeneratePrintGUID", "SoundBankGeneratePrintPath", "AutoSoundBankEnabled"};
|
||||
if (AkUtilities.SetSoundbankHeaderFilePath(WprojPath, SoundbankPath))
|
||||
if (AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToDisable, WprojPath, false))
|
||||
return AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToEnable, WprojPath, true);
|
||||
|
||||
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)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
var cameraArray = UnityEngine.Object.FindObjectsByType<UnityEngine.Camera>(FindObjectsSortMode.None);
|
||||
#else
|
||||
var cameraArray = UnityEngine.Object.FindObjectsOfType<UnityEngine.Camera>();
|
||||
#endif
|
||||
if (cameraArray.Length > 0)
|
||||
{
|
||||
foreach (var entry in cameraArray)
|
||||
{
|
||||
if (entry.name == "Main Camera")
|
||||
{
|
||||
camera = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (camera == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (camera.GetComponentInChildren<AkAudioListener>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var oldListener = camera.gameObject.GetComponent<UnityEngine.AudioListener>();
|
||||
if (oldListener != null)
|
||||
{
|
||||
UnityEditor.Undo.DestroyObjectImmediate(oldListener);
|
||||
}
|
||||
|
||||
var akAudioListener = UnityEditor.Undo.AddComponent<AkAudioListener>(camera.gameObject);
|
||||
if (!akAudioListener)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var akGameObj = akAudioListener.GetComponentInChildren<AkGameObj>();
|
||||
if (akGameObj)
|
||||
{
|
||||
akGameObj.isEnvironmentAware = false;
|
||||
}
|
||||
|
||||
if (logWarning)
|
||||
{
|
||||
UnityEngine.Debug.Log("Automatically added AkAudioListener to Main Camera. Go to \"Edit > Wwise Settings...\" to disable this functionality.");
|
||||
}
|
||||
}
|
||||
|
||||
public static BuildTargetGroup[] GetNonObsoleteTargetGroups()
|
||||
{
|
||||
System.Type enumType = typeof(BuildTargetGroup);
|
||||
|
||||
return System.Enum.GetValues(enumType).Cast<BuildTargetGroup>().Where(targetGroup =>
|
||||
{
|
||||
string name = targetGroup.ToString();
|
||||
MemberInfo member = enumType.GetMember(name).FirstOrDefault();
|
||||
|
||||
if (member == null) return false;
|
||||
|
||||
return member.GetCustomAttribute<System.ObsoleteAttribute>() == null;
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private static void SetAddressableAdapterSymbol()
|
||||
{
|
||||
foreach (BuildTargetGroup targetGroup in GetNonObsoleteTargetGroups())
|
||||
{
|
||||
#if UNITY_5_4_OR_NEWER
|
||||
if (targetGroup == BuildTargetGroup.Unknown)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
var namedTarget = UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(targetGroup);
|
||||
if (PlayerSettings.GetScriptingDefineSymbols(namedTarget).Contains(WwiseAddressableAPIDefine))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string currentDefines = PlayerSettings.GetScriptingDefineSymbols(namedTarget);
|
||||
var currentDefineList = currentDefines.Split(';').ToList();
|
||||
|
||||
const string wwiseAddressablePrefix = "ADDRESSABLES_API";
|
||||
currentDefineList.RemoveAll(define => define.StartsWith(wwiseAddressablePrefix));
|
||||
|
||||
currentDefineList.Add(WwiseAddressableAPIDefine);
|
||||
|
||||
string newDefinesString = string.Join(";", currentDefineList.Distinct());
|
||||
PlayerSettings.SetScriptingDefineSymbols(namedTarget, newDefinesString);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // UNITY_EDITOR
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90f5790a76fd1f4449499e336513354d
|
||||
@@ -0,0 +1,56 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
#if !UNITY_2021_1_OR_NEWER
|
||||
public static class AkXboxOneUtils
|
||||
{
|
||||
private static readonly int[] Usages = { 0, 1, 4, 7 };
|
||||
private static readonly int SessionRequirement = 0;
|
||||
private static readonly int[] DeviceUsages = { 0 };
|
||||
|
||||
[UnityEditor.MenuItem("Assets/Wwise/Xbox One/Enable Network Sockets")]
|
||||
public static void EnableXboxOneNetworkSockets()
|
||||
{
|
||||
var definitions = new[]
|
||||
{
|
||||
new SocketDefinition("WwiseDiscoverySocket", "24024", 1, "WwiseDiscovery"),
|
||||
new SocketDefinition("WwiseCommandSocket", "24025", 0, "WwiseCommand")
|
||||
};
|
||||
|
||||
foreach (var def in definitions)
|
||||
{
|
||||
UnityEditor.PlayerSettings.XboxOne.SetSocketDefinition(def.Name, def.Port, def.Protocol, Usages, def.TemplateName,
|
||||
SessionRequirement, DeviceUsages);
|
||||
}
|
||||
}
|
||||
|
||||
private class SocketDefinition
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Port;
|
||||
public readonly int Protocol;
|
||||
public readonly string TemplateName;
|
||||
|
||||
public SocketDefinition(string name, string port, int protocol, string templateName)
|
||||
{
|
||||
Name = name;
|
||||
Port = port;
|
||||
Protocol = protocol;
|
||||
TemplateName = templateName;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ff0287eef1770945b7f6cc88ed7ce3e
|
||||
Reference in New Issue
Block a user