Merge pull request 'feature/Sound' (#393) from feature/Sound into develop

Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/393
This commit is contained in:
hoangvd
2026-05-04 02:48:44 +00:00
4 changed files with 181 additions and 166 deletions
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ce4ce7c6a9576c56a5fb0b213f19e1253afc78d679474cb203612a1e50e8093d
size 111451
oid sha256:08dd99327890c9a20d09b1faadef16ad55b5a276d5080d744bfdc2f4191dceac
size 111628
@@ -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
/// </summary>
[SerializeField] private AudioSource _moveSoundSource;
/// <summary>
/// Mixer group that all skill SFX are routed through. Assign in the Inspector.
/// </summary>
[SerializeField] private AudioMixerGroup _sfxMixerGroup;
/// <summary>
/// Number of pooled AudioSources available for concurrent skill SFX playback.
/// </summary>
[SerializeField] private int _sfxPoolSize = 8;
private readonly List<AudioSource> _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<AudioSource>();
src.playOnAwake = false;
src.outputAudioMixerGroup = _sfxMixerGroup;
_sfxPool.Add(src);
}
}
/// <param name="worldPos">World position the source is moved to before playback.</param>
/// <param name="spatialBlend">0 = fully 2D, 1 = fully 3D positional.</param>
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);
}
/// <summary>
+102 -132
View File
@@ -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
+30 -30
View File
@@ -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
/// <summary>
/// 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);
}
/// <summary>Use host's m_pvp (we update it from S2C duel packets). Base IsInDuel() reads CECPlayer.m_pvp which is never set.</summary>
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<OBJECT_COORD> TargetCoord, ref bool bInTable)
{
TargetCoord = new List<OBJECT_COORD>();
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; }
// <summary>
// 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();
}
}*/
}
/// <summary>
@@ -4261,8 +4261,8 @@ namespace BrewMonster
return trace.GetTraceReason() == Trace_reason.TRACE_SPELL;
}
}
}