diff --git a/Assets/PerfectWorld/Scene/LoginScene.unity b/Assets/PerfectWorld/Scene/LoginScene.unity index ce0e50f81b..d6589e3bd1 100644 --- a/Assets/PerfectWorld/Scene/LoginScene.unity +++ b/Assets/PerfectWorld/Scene/LoginScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce4ce7c6a9576c56a5fb0b213f19e1253afc78d679474cb203612a1e50e8093d -size 111451 +oid sha256:08dd99327890c9a20d09b1faadef16ad55b5a276d5080d744bfdc2f4191dceac +size 111628 diff --git a/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs b/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs index 1599880e6c..676b68a131 100644 --- a/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs +++ b/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; +using UnityEngine.Audio; using BrewMonster.Scripts; namespace BrewMonster.Scripts @@ -24,10 +25,23 @@ namespace BrewMonster.Scripts /// [SerializeField] private AudioSource _moveSoundSource; + /// + /// Mixer group that all skill SFX are routed through. Assign in the Inspector. + /// + [SerializeField] private AudioMixerGroup _sfxMixerGroup; + + /// + /// Number of pooled AudioSources available for concurrent skill SFX playback. + /// + [SerializeField] private int _sfxPoolSize = 8; + + private readonly List _sfxPool = new(); + protected override void Initialize() { base.Initialize(); LoadSoundTable(); + BuildSfxPool(); } // ──────────────────────────────────────────────────────────────────── @@ -81,6 +95,37 @@ namespace BrewMonster.Scripts return path; } + // ──────────────────────────────────────────────────────────────────── + // Skill SFX pool + // ──────────────────────────────────────────────────────────────────── + + private void BuildSfxPool() + { + for (int i = 0; i < _sfxPoolSize; i++) + { + var child = new GameObject($"SFXPool_{i}"); + child.transform.SetParent(transform); + var src = child.AddComponent(); + src.playOnAwake = false; + src.outputAudioMixerGroup = _sfxMixerGroup; + _sfxPool.Add(src); + } + } + + /// World position the source is moved to before playback. + /// 0 = fully 2D, 1 = fully 3D positional. + private AudioSource GetPooledSource(Vector3 worldPos, float spatialBlend = 0f) + { + AudioSource chosen = null; + foreach (var src in _sfxPool) + if (!src.isPlaying) { chosen = src; break; } + if (chosen == null) chosen = _sfxPool[0]; // fallback: steal oldest + + chosen.transform.position = worldPos; + chosen.spatialBlend = spatialBlend; + return chosen; + } + // ──────────────────────────────────────────────────────────────────── // Public API // ──────────────────────────────────────────────────────────────────── @@ -114,14 +159,14 @@ namespace BrewMonster.Scripts if (mgr.TryGetCachedAudioClip(address, out var clip) && clip != null) { - AudioSource.PlayClipAtPoint(clip, Vector3.zero, SkillSfxVolume); + GetPooledSource(worldPos).PlayOneShot(clip, SkillSfxVolume); return; } await mgr.WaitUntilInitializedAsync(); var loaded = await mgr.LoadAudioClipAsync(address); if (loaded != null) - AudioSource.PlayClipAtPoint(loaded, Vector3.zero, SkillSfxVolume); + GetPooledSource(worldPos).PlayOneShot(loaded, SkillSfxVolume); } /// diff --git a/Assets/Prefabs/UI/Music.prefab b/Assets/Prefabs/UI/Music.prefab index 0ef6d16bfd..3348bdb751 100644 --- a/Assets/Prefabs/UI/Music.prefab +++ b/Assets/Prefabs/UI/Music.prefab @@ -10,6 +10,7 @@ GameObject: m_Component: - component: {fileID: 3636302681040170949} - component: {fileID: 4656951194032224} + - component: {fileID: 1928072503138413728} m_Layer: 0 m_Name: SFX m_TagString: Untagged @@ -29,8 +30,7 @@ Transform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 2281112146744556387} + m_Children: [] m_Father: {fileID: 4292995824318243454} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &4656951194032224 @@ -45,7 +45,106 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 4cfa292fff0815d40b82f32256b3f2cc, type: 3} m_Name: m_EditorClassIdentifier: - _moveSoundSource: {fileID: 2796487417538969809} + _moveSoundSource: {fileID: 1928072503138413728} + _sfxMixerGroup: {fileID: 217038053835239290, guid: 9c6a7598ca0dfcd4fa51470ebbdd7549, type: 2} + _sfxPoolSize: 8 +--- !u!82 &1928072503138413728 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2838129733766203984} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 217038053835239290, guid: 9c6a7598ca0dfcd4fa51470ebbdd7549, type: 2} + m_audioClip: {fileID: 0} + m_Resource: {fileID: 0} + m_PlayOnAwake: 1 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 --- !u!1 &6634120867767479402 GameObject: m_ObjectHideFlags: 0 @@ -314,132 +413,3 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: _worldMusicDB: {fileID: 11400000, guid: 7602c1f71697aae42a7751212c5144dc, type: 2} ---- !u!1 &9129044928287689905 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2281112146744556387} - - component: {fileID: 2796487417538969809} - m_Layer: 0 - m_Name: MoveSoundSource - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2281112146744556387 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9129044928287689905} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 3636302681040170949} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!82 &2796487417538969809 -AudioSource: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9129044928287689905} - m_Enabled: 1 - serializedVersion: 4 - OutputAudioMixerGroup: {fileID: 217038053835239290, guid: 9c6a7598ca0dfcd4fa51470ebbdd7549, type: 2} - m_audioClip: {fileID: 0} - m_Resource: {fileID: 0} - m_PlayOnAwake: 1 - m_Volume: 1 - m_Pitch: 1 - Loop: 0 - Mute: 0 - Spatialize: 0 - SpatializePostEffects: 0 - Priority: 128 - DopplerLevel: 1 - MinDistance: 1 - MaxDistance: 500 - Pan2D: 0 - rolloffMode: 0 - BypassEffects: 0 - BypassListenerEffects: 0 - BypassReverbZones: 0 - rolloffCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - - serializedVersion: 3 - time: 1 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - panLevelCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - spreadCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - reverbZoneMixCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 9745b693a7..818e0af5c5 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -54,8 +54,8 @@ namespace BrewMonster private bool m_bJumpInWater = false; public A3DVECTOR3 m_vVelocity; // Velocity - - + + bool m_bChangingFace; // true, host is changing face private int m_iRoleCreateTime; private int m_iRoleLastLoginTime; // Role last login time @@ -185,7 +185,7 @@ namespace BrewMonster private UnityEngine.InputSystem.Keyboard m_cachedKeyboard; int[] targetsCastSkill; - + public bool IsChangingFace() { return m_bChangingFace; @@ -367,8 +367,8 @@ namespace BrewMonster m_iAccountTotalCash = RoleInfo.cash_add; EC_Game.GetGameRun().AddPlayerName(m_PlayerInfo.cid, m_strName); - - if (!await LoadPlayerSkeleton(true)) + + if (!await LoadPlayerSkeleton(true)) { BMLogger.LogError($"HoangDev CECHostPlayer::LoadResources, Failed to load skeleton. {m_strName}"); return false; @@ -487,7 +487,7 @@ namespace BrewMonster public void ProcessMessage(in ECMSG Msg) { var msg = (int)Msg.dwMsg; - //Debug.LogError("HoangDev : ProcessMessageProcessMessageProcessMessage " + msg); + //Debug.LogError("HoangDev : ProcessMessageProcessMessageProcessMessage " + msg); switch (msg) { case EC_MsgDef.MSG_HST_CORRECTPOS: OnMsgHstCorrectPos(Msg); break; @@ -878,7 +878,7 @@ namespace BrewMonster NotifyServerForceAttack(true); } } - + #if UNITY_EDITOR /// /// Cycles through learned skills by removing all shortcuts and adding 2 new skills to slots 0 and 1. @@ -891,7 +891,7 @@ namespace BrewMonster { return m_bEnterGame; } - + void SetLevel2(int level2, bool bFirstTime) { int lastLevel2 = m_BasicProps.iLevel2; @@ -905,7 +905,7 @@ namespace BrewMonster { return m_pWorkMan.IsMovingToPosition(); }*/ - + public bool IsPosCollideFree(A3DVECTOR3 vTargetPos) { bool bAvailable = (false); @@ -1502,7 +1502,7 @@ namespace BrewMonster // SetPlayerModel(); //Debug.LogError("Pos Character = " + pos); } - + /// Use host's m_pvp (we update it from S2C duel packets). Base IsInDuel() reads CECPlayer.m_pvp which is never set. public new bool IsInDuel() { return m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL; } @@ -1536,7 +1536,7 @@ namespace BrewMonster //bool bResult = false; float fRange = 0.0f; //string reasonStr = iReason == 1 ? "melee" : (iReason == 2 ? "cast magic" : (iReason == 3 ? "talk" : $"unknown({iReason})")); - + switch (iReason) { case 1: // melee @@ -1769,7 +1769,7 @@ namespace BrewMonster return fSpeedSev; } - + public void PrepareNPCService(int idSev) { @@ -2077,9 +2077,9 @@ namespace BrewMonster return bRet; } - + public int GetMaxLevelSofar() { return Math.Max(m_ReincarnationTome.max_level, m_BasicProps.iLevel); } - + public bool CanUseProjectile(CECIvtrArrow pArrow) { if (pArrow == null) @@ -2660,7 +2660,7 @@ namespace BrewMonster return idNewSel; } - + //public float GetSwimSpeedSev() //{ // float fSpeedSev = GetSwimSpeed(); @@ -3021,7 +3021,7 @@ namespace BrewMonster // cursorType = CursorType.Pickup; // else if (CanGatherMatter(pMatter)) // cursorType = pMatter.IsMonsterSpiritMine() ? CursorType.Swallow : CursorType.Dig; - // + // // if (cursorType != CursorType.Normal) // m_idCurHover = idHitObject; // } @@ -3382,7 +3382,7 @@ namespace BrewMonster BUBBLE_HPWARN, BUBBLE_MPWARN, BUBBLE_REBOUND, // ·´µ¯ - BUBBLE_BEAT_BACK, // ·´»÷ + BUBBLE_BEAT_BACK, // ·´»÷ BUBBLE_ADD, // ÎüѪµÄ¼ÓºÅ BUBBLE_DODGE_DEBUFF, BUBBLE_REALMEXP, @@ -3781,7 +3781,7 @@ namespace BrewMonster // Get key object(NPC..) coordinates public A3DVECTOR3 GetObjectCoordinates(int idTarget, out List TargetCoord, ref bool bInTable) { - + TargetCoord = new List(); A3DVECTOR3 vDestPos = new A3DVECTOR3(0, 0, 0); @@ -3816,7 +3816,7 @@ namespace BrewMonster string strCurMap = pInstance.GetPath() ?? string.Empty; // �ȼ��ͬһ��ͼ���Ƿ���Ҫ���ҵ���Ʒ bool bHasObjectInCurrentInstance = originalCoords.Any(coord => coord.strMap == strCurMap); - + // Iterate over original list and build filtered TargetCoord list for (int i = 0; i < iCount; i++) { @@ -3848,10 +3848,10 @@ namespace BrewMonster if (instCoord[j].strMap == strCurMap) { TargetCoord.Add(instCoord[j]); - + // Check if this is the nearest target float tempDist = (instCoord[j].vPos - GetPos()).Magnitude(); - + if (tempDist < fMinDist) { fMinDist = tempDist; @@ -3869,7 +3869,7 @@ namespace BrewMonster public int GetRealmSubLevel() { return m_RealmLevel % 100; } public static int GetRealmLayer(int realmLevel) { return realmLevel > 0 ? (realmLevel + 9) / 10 : 0; } public static int GetRealmSubLevel(int realmLevel) { return realmLevel > 0 ? (realmLevel % 10 > 0 ? realmLevel % 10 : 10) : 0; } - + // // Calculate distance to an object and optionally retrieve the object reference // 计算到对象的距离,并可选地获取对象引用 @@ -3981,13 +3981,13 @@ namespace BrewMonster // } //} - } + } //// ID checking helper methods //private bool ISNPCID(int id) => ((id & 0x80000000) != 0) && ((id & 0x40000000) == 0); //private bool ISPLAYERID(int id) => id != 0 && (id & 0x80000000) == 0; //private bool ISMATTERID(int id) => ((id) & 0xC0000000) == 0xC0000000; - + // Release object public void Release() { @@ -4213,7 +4213,7 @@ namespace BrewMonster } else { - newId = 0; + newId = 164; } PlayMoveSound(newId); @@ -4228,13 +4228,13 @@ namespace BrewMonster if (id == _curMoveSndId) return; _curMoveSndId = id; if(id > 0) - { + { SFXManager.Instance?.PlayMoveSoundAsync(id).Forget(); } - else + /*else { SFXManager.Instance?.StopMoveSoundAsync().Forget(); - } + }*/ } /// @@ -4261,8 +4261,8 @@ namespace BrewMonster return trace.GetTraceReason() == Trace_reason.TRACE_SPELL; } } - - + + }