using UnityEditor; using UnityEngine; using Wwise.Wooduan.Components; using Wwise.Wooduan.Core; namespace Wwise.Wooduan.Tools { internal class AkWooduanBatchProcessor { #region OptimizeSpatialAudio private static LayerMask AudioVolumeLayer => LayerMask.NameToLayer("NoCollisionWithEntity"); [MenuItem("Wwise/Tools/Optimize Prefab/Spatial Audio &F12")] internal static void OptimizeSpatialAudio() { foreach (var prefab in Selection.gameObjects) { var mapName = prefab.name.Replace("_SpatialAudio", "").ToLower(); AkWooduanScriptingTools.SetAssetBundleName(prefab, "maps/" + mapName + "/audio"); prefab.layer = AudioVolumeLayer; foreach (Transform childTransform in prefab.transform) { IterateBuilding(childTransform); } } } private static void IterateBuilding(Transform building) { // for big map, one more level in hierarchy if (building.name == "Buildings") { foreach (Transform child in building) { IterateBuilding(child); } } else { if (building.name != "Outside") OptimizeBuilding(building); foreach (Transform child in building) { if (child.name.StartsWith("Room")) OptimizeRooms(child); else if (child.name.StartsWith("Portal")) OptimizePortals(child); else if (child.name.StartsWith("Geometr")) OptimizeGeometries(child); else if (child.name.StartsWith("Roof")) OptimizeRoofs(child); else continue; } } } private static void OptimizeBuilding(Transform building) { var gameObject = building.gameObject; gameObject.isStatic = false; gameObject.layer = AudioVolumeLayer; if (gameObject.GetComponent()) { var boxCollider = AkWooduanHelper.GetOrAddComponent(gameObject); boxCollider.enabled = true; ResizeTransformToCollider(boxCollider); } } private static void OptimizeRooms(Transform rootRooms) { CenterTransform(rootRooms); foreach (Transform roomTransform in rootRooms) { var gameObject = roomTransform.gameObject; gameObject.isStatic = false; gameObject.layer = AudioVolumeLayer; var boxCollider = AkWooduanHelper.GetOrAddComponent(gameObject); boxCollider.enabled = true; ResizeTransformToCollider(boxCollider); AkWooduanHelper.DeleteComponent(gameObject); var room = AkWooduanHelper.GetOrAddComponent(gameObject); room.AutoRename(); OptimizeSubrooms(roomTransform); } } private static void OptimizeRoofs(Transform rootRoofs) { CenterTransform(rootRoofs); foreach (Transform roofTransform in rootRoofs) { var gameObject = roofTransform.gameObject; gameObject.isStatic = false; gameObject.layer = AudioVolumeLayer; var boxCollider = AkWooduanHelper.GetOrAddComponent(gameObject); boxCollider.enabled = true; ResizeTransformToCollider(boxCollider); var akRoof = AkWooduanHelper.GetOrAddComponent(gameObject); akRoof.AutoRename(); } } private static void OptimizeSubrooms(Transform roomTransform) { foreach (Transform subroomTransform in roomTransform) { var gameObject = subroomTransform.gameObject; gameObject.isStatic = false; gameObject.layer = AudioVolumeLayer; var boxCollider = AkWooduanHelper.GetOrAddComponent(gameObject); boxCollider.enabled = true; ResizeTransformToCollider(boxCollider); var subRoom = AkWooduanHelper.GetOrAddComponent(gameObject); var room = gameObject.GetComponent(); if (room) { subRoom.overrideFloor = true; subRoom.floor = room.bottomFloor; Object.DestroyImmediate(room); } subRoom.AutoRename(); } } private static void OptimizePortals(Transform rootPortals) { CenterTransform(rootPortals); foreach (Transform portalTransform in rootPortals) { var gameObject = portalTransform.gameObject; gameObject.isStatic = false; gameObject.layer = AudioVolumeLayer; var boxCollider = AkWooduanHelper.GetOrAddComponent(gameObject); boxCollider.enabled = true; ResizeTransformToCollider(boxCollider); var boxSize = boxCollider.size; if (boxSize.z < 2) boxCollider.size = new Vector3(boxSize.x, boxSize.y, 2f); var portal = AkWooduanHelper.GetOrAddComponent(gameObject); portal.AutoRename(); if (!portal.frontRoom && !portal.backRoom) Debug.LogError(gameObject.name + " has no connenting rooms!" ); else if (portal.frontRoom == portal.backRoom) Debug.LogError(gameObject.name + " has identical front and back rooms!" ); } } private static void OptimizeGeometries(Transform rootPortals) { foreach (Transform roomTransform in rootPortals) { var gameObject = roomTransform.gameObject; gameObject.layer = AudioVolumeLayer; gameObject.isStatic = false; gameObject.layer = AudioVolumeLayer; var collider = AkWooduanHelper.GetOrAddComponent(gameObject); collider.enabled = false; var surfaceReflector = AkWooduanHelper.GetOrAddComponent(gameObject); surfaceReflector.EnableDiffraction = true; surfaceReflector.AutoFindAssociatedRoom(); } } private static void ResizeTransformToCollider(BoxCollider collider) { CenterCollider(collider); collider.isTrigger = true; var transform = collider.transform; var localScale = transform.localScale; if (localScale != Vector3.one) { transform.localScale = Vector3.one; collider.size = MultiplyScale(collider.size, localScale); collider.center = MultiplyScale(collider.center, localScale); foreach (Transform child in transform) { child.localScale = MultiplyScale(child.localScale, localScale); } } } private static void CenterCollider(BoxCollider collider) { var shiftPosition = collider.center; if (shiftPosition == Vector3.zero) return; var transform = collider.transform; if (transform.localRotation != Quaternion.identity) shiftPosition = transform.localRotation * shiftPosition; transform.localPosition += shiftPosition; foreach (Transform child in collider.transform) { child.transform.localPosition -= collider.center; } collider.center = Vector3.zero; } private static void CenterTransform(Transform transform) { var shiftPosition = transform.localPosition; if (shiftPosition == Vector3.zero) return; transform.localPosition = Vector3.zero; foreach (Transform child in transform) { child.transform.localPosition += shiftPosition; } } private static Vector3 MultiplyScale(Vector3 originalScale, Vector3 scale) { return new Vector3(originalScale.x * scale.x, originalScale.y * scale.y, originalScale.z * scale.z); } #endregion [MenuItem("Wwise/Tools/Optimize Prefab/Ambient Audio")] public static void OptimizeAmbientAudio() { foreach (var prefab in Selection.gameObjects) { var mapName = prefab.name.Replace("_AmbientAudio", "").ToLower(); AkWooduanScriptingTools.SetAssetBundleName(prefab, "maps/" + mapName + "/audio"); prefab.layer = AudioVolumeLayer; foreach (Transform childTransform in prefab.transform) { IterateAmbience(childTransform); } } } private static void IterateAmbience(Transform transform) { var akAmbient = transform.GetComponent(); if (akAmbient) IterateAkAmbient(akAmbient); else { foreach (Transform childTransform in transform) { IterateAmbience(childTransform); } } } private static void IterateAkAmbient(AkAmbient akAmbient) { AkWooduanHelper.DeleteComponent(akAmbient.gameObject); var akGameObj = akAmbient.gameObject.AddComponent(); switch (akAmbient.positionMode) { case AmbientEmitterPositionMode.Large: case AmbientEmitterPositionMode.Single: case AmbientEmitterPositionMode.MultiPosition: akGameObj.autoUpdatePosition = false; break; } } [MenuItem("GameObject/Wwise/Create AkRoom")] public static void CreateAkRoom() { var selection = Selection.activeGameObject; if (!selection) return; var originalCollider = selection.GetComponentInChildren(); var newGameObject = new GameObject("AkRoom_" + selection.name); newGameObject.transform.position = selection.transform.position; var originalRotation = selection.transform.rotation; selection.transform.rotation = Quaternion.identity; var originalBox = originalCollider as BoxCollider; if (originalBox) { var boxCollider = newGameObject.AddComponent(); boxCollider.isTrigger = true; boxCollider.center = originalBox.center; boxCollider.size = originalBox.size; } else { var colliderBound = originalCollider.bounds; var boxCollider = newGameObject.AddComponent(); boxCollider.isTrigger = true; boxCollider.center = colliderBound.center; boxCollider.size = colliderBound.extents; } selection.transform.rotation = originalRotation; newGameObject.transform.rotation = originalRotation; Selection.activeGameObject = newGameObject; } } }