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;
}
}
-
-
+
+
}