更新了NB Shader,少量优化GPU
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using SLSUtilities.WwiseAssistance;
|
||||
@@ -9,49 +8,53 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class NoteAudioSubmodule : SubmoduleBase
|
||||
{
|
||||
#region [暴露属性字段] Audio Settings
|
||||
#region Audio Settings
|
||||
public List<string> generalJudgeAudioList;
|
||||
public List<string> perfectAudioList;
|
||||
public List<string> goodAudioList;
|
||||
public List<string> badAudioList;
|
||||
public List<string> missAudioList;
|
||||
public List<string> holdStartAudioList;
|
||||
public List<string> holdLoopAudioList;
|
||||
public List<string> holdEndAudioList;
|
||||
#endregion
|
||||
|
||||
#region [运行时缓存变量] GC-Free Wwise IDs
|
||||
// --- 高性能无 GC 的 Wwise 预存 ID 数组 ---
|
||||
// 我们利用基础类型数组而不是 List 再次挤压最后一点遍历性能。
|
||||
|
||||
#region GC-Free Wwise IDs
|
||||
private uint[] _generalJudgeAudioIds;
|
||||
private uint[] _perfectAudioIds;
|
||||
private uint[] _goodAudioIds;
|
||||
private uint[] _badAudioIds;
|
||||
private uint[] _missAudioIds;
|
||||
private uint[] _holdStartAudioIds;
|
||||
|
||||
private uint[] _holdEndAudioIds;
|
||||
|
||||
private NoteBase note => attachedGameElement as NoteBase;
|
||||
#endregion
|
||||
|
||||
#region [生命周期] Initialization
|
||||
#region Initialization
|
||||
public NoteAudioSubmodule(NoteBase attachedGameElement, string defaultAudio) : base(attachedGameElement)
|
||||
{
|
||||
generalJudgeAudioList = new List<string>() { defaultAudio };
|
||||
generalJudgeAudioList = new List<string> { defaultAudio };
|
||||
perfectAudioList = new List<string>();
|
||||
goodAudioList = new List<string>();
|
||||
badAudioList = new List<string>();
|
||||
missAudioList = new List<string>();
|
||||
holdStartAudioList = new List<string>();
|
||||
holdLoopAudioList = new List<string>();
|
||||
holdEndAudioList = new List<string>();
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.note.NoteAudioSubmodule = this;
|
||||
note.NoteAudioSubmodule = this;
|
||||
}
|
||||
|
||||
|
||||
InitializeAudio();
|
||||
}
|
||||
|
||||
public NoteAudioSubmodule(NoteBase attachedGameElement, List<string> generalJudgeAudioList,
|
||||
List<string> perfectAudioList, List<string> goodAudioList, List<string> badAudioList,
|
||||
List<string> missAudioList, List<string> holdStartAudioList) : base(attachedGameElement)
|
||||
List<string> missAudioList, List<string> holdStartAudioList,
|
||||
List<string> holdLoopAudioList = null, List<string> holdEndAudioList = null) : base(attachedGameElement)
|
||||
{
|
||||
this.generalJudgeAudioList = generalJudgeAudioList ?? new List<string>();
|
||||
this.perfectAudioList = perfectAudioList ?? new List<string>();
|
||||
@@ -59,10 +62,12 @@ namespace Ichni.RhythmGame
|
||||
this.badAudioList = badAudioList ?? new List<string>();
|
||||
this.missAudioList = missAudioList ?? new List<string>();
|
||||
this.holdStartAudioList = holdStartAudioList ?? new List<string>();
|
||||
this.holdLoopAudioList = holdLoopAudioList ?? new List<string>();
|
||||
this.holdEndAudioList = holdEndAudioList ?? new List<string>();
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.note.NoteAudioSubmodule = this;
|
||||
note.NoteAudioSubmodule = this;
|
||||
}
|
||||
|
||||
InitializeAudio();
|
||||
@@ -70,44 +75,45 @@ namespace Ichni.RhythmGame
|
||||
|
||||
public void InitializeAudio()
|
||||
{
|
||||
// 通过反射,只在生成(或池化取出)时进行一次大写转换与常数查询,彻底摒弃字符串带来的运行时哈希。
|
||||
_generalJudgeAudioIds = ParseWwiseEventIDs(generalJudgeAudioList);
|
||||
_perfectAudioIds = ParseWwiseEventIDs(perfectAudioList);
|
||||
_goodAudioIds = ParseWwiseEventIDs(goodAudioList);
|
||||
_badAudioIds = ParseWwiseEventIDs(badAudioList);
|
||||
_missAudioIds = ParseWwiseEventIDs(missAudioList);
|
||||
_holdStartAudioIds = ParseWwiseEventIDs(holdStartAudioList);
|
||||
_holdEndAudioIds = ParseWwiseEventIDs(holdEndAudioList);
|
||||
}
|
||||
|
||||
|
||||
private uint[] ParseWwiseEventIDs(List<string> audioNames)
|
||||
{
|
||||
if (audioNames == null || audioNames.Count == 0) return new uint[0];
|
||||
|
||||
if (audioNames == null || audioNames.Count == 0) return Array.Empty<uint>();
|
||||
|
||||
List<uint> ids = new List<uint>(audioNames.Count);
|
||||
Type eventsType = typeof(AK.EVENTS);
|
||||
|
||||
|
||||
for (int i = 0; i < audioNames.Count; i++)
|
||||
{
|
||||
if (string.IsNullOrEmpty(audioNames[i])) continue;
|
||||
|
||||
|
||||
string upperName = audioNames[i].ToUpper();
|
||||
FieldInfo field = eventsType.GetField(upperName, BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
|
||||
if (field != null)
|
||||
{
|
||||
ids.Add((uint)field.GetValue(null));
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"[Wwise 注意] 在 AK.EVENTS 中找不到对应的大写事件名称: {upperName}");
|
||||
UnityEngine.Debug.LogWarning($"[Wwise] AK.EVENTS does not contain event name: {upperName}");
|
||||
}
|
||||
}
|
||||
|
||||
return ids.ToArray();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region [播放控制] Audio Playback Methods
|
||||
#region Audio Playback Methods
|
||||
public partial class NoteAudioSubmodule
|
||||
{
|
||||
public void PlayHoldStartAudio()
|
||||
@@ -115,19 +121,38 @@ namespace Ichni.RhythmGame
|
||||
PlayAudioInternal(_holdStartAudioIds);
|
||||
}
|
||||
|
||||
public void PlayHoldEndAudio()
|
||||
{
|
||||
if (_holdEndAudioIds != null && _holdEndAudioIds.Length > 0)
|
||||
{
|
||||
PlayAudioInternal(_holdEndAudioIds);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayGeneralJudgeAudios();
|
||||
}
|
||||
|
||||
public void PlayGeneralJudgeAudios()
|
||||
{
|
||||
PlayAudioInternal(_generalJudgeAudioIds);
|
||||
}
|
||||
|
||||
|
||||
public void PlayNoteJudgeAudios(NoteBase.NoteJudgeType judgeType)
|
||||
{
|
||||
switch (judgeType)
|
||||
{
|
||||
case NoteBase.NoteJudgeType.Perfect: PlayAudioInternal(_perfectAudioIds); break;
|
||||
case NoteBase.NoteJudgeType.Good: PlayAudioInternal(_goodAudioIds); break;
|
||||
case NoteBase.NoteJudgeType.Bad: PlayAudioInternal(_badAudioIds); break;
|
||||
case NoteBase.NoteJudgeType.Miss: PlayAudioInternal(_missAudioIds); break;
|
||||
case NoteBase.NoteJudgeType.Perfect:
|
||||
PlayAudioInternal(_perfectAudioIds);
|
||||
break;
|
||||
case NoteBase.NoteJudgeType.Good:
|
||||
PlayAudioInternal(_goodAudioIds);
|
||||
break;
|
||||
case NoteBase.NoteJudgeType.Bad:
|
||||
PlayAudioInternal(_badAudioIds);
|
||||
break;
|
||||
case NoteBase.NoteJudgeType.Miss:
|
||||
PlayAudioInternal(_missAudioIds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,15 +161,13 @@ namespace Ichni.RhythmGame
|
||||
if (audioIds == null) return;
|
||||
for (int i = 0; i < audioIds.Length; i++)
|
||||
{
|
||||
// 最高性能播放:绕过 AudioManager 那些空物体创建,直接挂载到 AudioManager 的单例底层进行原生播放。
|
||||
AkSoundEngine.PostEvent(audioIds[i], AudioManager.Instance.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [Beatmap] Executing and Reversing
|
||||
|
||||
#endregion
|
||||
#region Beatmap
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace Ichni.RhythmGame
|
||||
case NoteJudgeType.Miss: Miss(triggerTime); break;
|
||||
}
|
||||
|
||||
if (finalJudge != NoteJudgeType.Miss) NoteAudioSubmodule.PlayGeneralJudgeAudios();
|
||||
if (finalJudge != NoteJudgeType.Miss) NoteAudioSubmodule.PlayHoldEndAudio();
|
||||
}
|
||||
|
||||
protected override void SetJudgeArea()
|
||||
|
||||
Reference in New Issue
Block a user