引入 BGM 切换+文档初版草稿

This commit is contained in:
2026-04-25 23:49:38 +08:00
parent 5ae7ca8d56
commit 251c257489
97 changed files with 676 additions and 41 deletions
+5 -1
View File
@@ -1,7 +1,11 @@
# 音乐配置表
# 音乐配置表 列1 列2
# Id AssetName
# int string
# 音乐编号 策划备注 资源名称
1 菜单音乐 music_menu
2 战斗音乐 music_background
3 关于音乐 music_about
4 Chapter1 music_chapter1
5 Combine music_combine
6 Chapter3 music_chapter3
7 Chapter4 music_chapter4
+6 -7
View File
@@ -1,7 +1,6 @@
# 场景配置表
# Id AssetName BackgroundMusicId
# int string int
# 场景编号 备注 资源名称 背景音乐编号
1 菜单场景 Menu 1
2 战斗场景 Main 2
3 GameplayA 0
# 场景配置表 列1 列2
# Id AssetName
# int string
# 场景编号 备注 资源名称
1 菜单场景 Menu
2 Main
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 9e64c81855f973b4fb936c535cbd79d2
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 92f8dd3dabff14341abb15b5048284e8
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: fd6750467748e384caced25fde2c774a
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 913ea5fc4da43ab4d8f125284d4e0852
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: ada32f4de8605cd4bb04aba4adb943bf
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
+8 -5
View File
@@ -1,19 +1,22 @@
fileFormatVersion: 2
guid: caa829ab2ffc71340a69253afdf58365
guid: ad8872525ae4eb5459dd61903ceff393
AudioImporter:
serializedVersion: 6
externalObjects: {}
serializedVersion: 7
defaultSettings:
loadType: 2
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 0.01
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
preloadAudioData: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Event;
using Sound;
using UI;
using UnityEngine;
using UnityEngine.Events;
@@ -53,6 +54,15 @@ namespace CustomComponent
/// </summary>
[SerializeField] private UnityEvent _onPuzzleCompleted = new UnityEvent();
[SerializeField] [Tooltip("开始拼装时是否自动切换 BGM。")]
private bool _autoSwitchBgmOnStart = true;
[SerializeField] [Tooltip("拼装阶段 BGM Id。")]
private int _combineBgmId = 5;
[SerializeField] [Tooltip("拼装结束后是否自动恢复被打断的 BGM(带进度)。")]
private bool _autoRestoreInterruptedBgm = true;
#endregion
#region Runtime State
@@ -105,6 +115,10 @@ namespace CustomComponent
/// </summary>
private int _nextLevelStructureIndex = 0;
private bool _hasInterruptedBgm = false;
private int _interruptedBgmId = 0;
private float _interruptedBgmTimeSeconds = 0f;
#endregion
#region Public Query
@@ -139,6 +153,16 @@ namespace CustomComponent
}
}
private void Start()
{
GameEntry.Event.Subscribe(CombineCompletedEventArgs.EventId, OnCombineCompleted);
}
private void OnDestroy()
{
GameEntry.Event.Unsubscribe(CombineCompletedEventArgs.EventId, OnCombineCompleted);
}
#endregion
#region Level Lifecycle
@@ -167,6 +191,7 @@ namespace CustomComponent
return null;
}
SwitchToCombineBgm();
_nextLevelStructureIndex++;
return serialId;
}
@@ -178,6 +203,7 @@ namespace CustomComponent
{
_formController?.CloseUI();
ClearRuntimeContext();
RestoreInterruptedBgmIfNeeded();
}
#endregion
@@ -435,6 +461,53 @@ namespace CustomComponent
_isPaused = false;
}
private void OnCombineCompleted(object sender, GameFramework.Event.GameEventArgs e)
{
if (!(e is CombineCompletedEventArgs))
{
return;
}
RestoreInterruptedBgmIfNeeded();
}
private void SwitchToCombineBgm()
{
if (!_autoSwitchBgmOnStart || _combineBgmId <= 0 || GameEntry.Sound == null)
{
return;
}
if (!_hasInterruptedBgm && GameEntry.Sound.TryGetCurrentBgmSnapshot(out int bgmId, out float timeSeconds))
{
if (bgmId != _combineBgmId)
{
_hasInterruptedBgm = true;
_interruptedBgmId = bgmId;
_interruptedBgmTimeSeconds = Mathf.Max(0f, timeSeconds);
}
}
GameEntry.Sound.PlayBGM(_combineBgmId);
}
private void RestoreInterruptedBgmIfNeeded()
{
if (!_autoRestoreInterruptedBgm || !_hasInterruptedBgm || GameEntry.Sound == null)
{
return;
}
if (_interruptedBgmId > 0)
{
GameEntry.Sound.PlayBGM(_interruptedBgmId, _interruptedBgmTimeSeconds);
}
_hasInterruptedBgm = false;
_interruptedBgmId = 0;
_interruptedBgmTimeSeconds = 0f;
}
/// <summary>
/// 获取当前拖拽根节点。
/// </summary>
@@ -0,0 +1,23 @@
using UnityEngine;
namespace CustomComponent
{
[CreateAssetMenu(menuName = "Story/Directive/Change BGM", fileName = "Directive_ChangeBGM")]
public sealed class StoryChangeBgmDirectiveAsset : StoryDirectiveAsset
{
[SerializeField] [Tooltip("BGM 配置表 Id;<=0 表示停止当前 BGM。")]
private int _bgmId = 0;
public override string ActionName => "ChangeBGM";
public override void Execute(StoryDirectorComponent director)
{
if (director == null)
{
return;
}
director.ExecuteChangeBgm(_bgmId);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2f756304e6e46b48c7cabf5887971fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,6 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using Event;
using Sound;
using UI;
using UnityEngine;
using UnityGameFramework.Runtime;
@@ -273,6 +274,27 @@ namespace CustomComponent
}
}
public void ExecuteChangeBgm(int bgmId)
{
if (GameEntry.Sound == null)
{
Log.Warning("StoryDirector change BGM failed. Sound component is missing.");
return;
}
if (bgmId <= 0)
{
GameEntry.Sound.StopMusic();
return;
}
int? serialId = GameEntry.Sound.PlayBGM(bgmId);
if (!serialId.HasValue)
{
Log.Warning("StoryDirector change BGM failed. bgmId={0}", bgmId.ToString());
}
}
public void ExecuteEndChapter(int chapterId)
{
int finalChapterId = chapterId > 0
@@ -31,15 +31,6 @@ namespace DataTable
private set;
}
/// <summary>
/// 获取背景音乐编号。
/// </summary>
public int BackgroundMusicId
{
get;
private set;
}
public override bool ParseDataRow(string dataRowString, object userData)
{
string[] columnStrings = dataRowString.Split(DataTableExtension.DataSplitSeparators);
@@ -53,7 +44,6 @@ namespace DataTable
m_Id = int.Parse(columnStrings[index++]);
index++;
AssetName = columnStrings[index++];
BackgroundMusicId = int.Parse(columnStrings[index++]);
GeneratePropertyArray();
return true;
@@ -67,7 +57,6 @@ namespace DataTable
{
m_Id = binaryReader.Read7BitEncodedInt32();
AssetName = binaryReader.ReadString();
BackgroundMusicId = binaryReader.Read7BitEncodedInt32();
}
}
@@ -14,7 +14,6 @@ namespace Procedure
{
private int _nextSceneId = 0;
private bool _isChangeSceneComplete = false;
private int _backgroundMusicId = 0;
public override bool UseNativeDialog => false;
@@ -59,7 +58,6 @@ namespace Procedure
GameEntry.Scene.LoadScene(AssetUtility.GetSceneAsset(drScene.AssetName), Constant.AssetPriority.SceneAsset,
this);
_backgroundMusicId = drScene.BackgroundMusicId;
}
protected override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown)
@@ -110,11 +108,6 @@ namespace Procedure
Log.Info("Load scene '{0}' OK.", ne.SceneAssetName);
if (_backgroundMusicId > 0)
{
GameEntry.Sound.PlayBGM(_backgroundMusicId);
}
_isChangeSceneComplete = true;
}
@@ -73,6 +73,8 @@ namespace Procedure
_menuFormController = new MenuFormController();
_menuFormController.OpenUI(new MenuFormContext());
GameEntry.Sound.PlayBGM(1);
}
protected override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown)
@@ -3,6 +3,7 @@ using DataTable;
using Definition;
using GameFramework.DataTable;
using GameFramework.Sound;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Sound
@@ -11,8 +12,17 @@ namespace Sound
{
private const float FadeVolumeDuration = 1f;
private static int? s_MusicSerialId = null;
private static int? s_CurrentBgmId = null;
private static float s_CurrentBgmStartOffsetSeconds = 0f;
private static float s_CurrentBgmStartRealtime = 0f;
public static int? PlayBGM(this SoundComponent soundComponent, int musicId, object userData = null)
{
return PlayBGM(soundComponent, musicId, 0f, userData);
}
public static int? PlayBGM(this SoundComponent soundComponent, int musicId, float startTimeSeconds,
object userData = null)
{
soundComponent.StopMusic();
@@ -30,8 +40,12 @@ namespace Sound
playSoundParams.VolumeInSoundGroup = 1f;
playSoundParams.FadeInSeconds = FadeVolumeDuration;
playSoundParams.SpatialBlend = 0f;
playSoundParams.Time = Mathf.Max(0f, startTimeSeconds);
s_MusicSerialId = soundComponent.PlaySound(AssetUtility.GetMusicAsset(drBgm.AssetName), "BGM",
Constant.AssetPriority.MusicAsset, playSoundParams, null, userData);
s_CurrentBgmId = musicId;
s_CurrentBgmStartOffsetSeconds = playSoundParams.Time;
s_CurrentBgmStartRealtime = Time.realtimeSinceStartup;
return s_MusicSerialId;
}
@@ -44,6 +58,26 @@ namespace Sound
soundComponent.StopSound(s_MusicSerialId.Value, FadeVolumeDuration);
s_MusicSerialId = null;
s_CurrentBgmId = null;
s_CurrentBgmStartOffsetSeconds = 0f;
s_CurrentBgmStartRealtime = 0f;
}
public static bool TryGetCurrentBgmSnapshot(this SoundComponent soundComponent, out int bgmId,
out float timeSeconds)
{
bgmId = 0;
timeSeconds = 0f;
if (!s_MusicSerialId.HasValue || !s_CurrentBgmId.HasValue)
{
return false;
}
bgmId = s_CurrentBgmId.Value;
timeSeconds = s_CurrentBgmStartOffsetSeconds +
Mathf.Max(0f, Time.realtimeSinceStartup - s_CurrentBgmStartRealtime);
return true;
}
public static int? PlaySE(this SoundComponent soundComponent, int uiSoundId, object userData = null)
@@ -104,4 +138,4 @@ namespace Sound
GameEntry.Setting.Save();
}
}
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0e39aea8e25b93e43b730fa652754ced
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b2f756304e6e46b48c7cabf5887971fc, type: 3}
m_Name: ChangeBGM1001
m_EditorClassIdentifier:
_enabled: 1
_triggerType: 0
_triggerId: 1001
_bgmId: 4
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 68e4ca396e0f3904d9c130d93d0913e3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b2f756304e6e46b48c7cabf5887971fc, type: 3}
m_Name: ChangeBGM3001
m_EditorClassIdentifier:
_enabled: 1
_triggerType: 0
_triggerId: 3001
_bgmId: 6
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 09c4f714e027812448469d44cc86d2d2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b2f756304e6e46b48c7cabf5887971fc, type: 3}
m_Name: ChangeBGM4001
m_EditorClassIdentifier:
_enabled: 1
_triggerType: 0
_triggerId: 4001
_bgmId: 7
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 157a6b4146ed51d4fb33729f7bf4b94f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 85d19bdf6032a2f439ca1316169f03f1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90f2d30d7767cf346800345bf35d7837
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b1b56786ef9b8044bc50680f986568b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7c15202953ab22f4a9ad24f9f333a791
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: