[增加]1. 增加声音组件

This commit is contained in:
AlianBlank 2024-04-10 13:02:30 +08:00
parent 29a5bc0adf
commit 4bbf3628c7
77 changed files with 5139 additions and 1 deletions

8
Editor.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e5499d0d1ccff6408875a65197b94d6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
{
"name": "GameFrameX.Sound.Editor",
"references": [
"GameFrameX.Sound.Runtime",
"GameFrameX.Editor",
"GameFrameX.Runtime"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ea5f43a642897d44a9c413a11e71335b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Inspector.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9c445e0becac1ed459be7634b1a5d73f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,88 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Editor;
using GameFrameX.Sound.Runtime;
using UnityEditor;
namespace GameFrameX.Sound.Editor
{
[CustomEditor(typeof(SoundComponent))]
internal sealed class SoundComponentInspector : GameFrameworkInspector
{
// private SerializedProperty m_EnablePlaySoundUpdateEvent = null;
// private SerializedProperty m_EnablePlaySoundDependencyAssetEvent = null;
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_AudioMixer = null;
private SerializedProperty m_SoundGroups = null;
private HelperInfo<SoundHelperBase> m_SoundHelperInfo = new HelperInfo<SoundHelperBase>("Sound");
private HelperInfo<SoundGroupHelperBase> m_SoundGroupHelperInfo = new HelperInfo<SoundGroupHelperBase>("SoundGroup");
private HelperInfo<SoundAgentHelperBase> m_SoundAgentHelperInfo = new HelperInfo<SoundAgentHelperBase>("SoundAgent");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
SoundComponent t = (SoundComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
// EditorGUILayout.PropertyField(m_EnablePlaySoundUpdateEvent);
// EditorGUILayout.PropertyField(m_EnablePlaySoundDependencyAssetEvent);
EditorGUILayout.PropertyField(m_InstanceRoot);
EditorGUILayout.PropertyField(m_AudioMixer);
m_SoundHelperInfo.Draw();
m_SoundGroupHelperInfo.Draw();
m_SoundAgentHelperInfo.Draw();
EditorGUILayout.PropertyField(m_SoundGroups, true);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Sound Group Count", t.SoundGroupCount.ToString());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
// m_EnablePlaySoundUpdateEvent = serializedObject.FindProperty("m_EnablePlaySoundUpdateEvent");
// m_EnablePlaySoundDependencyAssetEvent = serializedObject.FindProperty("m_EnablePlaySoundDependencyAssetEvent");
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_AudioMixer = serializedObject.FindProperty("m_AudioMixer");
m_SoundGroups = serializedObject.FindProperty("m_SoundGroups");
m_SoundHelperInfo.Init(serializedObject);
m_SoundGroupHelperInfo.Init(serializedObject);
m_SoundAgentHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_SoundHelperInfo.Refresh();
m_SoundGroupHelperInfo.Refresh();
m_SoundAgentHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fad5b56ac3c54903b76e2c3bf2fb167d
timeCreated: 1712714844

201
LICENSE.md Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2023] [ALianBlank of copyright owner][alianblank@outlook.com][https://alianblank.com/]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

7
LICENSE.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 290a5934e1cb7ec41adeee4eef5dbea1
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1 +1,17 @@
# com.alianblank.gameframex.unity.sound
## HOMEPAGE
GameFrameX 的 Sound 声音管理组件
**Sound 声音管理组件 (Fsm Component)** - 提供声音管理组件相关的接口。
# 使用文档(文档编写于GPT4)
# 使用方式(任选其一)
1. 直接在 `manifest.json` 的文件中的 `dependencies` 节点下添加以下内容
```json
{"com.alianblank.gameframex.sound": "https://github.com/AlianBlank/com.alianblank.gameframex.unity.sound.git"}
```
2. 在Unity 的`Packages Manager` 中使用`Git URL` 的方式添加库,地址为https://github.com/AlianBlank/com.alianblank.gameframex.unity.sound.git
3. 直接下载仓库放置到Unity 项目的`Packages` 目录下。会自动加载识别

7
README.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2a4c79abb183a6f449e82491b52b7168
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b724027a57e0d7948a543f5f582a343e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

3
Runtime/EventArgs.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9d3b17619502428b961ec6e5873ffef9
timeCreated: 1712714824

View File

@ -0,0 +1,112 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Event;
namespace GameFrameX.Sound
{
/// <summary>
/// 播放声音失败事件。
/// </summary>
public sealed class PlaySoundFailureEventArgs : GameEventArgs
{
/// <summary>
/// 初始化播放声音失败事件的新实例。
/// </summary>
public PlaySoundFailureEventArgs()
{
SerialId = 0;
SoundAssetName = null;
SoundGroupName = null;
PlaySoundParams = null;
ErrorCode = PlaySoundErrorCode.Unknown;
ErrorMessage = null;
UserData = null;
}
/// <summary>
/// 获取声音的序列编号。
/// </summary>
public int SerialId { get; private set; }
/// <summary>
/// 获取声音资源名称。
/// </summary>
public string SoundAssetName { get; private set; }
/// <summary>
/// 获取声音组名称。
/// </summary>
public string SoundGroupName { get; private set; }
/// <summary>
/// 获取播放声音参数。
/// </summary>
public PlaySoundParams PlaySoundParams { get; private set; }
/// <summary>
/// 获取错误码。
/// </summary>
public PlaySoundErrorCode ErrorCode { get; private set; }
/// <summary>
/// 获取错误信息。
/// </summary>
public string ErrorMessage { get; private set; }
/// <summary>
/// 获取用户自定义数据。
/// </summary>
public object UserData { get; private set; }
/// <summary>
/// 创建播放声音失败事件。
/// </summary>
/// <param name="serialId">声音的序列编号。</param>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="errorCode">错误码。</param>
/// <param name="errorMessage">错误信息。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>创建的播放声音失败事件。</returns>
public static PlaySoundFailureEventArgs Create(int serialId, string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, PlaySoundErrorCode errorCode, string errorMessage,
object userData)
{
PlaySoundFailureEventArgs playSoundFailureEventArgs = ReferencePool.Acquire<PlaySoundFailureEventArgs>();
playSoundFailureEventArgs.SerialId = serialId;
playSoundFailureEventArgs.SoundAssetName = soundAssetName;
playSoundFailureEventArgs.SoundGroupName = soundGroupName;
playSoundFailureEventArgs.PlaySoundParams = playSoundParams;
playSoundFailureEventArgs.ErrorCode = errorCode;
playSoundFailureEventArgs.ErrorMessage = errorMessage;
playSoundFailureEventArgs.UserData = userData;
return playSoundFailureEventArgs;
}
/// <summary>
/// 清理播放声音失败事件。
/// </summary>
public override void Clear()
{
SerialId = 0;
SoundAssetName = null;
SoundGroupName = null;
PlaySoundParams = null;
ErrorCode = PlaySoundErrorCode.Unknown;
ErrorMessage = null;
UserData = null;
}
/// <summary>
/// 播放声音失败事件编号。
/// </summary>
public static readonly string EventId = typeof(PlaySoundFailureEventArgs).FullName;
public override string Id => EventId;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 54920a7ea93c4b2abdbe4686ea81804c
timeCreated: 1712714824

View File

@ -0,0 +1,96 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Event;
namespace GameFrameX.Sound
{
/// <summary>
/// 播放声音成功事件。
/// </summary>
public sealed class PlaySoundSuccessEventArgs : GameEventArgs
{
/// <summary>
/// 初始化播放声音成功事件的新实例。
/// </summary>
public PlaySoundSuccessEventArgs()
{
SerialId = 0;
SoundAssetName = null;
SoundAgent = null;
Duration = 0f;
UserData = null;
}
/// <summary>
/// 获取声音的序列编号。
/// </summary>
public int SerialId { get; private set; }
/// <summary>
/// 获取声音资源名称。
/// </summary>
public string SoundAssetName { get; private set; }
/// <summary>
/// 获取用于播放的声音代理。
/// </summary>
public ISoundAgent SoundAgent { get; private set; }
/// <summary>
/// 获取加载持续时间。
/// </summary>
public float Duration { get; private set; }
/// <summary>
/// 获取用户自定义数据。
/// </summary>
public object UserData { get; private set; }
/// <summary>
/// 创建播放声音成功事件。
/// </summary>
/// <param name="serialId">声音的序列编号。</param>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundAgent">用于播放的声音代理。</param>
/// <param name="duration">加载持续时间。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>创建的播放声音成功事件。</returns>
public static PlaySoundSuccessEventArgs Create(int serialId, string soundAssetName, ISoundAgent soundAgent, float duration, object userData)
{
PlaySoundSuccessEventArgs playSoundSuccessEventArgs = ReferencePool.Acquire<PlaySoundSuccessEventArgs>();
playSoundSuccessEventArgs.SerialId = serialId;
playSoundSuccessEventArgs.SoundAssetName = soundAssetName;
playSoundSuccessEventArgs.SoundAgent = soundAgent;
playSoundSuccessEventArgs.Duration = duration;
playSoundSuccessEventArgs.UserData = userData;
return playSoundSuccessEventArgs;
}
/// <summary>
/// 清理播放声音成功事件。
/// </summary>
public override void Clear()
{
SerialId = 0;
SoundAssetName = null;
SoundAgent = null;
Duration = 0f;
UserData = null;
}
/// <summary>
/// 播放声音成功事件编号。
/// </summary>
public static readonly string EventId = typeof(PlaySoundSuccessEventArgs).FullName;
public override string Id
{
get { return EventId; }
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b88db7007f8f40fbad3a701209b2be9a
timeCreated: 1712714824

View File

@ -0,0 +1,105 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Event;
namespace GameFrameX.Sound
{
/// <summary>
/// 播放声音更新事件。
/// </summary>
public sealed class PlaySoundUpdateEventArgs : GameEventArgs
{
/// <summary>
/// 初始化播放声音更新事件的新实例。
/// </summary>
public PlaySoundUpdateEventArgs()
{
SerialId = 0;
SoundAssetName = null;
SoundGroupName = null;
PlaySoundParams = null;
Progress = 0f;
UserData = null;
}
/// <summary>
/// 获取声音的序列编号。
/// </summary>
public int SerialId { get; private set; }
/// <summary>
/// 获取声音资源名称。
/// </summary>
public string SoundAssetName { get; private set; }
/// <summary>
/// 获取声音组名称。
/// </summary>
public string SoundGroupName { get; private set; }
/// <summary>
/// 获取播放声音参数。
/// </summary>
public PlaySoundParams PlaySoundParams { get; private set; }
/// <summary>
/// 获取加载声音进度。
/// </summary>
public float Progress { get; private set; }
/// <summary>
/// 获取用户自定义数据。
/// </summary>
public object UserData { get; private set; }
/// <summary>
/// 创建播放声音更新事件。
/// </summary>
/// <param name="serialId">声音的序列编号。</param>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="progress">加载声音进度。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>创建的播放声音更新事件。</returns>
public static PlaySoundUpdateEventArgs Create(int serialId, string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, float progress, object userData)
{
PlaySoundUpdateEventArgs playSoundUpdateEventArgs = ReferencePool.Acquire<PlaySoundUpdateEventArgs>();
playSoundUpdateEventArgs.SerialId = serialId;
playSoundUpdateEventArgs.SoundAssetName = soundAssetName;
playSoundUpdateEventArgs.SoundGroupName = soundGroupName;
playSoundUpdateEventArgs.PlaySoundParams = playSoundParams;
playSoundUpdateEventArgs.Progress = progress;
playSoundUpdateEventArgs.UserData = userData;
return playSoundUpdateEventArgs;
}
/// <summary>
/// 清理播放声音更新事件。
/// </summary>
public override void Clear()
{
SerialId = 0;
SoundAssetName = null;
SoundGroupName = null;
PlaySoundParams = null;
Progress = 0f;
UserData = null;
}
/// <summary>
/// 播放声音更新事件编号。
/// </summary>
public static readonly string EventId = typeof(PlaySoundUpdateEventArgs).FullName;
public override string Id
{
get { return EventId; }
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 807b4c21ad6445249ab12070a7456f7e
timeCreated: 1712714824

View File

@ -0,0 +1,51 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Event;
namespace GameFrameX.Sound
{
/// <summary>
/// 重置声音代理事件。
/// </summary>
public sealed class ResetSoundAgentEventArgs : GameEventArgs
{
/// <summary>
/// 初始化重置声音代理事件的新实例。
/// </summary>
public ResetSoundAgentEventArgs()
{
}
/// <summary>
/// 创建重置声音代理事件。
/// </summary>
/// <returns>创建的重置声音代理事件。</returns>
public static ResetSoundAgentEventArgs Create()
{
ResetSoundAgentEventArgs resetSoundAgentEventArgs = ReferencePool.Acquire<ResetSoundAgentEventArgs>();
return resetSoundAgentEventArgs;
}
/// <summary>
/// 清理重置声音代理事件。
/// </summary>
public override void Clear()
{
}
/// <summary>
/// 播放声音更新事件编号。
/// </summary>
public static readonly string EventId = typeof(ResetSoundAgentEventArgs).FullName;
public override string Id
{
get { return EventId; }
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e23ee74431f84e159033a0b2523aea84
timeCreated: 1712714824

View File

@ -0,0 +1,16 @@
{
"name": "GameFrameX.Sound.Runtime",
"references": [
"GameFrameX.Runtime"
],
"rootNamespace": "GameFrameX.Sound.Runtime",
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4f801b565dcbc1d4c80cc24f3de61c63
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
using UnityEngine;
namespace GameFrameX.Sound.Runtime
{
public class GameFrameXSoundCroppingHelper : MonoBehaviour
{
private void Start()
{
_ = typeof(DefaultSoundAgentHelper);
_ = typeof(DefaultSoundGroupHelper);
_ = typeof(DefaultSoundHelper);
_ = typeof(PlaySoundInfo);
_ = typeof(SoundAgentHelperBase);
_ = typeof(SoundComponent);
_ = typeof(SoundGroupHelperBase);
_ = typeof(SoundHelperBase);
_ = typeof(Constant);
_ = typeof(ISoundAgent);
_ = typeof(ISoundAgentHelper);
_ = typeof(ISoundGroup);
_ = typeof(ISoundGroupHelper);
_ = typeof(ISoundHelper);
_ = typeof(ISoundManager);
_ = typeof(PlaySoundErrorCode);
_ = typeof(PlaySoundFailureEventArgs);
_ = typeof(PlaySoundParams);
_ = typeof(PlaySoundSuccessEventArgs);
_ = typeof(PlaySoundUpdateEventArgs);
_ = typeof(ResetSoundAgentEventArgs);
_ = typeof(SoundManager);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0e2379e8acbf1564f919f09bbbf8e7c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

3
Runtime/Sound.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4ca0ea8697ef41eea21187413329c860
timeCreated: 1712714824

View File

@ -0,0 +1,434 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX;
using GameFrameX.Sound;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Audio;
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 默认声音代理辅助器。
/// </summary>
public class DefaultSoundAgentHelper : SoundAgentHelperBase
{
private Transform m_CachedTransform = null;
private AudioSource m_AudioSource = null;
private EntityLogic m_BindingEntityLogic = null;
private float m_VolumeWhenPause = 0f;
private bool m_ApplicationPauseFlag = false;
private EventHandler<ResetSoundAgentEventArgs> m_ResetSoundAgentEventHandler = null;
/// <summary>
/// 获取当前是否正在播放。
/// </summary>
public override bool IsPlaying
{
get
{
return m_AudioSource.isPlaying;
}
}
/// <summary>
/// 获取声音长度。
/// </summary>
public override float Length
{
get
{
return m_AudioSource.clip != null ? m_AudioSource.clip.length : 0f;
}
}
/// <summary>
/// 获取或设置播放位置。
/// </summary>
public override float Time
{
get
{
return m_AudioSource.time;
}
set
{
m_AudioSource.time = value;
}
}
/// <summary>
/// 获取或设置是否静音。
/// </summary>
public override bool Mute
{
get
{
return m_AudioSource.mute;
}
set
{
m_AudioSource.mute = value;
}
}
/// <summary>
/// 获取或设置是否循环播放。
/// </summary>
public override bool Loop
{
get
{
return m_AudioSource.loop;
}
set
{
m_AudioSource.loop = value;
}
}
/// <summary>
/// 获取或设置声音优先级。
/// </summary>
public override int Priority
{
get
{
return 128 - m_AudioSource.priority;
}
set
{
m_AudioSource.priority = 128 - value;
}
}
/// <summary>
/// 获取或设置音量大小。
/// </summary>
public override float Volume
{
get
{
return m_AudioSource.volume;
}
set
{
m_AudioSource.volume = value;
}
}
/// <summary>
/// 获取或设置声音音调。
/// </summary>
public override float Pitch
{
get
{
return m_AudioSource.pitch;
}
set
{
m_AudioSource.pitch = value;
}
}
/// <summary>
/// 获取或设置声音立体声声相。
/// </summary>
public override float PanStereo
{
get
{
return m_AudioSource.panStereo;
}
set
{
m_AudioSource.panStereo = value;
}
}
/// <summary>
/// 获取或设置声音空间混合量。
/// </summary>
public override float SpatialBlend
{
get
{
return m_AudioSource.spatialBlend;
}
set
{
m_AudioSource.spatialBlend = value;
}
}
/// <summary>
/// 获取或设置声音最大距离。
/// </summary>
public override float MaxDistance
{
get
{
return m_AudioSource.maxDistance;
}
set
{
m_AudioSource.maxDistance = value;
}
}
/// <summary>
/// 获取或设置声音多普勒等级。
/// </summary>
public override float DopplerLevel
{
get
{
return m_AudioSource.dopplerLevel;
}
set
{
m_AudioSource.dopplerLevel = value;
}
}
/// <summary>
/// 获取或设置声音代理辅助器所在的混音组。
/// </summary>
public override AudioMixerGroup AudioMixerGroup
{
get
{
return m_AudioSource.outputAudioMixerGroup;
}
set
{
m_AudioSource.outputAudioMixerGroup = value;
}
}
/// <summary>
/// 重置声音代理事件。
/// </summary>
public override event EventHandler<ResetSoundAgentEventArgs> ResetSoundAgent
{
add
{
m_ResetSoundAgentEventHandler += value;
}
remove
{
m_ResetSoundAgentEventHandler -= value;
}
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public override void Play(float fadeInSeconds)
{
StopAllCoroutines();
m_AudioSource.Play();
if (fadeInSeconds > 0f)
{
float volume = m_AudioSource.volume;
m_AudioSource.volume = 0f;
StartCoroutine(FadeToVolume(m_AudioSource, volume, fadeInSeconds));
}
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public override void Stop(float fadeOutSeconds)
{
StopAllCoroutines();
if (fadeOutSeconds > 0f && gameObject.activeInHierarchy)
{
StartCoroutine(StopCo(fadeOutSeconds));
}
else
{
m_AudioSource.Stop();
}
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public override void Pause(float fadeOutSeconds)
{
StopAllCoroutines();
m_VolumeWhenPause = m_AudioSource.volume;
if (fadeOutSeconds > 0f && gameObject.activeInHierarchy)
{
StartCoroutine(PauseCo(fadeOutSeconds));
}
else
{
m_AudioSource.Pause();
}
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public override void Resume(float fadeInSeconds)
{
StopAllCoroutines();
m_AudioSource.UnPause();
if (fadeInSeconds > 0f)
{
StartCoroutine(FadeToVolume(m_AudioSource, m_VolumeWhenPause, fadeInSeconds));
}
else
{
m_AudioSource.volume = m_VolumeWhenPause;
}
}
/// <summary>
/// 重置声音代理辅助器。
/// </summary>
public override void Reset()
{
m_CachedTransform.localPosition = Vector3.zero;
m_AudioSource.clip = null;
m_BindingEntityLogic = null;
m_VolumeWhenPause = 0f;
}
/// <summary>
/// 设置声音资源。
/// </summary>
/// <param name="soundAsset">声音资源。</param>
/// <returns>是否设置声音资源成功。</returns>
public override bool SetSoundAsset(object soundAsset)
{
AudioClip audioClip = soundAsset as AudioClip;
if (audioClip == null)
{
return false;
}
m_AudioSource.clip = audioClip;
return true;
}
/// <summary>
/// 设置声音绑定的实体。
/// </summary>
/// <param name="bindingEntity">声音绑定的实体。</param>
public override void SetBindingEntity(Entity bindingEntity)
{
m_BindingEntityLogic = bindingEntity.Logic;
if (m_BindingEntityLogic != null)
{
UpdateAgentPosition();
return;
}
if (m_ResetSoundAgentEventHandler != null)
{
ResetSoundAgentEventArgs resetSoundAgentEventArgs = ResetSoundAgentEventArgs.Create();
m_ResetSoundAgentEventHandler(this, resetSoundAgentEventArgs);
ReferencePool.Release(resetSoundAgentEventArgs);
}
}
/// <summary>
/// 设置声音所在的世界坐标。
/// </summary>
/// <param name="worldPosition">声音所在的世界坐标。</param>
public override void SetWorldPosition(Vector3 worldPosition)
{
m_CachedTransform.position = worldPosition;
}
private void Awake()
{
m_CachedTransform = transform;
m_AudioSource = gameObject.GetOrAddComponent<AudioSource>();
m_AudioSource.playOnAwake = false;
m_AudioSource.rolloffMode = AudioRolloffMode.Custom;
}
private void Update()
{
if (!m_ApplicationPauseFlag && !IsPlaying && m_AudioSource.clip != null && m_ResetSoundAgentEventHandler != null)
{
ResetSoundAgentEventArgs resetSoundAgentEventArgs = ResetSoundAgentEventArgs.Create();
m_ResetSoundAgentEventHandler(this, resetSoundAgentEventArgs);
ReferencePool.Release(resetSoundAgentEventArgs);
return;
}
if (m_BindingEntityLogic != null)
{
UpdateAgentPosition();
}
}
private void OnApplicationPause(bool pause)
{
m_ApplicationPauseFlag = pause;
}
private void UpdateAgentPosition()
{
if (m_BindingEntityLogic.Available)
{
m_CachedTransform.position = m_BindingEntityLogic.CachedTransform.position;
return;
}
if (m_ResetSoundAgentEventHandler != null)
{
ResetSoundAgentEventArgs resetSoundAgentEventArgs = ResetSoundAgentEventArgs.Create();
m_ResetSoundAgentEventHandler(this, resetSoundAgentEventArgs);
ReferencePool.Release(resetSoundAgentEventArgs);
}
}
private IEnumerator StopCo(float fadeOutSeconds)
{
yield return FadeToVolume(m_AudioSource, 0f, fadeOutSeconds);
m_AudioSource.Stop();
}
private IEnumerator PauseCo(float fadeOutSeconds)
{
yield return FadeToVolume(m_AudioSource, 0f, fadeOutSeconds);
m_AudioSource.Pause();
}
private IEnumerator FadeToVolume(AudioSource audioSource, float volume, float duration)
{
float time = 0f;
float originalVolume = audioSource.volume;
while (time < duration)
{
time += UnityEngine.Time.deltaTime;
audioSource.volume = Mathf.Lerp(originalVolume, volume, time / duration);
yield return new WaitForEndOfFrame();
}
audioSource.volume = volume;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 12be067a3b174004830b32456da453cf
timeCreated: 1712714824

View File

@ -0,0 +1,16 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 默认声音组辅助器。
/// </summary>
public class DefaultSoundGroupHelper : SoundGroupHelperBase
{
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ad8d81d5c1d643bfa7f516959f14ada2
timeCreated: 1712714824

View File

@ -0,0 +1,38 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Asset;
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 默认声音辅助器。
/// </summary>
public class DefaultSoundHelper : SoundHelperBase
{
private IAssetManager m_ResourceComponent = null;
/// <summary>
/// 释放声音资源。
/// </summary>
/// <param name="soundAsset">要释放的声音资源。</param>
public override void ReleaseSoundAsset(object soundAsset)
{
// m_ResourceComponent.UnloadAsset(soundAsset);
}
private void Start()
{
m_ResourceComponent = GameFrameworkEntry.GetModule<IAssetManager>();
if (m_ResourceComponent == null)
{
Log.Fatal("Resource component is invalid.");
return;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e95bc3bf491047fca897de7a89b54956
timeCreated: 1712714824

View File

@ -0,0 +1,66 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX;
using UnityEngine;
namespace GameFrameX.Sound.Runtime
{
internal sealed class PlaySoundInfo : IReference
{
private Entity m_BindingEntity;
private Vector3 m_WorldPosition;
private object m_UserData;
public PlaySoundInfo()
{
m_BindingEntity = null;
m_WorldPosition = Vector3.zero;
m_UserData = null;
}
public Entity BindingEntity
{
get
{
return m_BindingEntity;
}
}
public Vector3 WorldPosition
{
get
{
return m_WorldPosition;
}
}
public object UserData
{
get
{
return m_UserData;
}
}
public static PlaySoundInfo Create(Entity bindingEntity, Vector3 worldPosition, object userData)
{
PlaySoundInfo playSoundInfo = ReferencePool.Acquire<PlaySoundInfo>();
playSoundInfo.m_BindingEntity = bindingEntity;
playSoundInfo.m_WorldPosition = worldPosition;
playSoundInfo.m_UserData = userData;
return playSoundInfo;
}
public void Clear()
{
m_BindingEntity = null;
m_WorldPosition = Vector3.zero;
m_UserData = null;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8d546b7a042b428e99c75caf7a4c55f2
timeCreated: 1712714824

3
Runtime/Sound/Sound.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c4000084ff114abdbb80bddb8f307bf1
timeCreated: 1712714824

View File

@ -0,0 +1,28 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 声音相关常量。
/// </summary>
internal static class Constant
{
internal const float DefaultTime = 0f;
internal const bool DefaultMute = false;
internal const bool DefaultLoop = false;
internal const int DefaultPriority = 0;
internal const float DefaultVolume = 1f;
internal const float DefaultFadeInSeconds = 0f;
internal const float DefaultFadeOutSeconds = 0f;
internal const float DefaultPitch = 1f;
internal const float DefaultPanStereo = 0f;
internal const float DefaultSpatialBlend = 0f;
internal const float DefaultMaxDistance = 100f;
internal const float DefaultDopplerLevel = 1f;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b379b53a91c84d69a8166683fc99c7a3
timeCreated: 1712714824

View File

@ -0,0 +1,210 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 声音代理接口。
/// </summary>
public interface ISoundAgent
{
/// <summary>
/// 获取所在的声音组。
/// </summary>
ISoundGroup SoundGroup
{
get;
}
/// <summary>
/// 获取声音的序列编号。
/// </summary>
int SerialId
{
get;
}
/// <summary>
/// 获取当前是否正在播放。
/// </summary>
bool IsPlaying
{
get;
}
/// <summary>
/// 获取声音长度。
/// </summary>
float Length
{
get;
}
/// <summary>
/// 获取或设置播放位置。
/// </summary>
float Time
{
get;
set;
}
/// <summary>
/// 获取或设置是否静音。
/// </summary>
bool Mute
{
get;
}
/// <summary>
/// 获取或设置在声音组内是否静音。
/// </summary>
bool MuteInSoundGroup
{
get;
set;
}
/// <summary>
/// 获取或设置是否循环播放。
/// </summary>
bool Loop
{
get;
set;
}
/// <summary>
/// 获取或设置声音优先级。
/// </summary>
int Priority
{
get;
set;
}
/// <summary>
/// 获取音量大小。
/// </summary>
float Volume
{
get;
}
/// <summary>
/// 获取或设置在声音组内音量大小。
/// </summary>
float VolumeInSoundGroup
{
get;
set;
}
/// <summary>
/// 获取或设置声音音调。
/// </summary>
float Pitch
{
get;
set;
}
/// <summary>
/// 获取或设置声音立体声声相。
/// </summary>
float PanStereo
{
get;
set;
}
/// <summary>
/// 获取或设置声音空间混合量。
/// </summary>
float SpatialBlend
{
get;
set;
}
/// <summary>
/// 获取或设置声音最大距离。
/// </summary>
float MaxDistance
{
get;
set;
}
/// <summary>
/// 获取或设置声音多普勒等级。
/// </summary>
float DopplerLevel
{
get;
set;
}
/// <summary>
/// 获取声音代理辅助器。
/// </summary>
ISoundAgentHelper Helper
{
get;
}
/// <summary>
/// 播放声音。
/// </summary>
void Play();
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
void Play(float fadeInSeconds);
/// <summary>
/// 停止播放声音。
/// </summary>
void Stop();
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void Stop(float fadeOutSeconds);
/// <summary>
/// 暂停播放声音。
/// </summary>
void Pause();
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void Pause(float fadeOutSeconds);
/// <summary>
/// 恢复播放声音。
/// </summary>
void Resume();
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
void Resume(float fadeInSeconds);
/// <summary>
/// 重置声音代理。
/// </summary>
void Reset();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d76418ac4ffa48529755ecc96239f050
timeCreated: 1712714824

View File

@ -0,0 +1,164 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
namespace GameFrameX.Sound
{
/// <summary>
/// 声音代理辅助器接口。
/// </summary>
public interface ISoundAgentHelper
{
/// <summary>
/// 获取当前是否正在播放。
/// </summary>
bool IsPlaying
{
get;
}
/// <summary>
/// 获取声音长度。
/// </summary>
float Length
{
get;
}
/// <summary>
/// 获取或设置播放位置。
/// </summary>
float Time
{
get;
set;
}
/// <summary>
/// 获取或设置是否静音。
/// </summary>
bool Mute
{
get;
set;
}
/// <summary>
/// 获取或设置是否循环播放。
/// </summary>
bool Loop
{
get;
set;
}
/// <summary>
/// 获取或设置声音优先级。
/// </summary>
int Priority
{
get;
set;
}
/// <summary>
/// 获取或设置音量大小。
/// </summary>
float Volume
{
get;
set;
}
/// <summary>
/// 获取或设置声音音调。
/// </summary>
float Pitch
{
get;
set;
}
/// <summary>
/// 获取或设置声音立体声声相。
/// </summary>
float PanStereo
{
get;
set;
}
/// <summary>
/// 获取或设置声音空间混合量。
/// </summary>
float SpatialBlend
{
get;
set;
}
/// <summary>
/// 获取或设置声音最大距离。
/// </summary>
float MaxDistance
{
get;
set;
}
/// <summary>
/// 获取或设置声音多普勒等级。
/// </summary>
float DopplerLevel
{
get;
set;
}
/// <summary>
/// 重置声音代理事件。
/// </summary>
event EventHandler<ResetSoundAgentEventArgs> ResetSoundAgent;
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
void Play(float fadeInSeconds);
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void Stop(float fadeOutSeconds);
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void Pause(float fadeOutSeconds);
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
void Resume(float fadeInSeconds);
/// <summary>
/// 重置声音代理辅助器。
/// </summary>
void Reset();
/// <summary>
/// 设置声音资源。
/// </summary>
/// <param name="soundAsset">声音资源。</param>
/// <returns>是否设置声音资源成功。</returns>
bool SetSoundAsset(object soundAsset);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e393a6a841c34d9794c8ff371678ffc3
timeCreated: 1712714824

View File

@ -0,0 +1,77 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 声音组接口。
/// </summary>
public interface ISoundGroup
{
/// <summary>
/// 获取声音组名称。
/// </summary>
string Name
{
get;
}
/// <summary>
/// 获取声音代理数。
/// </summary>
int SoundAgentCount
{
get;
}
/// <summary>
/// 获取或设置声音组中的声音是否避免被同优先级声音替换。
/// </summary>
bool AvoidBeingReplacedBySamePriority
{
get;
set;
}
/// <summary>
/// 获取或设置声音组静音。
/// </summary>
bool Mute
{
get;
set;
}
/// <summary>
/// 获取或设置声音组音量。
/// </summary>
float Volume
{
get;
set;
}
/// <summary>
/// 获取声音组辅助器。
/// </summary>
ISoundGroupHelper Helper
{
get;
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
void StopAllLoadedSounds();
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void StopAllLoadedSounds(float fadeOutSeconds);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 271c56a451d24fe99c627c87c4558ca7
timeCreated: 1712714824

View File

@ -0,0 +1,16 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 声音组辅助器接口。
/// </summary>
public interface ISoundGroupHelper
{
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 220fb3b3984049dba6f2c994b64ba688
timeCreated: 1712714824

View File

@ -0,0 +1,21 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 声音辅助器接口。
/// </summary>
public interface ISoundHelper
{
/// <summary>
/// 释放声音资源。
/// </summary>
/// <param name="soundAsset">要释放的声音资源。</param>
void ReleaseSoundAsset(object soundAsset);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2848f97390a944bd94c9a60fbf87ef4c
timeCreated: 1712714824

View File

@ -0,0 +1,257 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using GameFrameX.Asset;
using GameFrameX.Runtime;
namespace GameFrameX.Sound
{
/// <summary>
/// 声音管理器接口。
/// </summary>
public interface ISoundManager
{
/// <summary>
/// 获取声音组数量。
/// </summary>
int SoundGroupCount { get; }
/// <summary>
/// 播放声音成功事件。
/// </summary>
event EventHandler<PlaySoundSuccessEventArgs> PlaySoundSuccess;
/// <summary>
/// 播放声音失败事件。
/// </summary>
event EventHandler<PlaySoundFailureEventArgs> PlaySoundFailure;
/*/// <summary>
/// 播放声音更新事件。
/// </summary>
event EventHandler<PlaySoundUpdateEventArgs> PlaySoundUpdate;*/
/// <summary>
/// 设置资源管理器。
/// </summary>
/// <param name="assetManager">资源管理器。</param>
void SetResourceManager(IAssetManager assetManager);
/// <summary>
/// 设置声音辅助器。
/// </summary>
/// <param name="soundHelper">声音辅助器。</param>
void SetSoundHelper(ISoundHelper soundHelper);
/// <summary>
/// 是否存在指定声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>指定声音组是否存在。</returns>
bool HasSoundGroup(string soundGroupName);
/// <summary>
/// 获取指定声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>要获取的声音组。</returns>
ISoundGroup GetSoundGroup(string soundGroupName);
/// <summary>
/// 获取所有声音组。
/// </summary>
/// <returns>所有声音组。</returns>
ISoundGroup[] GetAllSoundGroups();
/// <summary>
/// 获取所有声音组。
/// </summary>
/// <param name="results">所有声音组。</param>
void GetAllSoundGroups(List<ISoundGroup> results);
/// <summary>
/// 增加声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundGroupHelper">声音组辅助器。</param>
/// <returns>是否增加声音组成功。</returns>
bool AddSoundGroup(string soundGroupName, ISoundGroupHelper soundGroupHelper);
/// <summary>
/// 增加声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundGroupAvoidBeingReplacedBySamePriority">声音组中的声音是否避免被同优先级声音替换。</param>
/// <param name="soundGroupMute">声音组是否静音。</param>
/// <param name="soundGroupVolume">声音组音量。</param>
/// <param name="soundGroupHelper">声音组辅助器。</param>
/// <returns>是否增加声音组成功。</returns>
bool AddSoundGroup(string soundGroupName, bool soundGroupAvoidBeingReplacedBySamePriority, bool soundGroupMute, float soundGroupVolume, ISoundGroupHelper soundGroupHelper);
/// <summary>
/// 增加声音代理辅助器。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundAgentHelper">要增加的声音代理辅助器。</param>
void AddSoundAgentHelper(string soundGroupName, ISoundAgentHelper soundAgentHelper);
/// <summary>
/// 获取所有正在加载声音的序列编号。
/// </summary>
/// <returns>所有正在加载声音的序列编号。</returns>
int[] GetAllLoadingSoundSerialIds();
/// <summary>
/// 获取所有正在加载声音的序列编号。
/// </summary>
/// <param name="results">所有正在加载声音的序列编号。</param>
void GetAllLoadingSoundSerialIds(List<int> results);
/// <summary>
/// 是否正在加载声音。
/// </summary>
/// <param name="serialId">声音序列编号。</param>
/// <returns>是否正在加载声音。</returns>
bool IsLoadingSound(int serialId);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, object userData);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority, object userData);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, object userData);
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, object userData);
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <returns>是否停止播放声音成功。</returns>
bool StopSound(int serialId);
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
/// <returns>是否停止播放声音成功。</returns>
bool StopSound(int serialId, float fadeOutSeconds);
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
void StopAllLoadedSounds();
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void StopAllLoadedSounds(float fadeOutSeconds);
/// <summary>
/// 停止所有正在加载的声音。
/// </summary>
void StopAllLoadingSounds();
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
void PauseSound(int serialId);
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
void PauseSound(int serialId, float fadeOutSeconds);
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
void ResumeSound(int serialId);
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
void ResumeSound(int serialId, float fadeInSeconds);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 89c83e2319444b28bac6b79c52b3b860
timeCreated: 1712714824

View File

@ -0,0 +1,45 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 播放声音错误码。
/// </summary>
public enum PlaySoundErrorCode : byte
{
/// <summary>
/// 未知错误。
/// </summary>
Unknown = 0,
/// <summary>
/// 声音组不存在。
/// </summary>
SoundGroupNotExist,
/// <summary>
/// 声音组没有声音代理。
/// </summary>
SoundGroupHasNoAgent,
/// <summary>
/// 加载资源失败。
/// </summary>
LoadAssetFailure,
/// <summary>
/// 播放声音因优先级低被忽略。
/// </summary>
IgnoredDueToLowPriority,
/// <summary>
/// 设置声音资源失败。
/// </summary>
SetSoundAssetFailure
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8fd0d0d995ca4fb8957083fa92c5c0f4
timeCreated: 1712714824

View File

@ -0,0 +1,249 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
/// <summary>
/// 播放声音参数。
/// </summary>
public sealed class PlaySoundParams : IReference
{
private bool m_Referenced;
private float m_Time;
private bool m_MuteInSoundGroup;
private bool m_Loop;
private int m_Priority;
private float m_VolumeInSoundGroup;
private float m_FadeInSeconds;
private float m_Pitch;
private float m_PanStereo;
private float m_SpatialBlend;
private float m_MaxDistance;
private float m_DopplerLevel;
/// <summary>
/// 初始化播放声音参数的新实例。
/// </summary>
public PlaySoundParams()
{
m_Referenced = false;
m_Time = Constant.DefaultTime;
m_MuteInSoundGroup = Constant.DefaultMute;
m_Loop = Constant.DefaultLoop;
m_Priority = Constant.DefaultPriority;
m_VolumeInSoundGroup = Constant.DefaultVolume;
m_FadeInSeconds = Constant.DefaultFadeInSeconds;
m_Pitch = Constant.DefaultPitch;
m_PanStereo = Constant.DefaultPanStereo;
m_SpatialBlend = Constant.DefaultSpatialBlend;
m_MaxDistance = Constant.DefaultMaxDistance;
m_DopplerLevel = Constant.DefaultDopplerLevel;
}
/// <summary>
/// 获取或设置播放位置。
/// </summary>
public float Time
{
get
{
return m_Time;
}
set
{
m_Time = value;
}
}
/// <summary>
/// 获取或设置在声音组内是否静音。
/// </summary>
public bool MuteInSoundGroup
{
get
{
return m_MuteInSoundGroup;
}
set
{
m_MuteInSoundGroup = value;
}
}
/// <summary>
/// 获取或设置是否循环播放。
/// </summary>
public bool Loop
{
get
{
return m_Loop;
}
set
{
m_Loop = value;
}
}
/// <summary>
/// 获取或设置声音优先级。
/// </summary>
public int Priority
{
get
{
return m_Priority;
}
set
{
m_Priority = value;
}
}
/// <summary>
/// 获取或设置在声音组内音量大小。
/// </summary>
public float VolumeInSoundGroup
{
get
{
return m_VolumeInSoundGroup;
}
set
{
m_VolumeInSoundGroup = value;
}
}
/// <summary>
/// 获取或设置声音淡入时间,以秒为单位。
/// </summary>
public float FadeInSeconds
{
get
{
return m_FadeInSeconds;
}
set
{
m_FadeInSeconds = value;
}
}
/// <summary>
/// 获取或设置声音音调。
/// </summary>
public float Pitch
{
get
{
return m_Pitch;
}
set
{
m_Pitch = value;
}
}
/// <summary>
/// 获取或设置声音立体声声相。
/// </summary>
public float PanStereo
{
get
{
return m_PanStereo;
}
set
{
m_PanStereo = value;
}
}
/// <summary>
/// 获取或设置声音空间混合量。
/// </summary>
public float SpatialBlend
{
get
{
return m_SpatialBlend;
}
set
{
m_SpatialBlend = value;
}
}
/// <summary>
/// 获取或设置声音最大距离。
/// </summary>
public float MaxDistance
{
get
{
return m_MaxDistance;
}
set
{
m_MaxDistance = value;
}
}
/// <summary>
/// 获取或设置声音多普勒等级。
/// </summary>
public float DopplerLevel
{
get
{
return m_DopplerLevel;
}
set
{
m_DopplerLevel = value;
}
}
internal bool Referenced
{
get
{
return m_Referenced;
}
}
/// <summary>
/// 创建播放声音参数。
/// </summary>
/// <returns>创建的播放声音参数。</returns>
public static PlaySoundParams Create()
{
PlaySoundParams playSoundParams = ReferencePool.Acquire<PlaySoundParams>();
playSoundParams.m_Referenced = true;
return playSoundParams;
}
/// <summary>
/// 清理播放声音参数。
/// </summary>
public void Clear()
{
m_Time = Constant.DefaultTime;
m_MuteInSoundGroup = Constant.DefaultMute;
m_Loop = Constant.DefaultLoop;
m_Priority = Constant.DefaultPriority;
m_VolumeInSoundGroup = Constant.DefaultVolume;
m_FadeInSeconds = Constant.DefaultFadeInSeconds;
m_Pitch = Constant.DefaultPitch;
m_PanStereo = Constant.DefaultPanStereo;
m_SpatialBlend = Constant.DefaultSpatialBlend;
m_MaxDistance = Constant.DefaultMaxDistance;
m_DopplerLevel = Constant.DefaultDopplerLevel;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4b90e8d384164c7185ce363221abae2a
timeCreated: 1712714824

View File

@ -0,0 +1,78 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
namespace GameFrameX.Sound
{
public sealed partial class SoundManager : GameFrameworkModule, ISoundManager
{
private sealed class PlaySoundInfo : IReference
{
private int m_SerialId;
private SoundGroup m_SoundGroup;
private PlaySoundParams m_PlaySoundParams;
private object m_UserData;
public PlaySoundInfo()
{
m_SerialId = 0;
m_SoundGroup = null;
m_PlaySoundParams = null;
m_UserData = null;
}
public int SerialId
{
get
{
return m_SerialId;
}
}
public SoundGroup SoundGroup
{
get
{
return m_SoundGroup;
}
}
public PlaySoundParams PlaySoundParams
{
get
{
return m_PlaySoundParams;
}
}
public object UserData
{
get
{
return m_UserData;
}
}
public static PlaySoundInfo Create(int serialId, SoundGroup soundGroup, PlaySoundParams playSoundParams, object userData)
{
PlaySoundInfo playSoundInfo = ReferencePool.Acquire<PlaySoundInfo>();
playSoundInfo.m_SerialId = serialId;
playSoundInfo.m_SoundGroup = soundGroup;
playSoundInfo.m_PlaySoundParams = playSoundParams;
playSoundInfo.m_UserData = userData;
return playSoundInfo;
}
public void Clear()
{
m_SerialId = 0;
m_SoundGroup = null;
m_PlaySoundParams = null;
m_UserData = null;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 02d5d9692a9040439f5f35120df57a38
timeCreated: 1712714824

View File

@ -0,0 +1,421 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
namespace GameFrameX.Sound
{
public sealed partial class SoundManager : GameFrameworkModule, ISoundManager
{
/// <summary>
/// 声音代理。
/// </summary>
private sealed class SoundAgent : ISoundAgent
{
private readonly SoundGroup m_SoundGroup;
private readonly ISoundHelper m_SoundHelper;
private readonly ISoundAgentHelper m_SoundAgentHelper;
private int m_SerialId;
private object m_SoundAsset;
private DateTime m_SetSoundAssetTime;
private bool m_MuteInSoundGroup;
private float m_VolumeInSoundGroup;
/// <summary>
/// 初始化声音代理的新实例。
/// </summary>
/// <param name="soundGroup">所在的声音组。</param>
/// <param name="soundHelper">声音辅助器接口。</param>
/// <param name="soundAgentHelper">声音代理辅助器接口。</param>
public SoundAgent(SoundGroup soundGroup, ISoundHelper soundHelper, ISoundAgentHelper soundAgentHelper)
{
if (soundGroup == null)
{
throw new GameFrameworkException("Sound group is invalid.");
}
if (soundHelper == null)
{
throw new GameFrameworkException("Sound helper is invalid.");
}
if (soundAgentHelper == null)
{
throw new GameFrameworkException("Sound agent helper is invalid.");
}
m_SoundGroup = soundGroup;
m_SoundHelper = soundHelper;
m_SoundAgentHelper = soundAgentHelper;
m_SoundAgentHelper.ResetSoundAgent += OnResetSoundAgent;
m_SerialId = 0;
m_SoundAsset = null;
Reset();
}
/// <summary>
/// 获取所在的声音组。
/// </summary>
public ISoundGroup SoundGroup
{
get
{
return m_SoundGroup;
}
}
/// <summary>
/// 获取或设置声音的序列编号。
/// </summary>
public int SerialId
{
get
{
return m_SerialId;
}
set
{
m_SerialId = value;
}
}
/// <summary>
/// 获取当前是否正在播放。
/// </summary>
public bool IsPlaying
{
get
{
return m_SoundAgentHelper.IsPlaying;
}
}
/// <summary>
/// 获取声音长度。
/// </summary>
public float Length
{
get
{
return m_SoundAgentHelper.Length;
}
}
/// <summary>
/// 获取或设置播放位置。
/// </summary>
public float Time
{
get
{
return m_SoundAgentHelper.Time;
}
set
{
m_SoundAgentHelper.Time = value;
}
}
/// <summary>
/// 获取是否静音。
/// </summary>
public bool Mute
{
get
{
return m_SoundAgentHelper.Mute;
}
}
/// <summary>
/// 获取或设置在声音组内是否静音。
/// </summary>
public bool MuteInSoundGroup
{
get
{
return m_MuteInSoundGroup;
}
set
{
m_MuteInSoundGroup = value;
RefreshMute();
}
}
/// <summary>
/// 获取或设置是否循环播放。
/// </summary>
public bool Loop
{
get
{
return m_SoundAgentHelper.Loop;
}
set
{
m_SoundAgentHelper.Loop = value;
}
}
/// <summary>
/// 获取或设置声音优先级。
/// </summary>
public int Priority
{
get
{
return m_SoundAgentHelper.Priority;
}
set
{
m_SoundAgentHelper.Priority = value;
}
}
/// <summary>
/// 获取音量大小。
/// </summary>
public float Volume
{
get
{
return m_SoundAgentHelper.Volume;
}
}
/// <summary>
/// 获取或设置在声音组内音量大小。
/// </summary>
public float VolumeInSoundGroup
{
get
{
return m_VolumeInSoundGroup;
}
set
{
m_VolumeInSoundGroup = value;
RefreshVolume();
}
}
/// <summary>
/// 获取或设置声音音调。
/// </summary>
public float Pitch
{
get
{
return m_SoundAgentHelper.Pitch;
}
set
{
m_SoundAgentHelper.Pitch = value;
}
}
/// <summary>
/// 获取或设置声音立体声声相。
/// </summary>
public float PanStereo
{
get
{
return m_SoundAgentHelper.PanStereo;
}
set
{
m_SoundAgentHelper.PanStereo = value;
}
}
/// <summary>
/// 获取或设置声音空间混合量。
/// </summary>
public float SpatialBlend
{
get
{
return m_SoundAgentHelper.SpatialBlend;
}
set
{
m_SoundAgentHelper.SpatialBlend = value;
}
}
/// <summary>
/// 获取或设置声音最大距离。
/// </summary>
public float MaxDistance
{
get
{
return m_SoundAgentHelper.MaxDistance;
}
set
{
m_SoundAgentHelper.MaxDistance = value;
}
}
/// <summary>
/// 获取或设置声音多普勒等级。
/// </summary>
public float DopplerLevel
{
get
{
return m_SoundAgentHelper.DopplerLevel;
}
set
{
m_SoundAgentHelper.DopplerLevel = value;
}
}
/// <summary>
/// 获取声音代理辅助器。
/// </summary>
public ISoundAgentHelper Helper
{
get
{
return m_SoundAgentHelper;
}
}
/// <summary>
/// 获取声音创建时间。
/// </summary>
internal DateTime SetSoundAssetTime
{
get
{
return m_SetSoundAssetTime;
}
}
/// <summary>
/// 播放声音。
/// </summary>
public void Play()
{
m_SoundAgentHelper.Play(Constant.DefaultFadeInSeconds);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public void Play(float fadeInSeconds)
{
m_SoundAgentHelper.Play(fadeInSeconds);
}
/// <summary>
/// 停止播放声音。
/// </summary>
public void Stop()
{
m_SoundAgentHelper.Stop(Constant.DefaultFadeOutSeconds);
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void Stop(float fadeOutSeconds)
{
m_SoundAgentHelper.Stop(fadeOutSeconds);
}
/// <summary>
/// 暂停播放声音。
/// </summary>
public void Pause()
{
m_SoundAgentHelper.Pause(Constant.DefaultFadeOutSeconds);
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void Pause(float fadeOutSeconds)
{
m_SoundAgentHelper.Pause(fadeOutSeconds);
}
/// <summary>
/// 恢复播放声音。
/// </summary>
public void Resume()
{
m_SoundAgentHelper.Resume(Constant.DefaultFadeInSeconds);
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public void Resume(float fadeInSeconds)
{
m_SoundAgentHelper.Resume(fadeInSeconds);
}
/// <summary>
/// 重置声音代理。
/// </summary>
public void Reset()
{
if (m_SoundAsset != null)
{
m_SoundHelper.ReleaseSoundAsset(m_SoundAsset);
m_SoundAsset = null;
}
m_SetSoundAssetTime = DateTime.MinValue;
Time = Constant.DefaultTime;
MuteInSoundGroup = Constant.DefaultMute;
Loop = Constant.DefaultLoop;
Priority = Constant.DefaultPriority;
VolumeInSoundGroup = Constant.DefaultVolume;
Pitch = Constant.DefaultPitch;
PanStereo = Constant.DefaultPanStereo;
SpatialBlend = Constant.DefaultSpatialBlend;
MaxDistance = Constant.DefaultMaxDistance;
DopplerLevel = Constant.DefaultDopplerLevel;
m_SoundAgentHelper.Reset();
}
internal bool SetSoundAsset(object soundAsset)
{
Reset();
m_SoundAsset = soundAsset;
m_SetSoundAssetTime = DateTime.UtcNow;
return m_SoundAgentHelper.SetSoundAsset(soundAsset);
}
internal void RefreshMute()
{
m_SoundAgentHelper.Mute = m_SoundGroup.Mute || m_MuteInSoundGroup;
}
internal void RefreshVolume()
{
m_SoundAgentHelper.Volume = m_SoundGroup.Volume * m_VolumeInSoundGroup;
}
private void OnResetSoundAgent(object sender, ResetSoundAgentEventArgs e)
{
Reset();
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: caeb1649935f4ea698ade255d768edff
timeCreated: 1712714824

View File

@ -0,0 +1,303 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System.Collections.Generic;
namespace GameFrameX.Sound
{
public sealed partial class SoundManager : GameFrameworkModule, ISoundManager
{
/// <summary>
/// 声音组。
/// </summary>
private sealed class SoundGroup : ISoundGroup
{
private readonly string m_Name;
private readonly ISoundGroupHelper m_SoundGroupHelper;
private readonly List<SoundAgent> m_SoundAgents;
private bool m_AvoidBeingReplacedBySamePriority;
private bool m_Mute;
private float m_Volume;
/// <summary>
/// 初始化声音组的新实例。
/// </summary>
/// <param name="name">声音组名称。</param>
/// <param name="soundGroupHelper">声音组辅助器。</param>
public SoundGroup(string name, ISoundGroupHelper soundGroupHelper)
{
if (string.IsNullOrEmpty(name))
{
throw new GameFrameworkException("Sound group name is invalid.");
}
if (soundGroupHelper == null)
{
throw new GameFrameworkException("Sound group helper is invalid.");
}
m_Name = name;
m_SoundGroupHelper = soundGroupHelper;
m_SoundAgents = new List<SoundAgent>();
}
/// <summary>
/// 获取声音组名称。
/// </summary>
public string Name
{
get
{
return m_Name;
}
}
/// <summary>
/// 获取声音代理数。
/// </summary>
public int SoundAgentCount
{
get
{
return m_SoundAgents.Count;
}
}
/// <summary>
/// 获取或设置声音组中的声音是否避免被同优先级声音替换。
/// </summary>
public bool AvoidBeingReplacedBySamePriority
{
get
{
return m_AvoidBeingReplacedBySamePriority;
}
set
{
m_AvoidBeingReplacedBySamePriority = value;
}
}
/// <summary>
/// 获取或设置声音组静音。
/// </summary>
public bool Mute
{
get
{
return m_Mute;
}
set
{
m_Mute = value;
foreach (SoundAgent soundAgent in m_SoundAgents)
{
soundAgent.RefreshMute();
}
}
}
/// <summary>
/// 获取或设置声音组音量。
/// </summary>
public float Volume
{
get
{
return m_Volume;
}
set
{
m_Volume = value;
foreach (SoundAgent soundAgent in m_SoundAgents)
{
soundAgent.RefreshVolume();
}
}
}
/// <summary>
/// 获取声音组辅助器。
/// </summary>
public ISoundGroupHelper Helper
{
get
{
return m_SoundGroupHelper;
}
}
/// <summary>
/// 增加声音代理辅助器。
/// </summary>
/// <param name="soundHelper">声音辅助器接口。</param>
/// <param name="soundAgentHelper">要增加的声音代理辅助器。</param>
public void AddSoundAgentHelper(ISoundHelper soundHelper, ISoundAgentHelper soundAgentHelper)
{
m_SoundAgents.Add(new SoundAgent(this, soundHelper, soundAgentHelper));
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="serialId">声音的序列编号。</param>
/// <param name="soundAsset">声音资源。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="errorCode">错误码。</param>
/// <returns>用于播放的声音代理。</returns>
public ISoundAgent PlaySound(int serialId, object soundAsset, PlaySoundParams playSoundParams, out PlaySoundErrorCode? errorCode)
{
errorCode = null;
SoundAgent candidateAgent = null;
foreach (SoundAgent soundAgent in m_SoundAgents)
{
if (!soundAgent.IsPlaying)
{
candidateAgent = soundAgent;
break;
}
if (soundAgent.Priority < playSoundParams.Priority)
{
if (candidateAgent == null || soundAgent.Priority < candidateAgent.Priority)
{
candidateAgent = soundAgent;
}
}
else if (!m_AvoidBeingReplacedBySamePriority && soundAgent.Priority == playSoundParams.Priority)
{
if (candidateAgent == null || soundAgent.SetSoundAssetTime < candidateAgent.SetSoundAssetTime)
{
candidateAgent = soundAgent;
}
}
}
if (candidateAgent == null)
{
errorCode = PlaySoundErrorCode.IgnoredDueToLowPriority;
return null;
}
if (!candidateAgent.SetSoundAsset(soundAsset))
{
errorCode = PlaySoundErrorCode.SetSoundAssetFailure;
return null;
}
candidateAgent.SerialId = serialId;
candidateAgent.Time = playSoundParams.Time;
candidateAgent.MuteInSoundGroup = playSoundParams.MuteInSoundGroup;
candidateAgent.Loop = playSoundParams.Loop;
candidateAgent.Priority = playSoundParams.Priority;
candidateAgent.VolumeInSoundGroup = playSoundParams.VolumeInSoundGroup;
candidateAgent.Pitch = playSoundParams.Pitch;
candidateAgent.PanStereo = playSoundParams.PanStereo;
candidateAgent.SpatialBlend = playSoundParams.SpatialBlend;
candidateAgent.MaxDistance = playSoundParams.MaxDistance;
candidateAgent.DopplerLevel = playSoundParams.DopplerLevel;
candidateAgent.Play(playSoundParams.FadeInSeconds);
return candidateAgent;
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
/// <returns>是否停止播放声音成功。</returns>
public bool StopSound(int serialId, float fadeOutSeconds)
{
foreach (SoundAgent soundAgent in m_SoundAgents)
{
if (soundAgent.SerialId != serialId)
{
continue;
}
soundAgent.Stop(fadeOutSeconds);
return true;
}
return false;
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
/// <returns>是否暂停播放声音成功。</returns>
public bool PauseSound(int serialId, float fadeOutSeconds)
{
foreach (SoundAgent soundAgent in m_SoundAgents)
{
if (soundAgent.SerialId != serialId)
{
continue;
}
soundAgent.Pause(fadeOutSeconds);
return true;
}
return false;
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
/// <returns>是否恢复播放声音成功。</returns>
public bool ResumeSound(int serialId, float fadeInSeconds)
{
foreach (SoundAgent soundAgent in m_SoundAgents)
{
if (soundAgent.SerialId != serialId)
{
continue;
}
soundAgent.Resume(fadeInSeconds);
return true;
}
return false;
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
public void StopAllLoadedSounds()
{
foreach (SoundAgent soundAgent in m_SoundAgents)
{
if (soundAgent.IsPlaying)
{
soundAgent.Stop();
}
}
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void StopAllLoadedSounds(float fadeOutSeconds)
{
foreach (SoundAgent soundAgent in m_SoundAgents)
{
if (soundAgent.IsPlaying)
{
soundAgent.Stop(fadeOutSeconds);
}
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 679fe9ecef42466db627c0f7a9d18ec4
timeCreated: 1712714824

View File

@ -0,0 +1,713 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using GameFrameX.Asset;
using UnityEngine;
namespace GameFrameX.Sound
{
/// <summary>
/// 声音管理器。
/// </summary>
public sealed partial class SoundManager : GameFrameworkModule, ISoundManager
{
private readonly Dictionary<string, SoundGroup> m_SoundGroups;
private readonly List<int> m_SoundsBeingLoaded;
private readonly HashSet<int> m_SoundsToReleaseOnLoad;
// private readonly LoadAssetCallbacks m_LoadAssetCallbacks;
private IAssetManager _assetManager;
private ISoundHelper m_SoundHelper;
private int m_Serial;
private EventHandler<PlaySoundSuccessEventArgs> m_PlaySoundSuccessEventHandler;
private EventHandler<PlaySoundFailureEventArgs> m_PlaySoundFailureEventHandler;
// private EventHandler<PlaySoundUpdateEventArgs> m_PlaySoundUpdateEventHandler;
/// <summary>
/// 初始化声音管理器的新实例。
/// </summary>
public SoundManager()
{
m_SoundGroups = new Dictionary<string, SoundGroup>(StringComparer.Ordinal);
m_SoundsBeingLoaded = new List<int>();
m_SoundsToReleaseOnLoad = new HashSet<int>();
// m_LoadAssetCallbacks = new LoadAssetCallbacks(LoadAssetSuccessCallback, LoadAssetFailureCallback, LoadAssetUpdateCallback);
_assetManager = null;
m_SoundHelper = null;
m_Serial = 0;
m_PlaySoundSuccessEventHandler = null;
m_PlaySoundFailureEventHandler = null;
// m_PlaySoundUpdateEventHandler = null;
}
/// <summary>
/// 获取声音组数量。
/// </summary>
public int SoundGroupCount
{
get { return m_SoundGroups.Count; }
}
/// <summary>
/// 播放声音成功事件。
/// </summary>
public event EventHandler<PlaySoundSuccessEventArgs> PlaySoundSuccess
{
add { m_PlaySoundSuccessEventHandler += value; }
remove { m_PlaySoundSuccessEventHandler -= value; }
}
/// <summary>
/// 播放声音失败事件。
/// </summary>
public event EventHandler<PlaySoundFailureEventArgs> PlaySoundFailure
{
add { m_PlaySoundFailureEventHandler += value; }
remove { m_PlaySoundFailureEventHandler -= value; }
}
/*/// <summary>
/// 播放声音更新事件。
/// </summary>
public event EventHandler<PlaySoundUpdateEventArgs> PlaySoundUpdate
{
add { m_PlaySoundUpdateEventHandler += value; }
remove { m_PlaySoundUpdateEventHandler -= value; }
}*/
/// <summary>
/// 声音管理器轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
protected internal override void Update(float elapseSeconds, float realElapseSeconds)
{
}
/// <summary>
/// 关闭并清理声音管理器。
/// </summary>
protected internal override void Shutdown()
{
StopAllLoadedSounds();
m_SoundGroups.Clear();
m_SoundsBeingLoaded.Clear();
m_SoundsToReleaseOnLoad.Clear();
}
/// <summary>
/// 设置资源管理器。
/// </summary>
/// <param name="assetManager">资源管理器。</param>
public void SetResourceManager(IAssetManager assetManager)
{
if (assetManager == null)
{
throw new GameFrameworkException("Resource manager is invalid.");
}
_assetManager = assetManager;
}
/// <summary>
/// 设置声音辅助器。
/// </summary>
/// <param name="soundHelper">声音辅助器。</param>
public void SetSoundHelper(ISoundHelper soundHelper)
{
if (soundHelper == null)
{
throw new GameFrameworkException("Sound helper is invalid.");
}
m_SoundHelper = soundHelper;
}
/// <summary>
/// 是否存在指定声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>指定声音组是否存在。</returns>
public bool HasSoundGroup(string soundGroupName)
{
if (string.IsNullOrEmpty(soundGroupName))
{
throw new GameFrameworkException("Sound group name is invalid.");
}
return m_SoundGroups.ContainsKey(soundGroupName);
}
/// <summary>
/// 获取指定声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>要获取的声音组。</returns>
public ISoundGroup GetSoundGroup(string soundGroupName)
{
if (string.IsNullOrEmpty(soundGroupName))
{
throw new GameFrameworkException("Sound group name is invalid.");
}
if (m_SoundGroups.TryGetValue(soundGroupName, out var soundGroup))
{
return soundGroup;
}
return null;
}
/// <summary>
/// 获取所有声音组。
/// </summary>
/// <returns>所有声音组。</returns>
public ISoundGroup[] GetAllSoundGroups()
{
int index = 0;
ISoundGroup[] results = new ISoundGroup[m_SoundGroups.Count];
foreach (KeyValuePair<string, SoundGroup> soundGroup in m_SoundGroups)
{
results[index++] = soundGroup.Value;
}
return results;
}
/// <summary>
/// 获取所有声音组。
/// </summary>
/// <param name="results">所有声音组。</param>
public void GetAllSoundGroups(List<ISoundGroup> results)
{
if (results == null)
{
throw new GameFrameworkException("Results is invalid.");
}
results.Clear();
foreach (KeyValuePair<string, SoundGroup> soundGroup in m_SoundGroups)
{
results.Add(soundGroup.Value);
}
}
/// <summary>
/// 增加声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundGroupHelper">声音组辅助器。</param>
/// <returns>是否增加声音组成功。</returns>
public bool AddSoundGroup(string soundGroupName, ISoundGroupHelper soundGroupHelper)
{
return AddSoundGroup(soundGroupName, false, Constant.DefaultMute, Constant.DefaultVolume, soundGroupHelper);
}
/// <summary>
/// 增加声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundGroupAvoidBeingReplacedBySamePriority">声音组中的声音是否避免被同优先级声音替换。</param>
/// <param name="soundGroupMute">声音组是否静音。</param>
/// <param name="soundGroupVolume">声音组音量。</param>
/// <param name="soundGroupHelper">声音组辅助器。</param>
/// <returns>是否增加声音组成功。</returns>
public bool AddSoundGroup(string soundGroupName, bool soundGroupAvoidBeingReplacedBySamePriority, bool soundGroupMute, float soundGroupVolume, ISoundGroupHelper soundGroupHelper)
{
if (string.IsNullOrEmpty(soundGroupName))
{
throw new GameFrameworkException("Sound group name is invalid.");
}
if (soundGroupHelper == null)
{
throw new GameFrameworkException("Sound group helper is invalid.");
}
if (HasSoundGroup(soundGroupName))
{
return false;
}
SoundGroup soundGroup = new SoundGroup(soundGroupName, soundGroupHelper)
{
AvoidBeingReplacedBySamePriority = soundGroupAvoidBeingReplacedBySamePriority,
Mute = soundGroupMute,
Volume = soundGroupVolume
};
m_SoundGroups.Add(soundGroupName, soundGroup);
return true;
}
/// <summary>
/// 增加声音代理辅助器。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundAgentHelper">要增加的声音代理辅助器。</param>
public void AddSoundAgentHelper(string soundGroupName, ISoundAgentHelper soundAgentHelper)
{
if (m_SoundHelper == null)
{
throw new GameFrameworkException("You must set sound helper first.");
}
SoundGroup soundGroup = (SoundGroup)GetSoundGroup(soundGroupName);
if (soundGroup == null)
{
throw new GameFrameworkException(Utility.Text.Format("Sound group '{0}' is not exist.", soundGroupName));
}
soundGroup.AddSoundAgentHelper(m_SoundHelper, soundAgentHelper);
}
/// <summary>
/// 获取所有正在加载声音的序列编号。
/// </summary>
/// <returns>所有正在加载声音的序列编号。</returns>
public int[] GetAllLoadingSoundSerialIds()
{
return m_SoundsBeingLoaded.ToArray();
}
/// <summary>
/// 获取所有正在加载声音的序列编号。
/// </summary>
/// <param name="results">所有正在加载声音的序列编号。</param>
public void GetAllLoadingSoundSerialIds(List<int> results)
{
if (results == null)
{
throw new GameFrameworkException("Results is invalid.");
}
results.Clear();
results.AddRange(m_SoundsBeingLoaded);
}
/// <summary>
/// 是否正在加载声音。
/// </summary>
/// <param name="serialId">声音序列编号。</param>
/// <returns>是否正在加载声音。</returns>
public bool IsLoadingSound(int serialId)
{
return m_SoundsBeingLoaded.Contains(serialId);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>声音的序列编号。</returns>
public Task<int> PlaySound(string soundAssetName, string soundGroupName)
{
return PlaySound(soundAssetName, soundGroupName, Asset.Constant.DefaultPriority, null, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <returns>声音的序列编号。</returns>
public Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority)
{
return PlaySound(soundAssetName, soundGroupName, priority, null, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <returns>声音的序列编号。</returns>
public Task<int> PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams)
{
return PlaySound(soundAssetName, soundGroupName, Asset.Constant.DefaultPriority, playSoundParams, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public Task<int> PlaySound(string soundAssetName, string soundGroupName, object userData)
{
return PlaySound(soundAssetName, soundGroupName, Asset.Constant.DefaultPriority, null, userData);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <returns>声音的序列编号。</returns>
public Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams)
{
return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority, object userData)
{
return PlaySound(soundAssetName, soundGroupName, priority, null, userData);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public async Task<int> PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, object userData)
{
return await PlaySound(soundAssetName, soundGroupName, Asset.Constant.DefaultPriority, playSoundParams, userData);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public async Task<int> PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, object userData)
{
if (_assetManager == null)
{
throw new GameFrameworkException("You must set resource manager first.");
}
if (m_SoundHelper == null)
{
throw new GameFrameworkException("You must set sound helper first.");
}
if (playSoundParams == null)
{
playSoundParams = PlaySoundParams.Create();
}
int serialId = ++m_Serial;
PlaySoundErrorCode? errorCode = null;
string errorMessage = null;
SoundGroup soundGroup = (SoundGroup)GetSoundGroup(soundGroupName);
if (soundGroup == null)
{
errorCode = PlaySoundErrorCode.SoundGroupNotExist;
errorMessage = Utility.Text.Format("Sound group '{0}' is not exist.", soundGroupName);
}
else if (soundGroup.SoundAgentCount <= 0)
{
errorCode = PlaySoundErrorCode.SoundGroupHasNoAgent;
errorMessage = Utility.Text.Format("Sound group '{0}' is have no sound agent.", soundGroupName);
}
if (errorCode.HasValue)
{
if (m_PlaySoundFailureEventHandler != null)
{
PlaySoundFailureEventArgs playSoundFailureEventArgs =
PlaySoundFailureEventArgs.Create(serialId, soundAssetName, soundGroupName, playSoundParams, errorCode.Value, errorMessage, userData);
m_PlaySoundFailureEventHandler(this, playSoundFailureEventArgs);
ReferencePool.Release(playSoundFailureEventArgs);
if (playSoundParams.Referenced)
{
ReferencePool.Release(playSoundParams);
}
return serialId;
}
throw new GameFrameworkException(errorMessage);
}
m_SoundsBeingLoaded.Add(serialId);
var assetOperationHandle = await _assetManager.LoadAssetAsync(soundAssetName, typeof(AudioClip));
assetOperationHandle.Completed += (aoh) =>
{
LoadAssetSuccessCallback(soundAssetName, aoh.GetAssetObject<AudioClip>(), aoh.GetAssetObject<AudioClip>().length,
PlaySoundInfo.Create(serialId, soundGroup, playSoundParams, userData));
};
return serialId;
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <returns>是否停止播放声音成功。</returns>
public bool StopSound(int serialId)
{
return StopSound(serialId, Constant.DefaultFadeOutSeconds);
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
/// <returns>是否停止播放声音成功。</returns>
public bool StopSound(int serialId, float fadeOutSeconds)
{
if (IsLoadingSound(serialId))
{
m_SoundsToReleaseOnLoad.Add(serialId);
m_SoundsBeingLoaded.Remove(serialId);
return true;
}
foreach (KeyValuePair<string, SoundGroup> soundGroup in m_SoundGroups)
{
if (soundGroup.Value.StopSound(serialId, fadeOutSeconds))
{
return true;
}
}
return false;
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
public void StopAllLoadedSounds()
{
StopAllLoadedSounds(Constant.DefaultFadeOutSeconds);
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void StopAllLoadedSounds(float fadeOutSeconds)
{
foreach (KeyValuePair<string, SoundGroup> soundGroup in m_SoundGroups)
{
soundGroup.Value.StopAllLoadedSounds(fadeOutSeconds);
}
}
/// <summary>
/// 停止所有正在加载的声音。
/// </summary>
public void StopAllLoadingSounds()
{
foreach (int serialId in m_SoundsBeingLoaded)
{
m_SoundsToReleaseOnLoad.Add(serialId);
}
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
public void PauseSound(int serialId)
{
PauseSound(serialId, Constant.DefaultFadeOutSeconds);
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void PauseSound(int serialId, float fadeOutSeconds)
{
foreach (KeyValuePair<string, SoundGroup> soundGroup in m_SoundGroups)
{
if (soundGroup.Value.PauseSound(serialId, fadeOutSeconds))
{
return;
}
}
throw new GameFrameworkException(Utility.Text.Format("Can not find sound '{0}'.", serialId));
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
public void ResumeSound(int serialId)
{
ResumeSound(serialId, Constant.DefaultFadeInSeconds);
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public void ResumeSound(int serialId, float fadeInSeconds)
{
foreach (KeyValuePair<string, SoundGroup> soundGroup in m_SoundGroups)
{
if (soundGroup.Value.ResumeSound(serialId, fadeInSeconds))
{
return;
}
}
throw new GameFrameworkException(Utility.Text.Format("Can not find sound '{0}'.", serialId));
}
private void LoadAssetSuccessCallback(string soundAssetName, object soundAsset, float duration, object userData)
{
PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData;
if (playSoundInfo == null)
{
throw new GameFrameworkException("Play sound info is invalid.");
}
if (m_SoundsToReleaseOnLoad.Contains(playSoundInfo.SerialId))
{
m_SoundsToReleaseOnLoad.Remove(playSoundInfo.SerialId);
if (playSoundInfo.PlaySoundParams.Referenced)
{
ReferencePool.Release(playSoundInfo.PlaySoundParams);
}
ReferencePool.Release(playSoundInfo);
m_SoundHelper.ReleaseSoundAsset(soundAsset);
return;
}
m_SoundsBeingLoaded.Remove(playSoundInfo.SerialId);
ISoundAgent soundAgent = playSoundInfo.SoundGroup.PlaySound(playSoundInfo.SerialId, soundAsset, playSoundInfo.PlaySoundParams, out var errorCode);
if (soundAgent != null)
{
if (m_PlaySoundSuccessEventHandler != null)
{
PlaySoundSuccessEventArgs playSoundSuccessEventArgs = PlaySoundSuccessEventArgs.Create(playSoundInfo.SerialId, soundAssetName, soundAgent, duration, playSoundInfo.UserData);
m_PlaySoundSuccessEventHandler(this, playSoundSuccessEventArgs);
ReferencePool.Release(playSoundSuccessEventArgs);
}
if (playSoundInfo.PlaySoundParams.Referenced)
{
ReferencePool.Release(playSoundInfo.PlaySoundParams);
}
ReferencePool.Release(playSoundInfo);
return;
}
m_SoundsToReleaseOnLoad.Remove(playSoundInfo.SerialId);
m_SoundHelper.ReleaseSoundAsset(soundAsset);
string errorMessage = Utility.Text.Format("Sound group '{0}' play sound '{1}' failure.", playSoundInfo.SoundGroup.Name, soundAssetName);
if (m_PlaySoundFailureEventHandler != null)
{
PlaySoundFailureEventArgs playSoundFailureEventArgs = PlaySoundFailureEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name,
playSoundInfo.PlaySoundParams, errorCode.Value, errorMessage, playSoundInfo.UserData);
m_PlaySoundFailureEventHandler(this, playSoundFailureEventArgs);
ReferencePool.Release(playSoundFailureEventArgs);
if (playSoundInfo.PlaySoundParams.Referenced)
{
ReferencePool.Release(playSoundInfo.PlaySoundParams);
}
ReferencePool.Release(playSoundInfo);
return;
}
if (playSoundInfo.PlaySoundParams.Referenced)
{
ReferencePool.Release(playSoundInfo.PlaySoundParams);
}
ReferencePool.Release(playSoundInfo);
throw new GameFrameworkException(errorMessage);
}
/*
private void LoadAssetFailureCallback(string soundAssetName, LoadResourceStatus status, string errorMessage, object userData)
{
PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData;
if (playSoundInfo == null)
{
throw new GameFrameworkException("Play sound info is invalid.");
}
if (m_SoundsToReleaseOnLoad.Contains(playSoundInfo.SerialId))
{
m_SoundsToReleaseOnLoad.Remove(playSoundInfo.SerialId);
if (playSoundInfo.PlaySoundParams.Referenced)
{
ReferencePool.Release(playSoundInfo.PlaySoundParams);
}
return;
}
m_SoundsBeingLoaded.Remove(playSoundInfo.SerialId);
string appendErrorMessage = Utility.Text.Format("Load sound failure, asset name '{0}', status '{1}', error message '{2}'.", soundAssetName, status, errorMessage);
if (m_PlaySoundFailureEventHandler != null)
{
PlaySoundFailureEventArgs playSoundFailureEventArgs = PlaySoundFailureEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name,
playSoundInfo.PlaySoundParams, PlaySoundErrorCode.LoadAssetFailure, appendErrorMessage, playSoundInfo.UserData);
m_PlaySoundFailureEventHandler(this, playSoundFailureEventArgs);
ReferencePool.Release(playSoundFailureEventArgs);
if (playSoundInfo.PlaySoundParams.Referenced)
{
ReferencePool.Release(playSoundInfo.PlaySoundParams);
}
return;
}
throw new GameFrameworkException(appendErrorMessage);
}*/
/*
private void LoadAssetUpdateCallback(string soundAssetName, float progress, object userData)
{
PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData;
if (playSoundInfo == null)
{
throw new GameFrameworkException("Play sound info is invalid.");
}
if (m_PlaySoundUpdateEventHandler != null)
{
PlaySoundUpdateEventArgs playSoundUpdateEventArgs = PlaySoundUpdateEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name,
playSoundInfo.PlaySoundParams, progress, playSoundInfo.UserData);
m_PlaySoundUpdateEventHandler(this, playSoundUpdateEventArgs);
ReferencePool.Release(playSoundUpdateEventArgs);
}
}*/
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6b0c9e95f8a54e5cb4597043d0948237
timeCreated: 1712714824

View File

@ -0,0 +1,188 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Sound;
using System;
using UnityEngine;
using UnityEngine.Audio;
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 声音代理辅助器基类。
/// </summary>
public abstract class SoundAgentHelperBase : MonoBehaviour, ISoundAgentHelper
{
/// <summary>
/// 获取当前是否正在播放。
/// </summary>
public abstract bool IsPlaying
{
get;
}
/// <summary>
/// 获取声音长度。
/// </summary>
public abstract float Length
{
get;
}
/// <summary>
/// 获取或设置播放位置。
/// </summary>
public abstract float Time
{
get;
set;
}
/// <summary>
/// 获取或设置是否静音。
/// </summary>
public abstract bool Mute
{
get;
set;
}
/// <summary>
/// 获取或设置是否循环播放。
/// </summary>
public abstract bool Loop
{
get;
set;
}
/// <summary>
/// 获取或设置声音优先级。
/// </summary>
public abstract int Priority
{
get;
set;
}
/// <summary>
/// 获取或设置音量大小。
/// </summary>
public abstract float Volume
{
get;
set;
}
/// <summary>
/// 获取或设置声音音调。
/// </summary>
public abstract float Pitch
{
get;
set;
}
/// <summary>
/// 获取或设置声音立体声声相。
/// </summary>
public abstract float PanStereo
{
get;
set;
}
/// <summary>
/// 获取或设置声音空间混合量。
/// </summary>
public abstract float SpatialBlend
{
get;
set;
}
/// <summary>
/// 获取或设置声音最大距离。
/// </summary>
public abstract float MaxDistance
{
get;
set;
}
/// <summary>
/// 获取或设置声音多普勒等级。
/// </summary>
public abstract float DopplerLevel
{
get;
set;
}
/// <summary>
/// 获取或设置声音代理辅助器所在的混音组。
/// </summary>
public abstract AudioMixerGroup AudioMixerGroup
{
get;
set;
}
/// <summary>
/// 重置声音代理事件。
/// </summary>
public abstract event EventHandler<ResetSoundAgentEventArgs> ResetSoundAgent;
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public abstract void Play(float fadeInSeconds);
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public abstract void Stop(float fadeOutSeconds);
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public abstract void Pause(float fadeOutSeconds);
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public abstract void Resume(float fadeInSeconds);
/// <summary>
/// 重置声音代理辅助器。
/// </summary>
public abstract void Reset();
/// <summary>
/// 设置声音资源。
/// </summary>
/// <param name="soundAsset">声音资源。</param>
/// <returns>是否设置声音资源成功。</returns>
public abstract bool SetSoundAsset(object soundAsset);
/// <summary>
/// 设置声音绑定的实体。
/// </summary>
/// <param name="bindingEntity">声音绑定的实体。</param>
public abstract void SetBindingEntity(Entity bindingEntity);
/// <summary>
/// 设置声音所在的世界坐标。
/// </summary>
/// <param name="worldPosition">声音所在的世界坐标。</param>
public abstract void SetWorldPosition(Vector3 worldPosition);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d66e8f17431b4afab73dc9ccabff39ab
timeCreated: 1712714824

View File

@ -0,0 +1,75 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using GameFrameX.Runtime;
using UnityEngine;
namespace GameFrameX.Sound.Runtime
{
public sealed partial class SoundComponent : GameFrameworkComponent
{
[Serializable]
private sealed class SoundGroup
{
[SerializeField]
private string m_Name = null;
[SerializeField]
private bool m_AvoidBeingReplacedBySamePriority = false;
[SerializeField]
private bool m_Mute = false;
[SerializeField, Range(0f, 1f)]
private float m_Volume = 1f;
[SerializeField]
private int m_AgentHelperCount = 1;
public string Name
{
get
{
return m_Name;
}
}
public bool AvoidBeingReplacedBySamePriority
{
get
{
return m_AvoidBeingReplacedBySamePriority;
}
}
public bool Mute
{
get
{
return m_Mute;
}
}
public float Volume
{
get
{
return m_Volume;
}
}
public int AgentHelperCount
{
get
{
return m_AgentHelperCount;
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b7aeedb3e63942e2a4237ef556bd8d14
timeCreated: 1712714824

View File

@ -0,0 +1,677 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
#if UNITY_5_3
using GameFramework.Scene;
#endif
using GameFrameX.Sound;
using System.Collections.Generic;
using GameFrameX.Asset;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 声音组件。
/// </summary>
[DisallowMultipleComponent]
[AddComponentMenu("Game Framework/Sound")]
public sealed partial class SoundComponent : GameFrameworkComponent
{
private const int DefaultPriority = 0;
private ISoundManager m_SoundManager = null;
private EventComponent m_EventComponent = null;
private AudioListener m_AudioListener = null;
// [SerializeField] private bool m_EnablePlaySoundUpdateEvent = false;
[SerializeField] private Transform m_InstanceRoot = null;
[SerializeField] private AudioMixer m_AudioMixer = null;
[SerializeField] private string m_SoundHelperTypeName = "UnityGameFramework.Runtime.DefaultSoundHelper";
[SerializeField] private SoundHelperBase m_CustomSoundHelper = null;
[SerializeField] private string m_SoundGroupHelperTypeName = "UnityGameFramework.Runtime.DefaultSoundGroupHelper";
[SerializeField] private SoundGroupHelperBase m_CustomSoundGroupHelper = null;
[SerializeField] private string m_SoundAgentHelperTypeName = "UnityGameFramework.Runtime.DefaultSoundAgentHelper";
[SerializeField] private SoundAgentHelperBase m_CustomSoundAgentHelper = null;
[SerializeField] private SoundGroup[] m_SoundGroups = null;
/// <summary>
/// 获取声音组数量。
/// </summary>
public int SoundGroupCount
{
get { return m_SoundManager.SoundGroupCount; }
}
/// <summary>
/// 获取声音混响器。
/// </summary>
public AudioMixer AudioMixer
{
get { return m_AudioMixer; }
}
/// <summary>
/// 游戏框架组件初始化。
/// </summary>
protected override void Awake()
{
base.Awake();
new SoundManager();
m_SoundManager = GameFrameworkEntry.GetModule<ISoundManager>();
if (m_SoundManager == null)
{
Log.Fatal("Sound manager is invalid.");
return;
}
m_SoundManager.PlaySoundSuccess += OnPlaySoundSuccess;
m_SoundManager.PlaySoundFailure += OnPlaySoundFailure;
// if (m_EnablePlaySoundUpdateEvent)
// {
// m_SoundManager.PlaySoundUpdate += OnPlaySoundUpdate;
// }
m_AudioListener = gameObject.GetOrAddComponent<AudioListener>();
#if UNITY_5_4_OR_NEWER
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.sceneUnloaded += OnSceneUnloaded;
#else
ISceneManager sceneManager = GameFrameworkEntry.GetModule<ISceneManager>();
if (sceneManager == null)
{
Log.Fatal("Scene manager is invalid.");
return;
}
sceneManager.LoadSceneSuccess += OnLoadSceneSuccess;
sceneManager.LoadSceneFailure += OnLoadSceneFailure;
sceneManager.UnloadSceneSuccess += OnUnloadSceneSuccess;
sceneManager.UnloadSceneFailure += OnUnloadSceneFailure;
#endif
}
private void Start()
{
BaseComponent baseComponent = GameEntry.GetComponent<BaseComponent>();
if (baseComponent == null)
{
Log.Fatal("Base component is invalid.");
return;
}
m_EventComponent = GameEntry.GetComponent<EventComponent>();
if (m_EventComponent == null)
{
Log.Fatal("Event component is invalid.");
return;
}
{
m_SoundManager.SetResourceManager(GameFrameworkEntry.GetModule<IAssetManager>());
}
SoundHelperBase soundHelper = Helper.CreateHelper(m_SoundHelperTypeName, m_CustomSoundHelper);
if (soundHelper == null)
{
Log.Error("Can not create sound helper.");
return;
}
soundHelper.name = "Sound Helper";
Transform transform = soundHelper.transform;
transform.SetParent(this.transform);
transform.localScale = Vector3.one;
m_SoundManager.SetSoundHelper(soundHelper);
if (m_InstanceRoot == null)
{
m_InstanceRoot = new GameObject("Sound Instances").transform;
m_InstanceRoot.SetParent(gameObject.transform);
m_InstanceRoot.localScale = Vector3.one;
}
for (int i = 0; i < m_SoundGroups.Length; i++)
{
if (!AddSoundGroup(m_SoundGroups[i].Name, m_SoundGroups[i].AvoidBeingReplacedBySamePriority,
m_SoundGroups[i].Mute, m_SoundGroups[i].Volume, m_SoundGroups[i].AgentHelperCount))
{
Log.Warning("Add sound group '{0}' failure.", m_SoundGroups[i].Name);
continue;
}
}
}
private void OnDestroy()
{
#if UNITY_5_4_OR_NEWER
SceneManager.sceneLoaded -= OnSceneLoaded;
SceneManager.sceneUnloaded -= OnSceneUnloaded;
#endif
}
/// <summary>
/// 是否存在指定声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>指定声音组是否存在。</returns>
public bool HasSoundGroup(string soundGroupName)
{
return m_SoundManager.HasSoundGroup(soundGroupName);
}
/// <summary>
/// 获取指定声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>要获取的声音组。</returns>
public ISoundGroup GetSoundGroup(string soundGroupName)
{
return m_SoundManager.GetSoundGroup(soundGroupName);
}
/// <summary>
/// 获取所有声音组。
/// </summary>
/// <returns>所有声音组。</returns>
public ISoundGroup[] GetAllSoundGroups()
{
return m_SoundManager.GetAllSoundGroups();
}
/// <summary>
/// 获取所有声音组。
/// </summary>
/// <param name="results">所有声音组。</param>
public void GetAllSoundGroups(List<ISoundGroup> results)
{
m_SoundManager.GetAllSoundGroups(results);
}
/// <summary>
/// 增加声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundAgentHelperCount">声音代理辅助器数量。</param>
/// <returns>是否增加声音组成功。</returns>
public bool AddSoundGroup(string soundGroupName, int soundAgentHelperCount)
{
return AddSoundGroup(soundGroupName, false, false, 1f, soundAgentHelperCount);
}
/// <summary>
/// 增加声音组。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundGroupAvoidBeingReplacedBySamePriority">声音组中的声音是否避免被同优先级声音替换。</param>
/// <param name="soundGroupMute">声音组是否静音。</param>
/// <param name="soundGroupVolume">声音组音量。</param>
/// <param name="soundAgentHelperCount">声音代理辅助器数量。</param>
/// <returns>是否增加声音组成功。</returns>
public bool AddSoundGroup(string soundGroupName, bool soundGroupAvoidBeingReplacedBySamePriority,
bool soundGroupMute, float soundGroupVolume, int soundAgentHelperCount)
{
if (m_SoundManager.HasSoundGroup(soundGroupName))
{
return false;
}
SoundGroupHelperBase soundGroupHelper =
Helper.CreateHelper(m_SoundGroupHelperTypeName, m_CustomSoundGroupHelper, SoundGroupCount);
if (soundGroupHelper == null)
{
Log.Error("Can not create sound group helper.");
return false;
}
soundGroupHelper.name = Utility.Text.Format("Sound Group - {0}", soundGroupName);
Transform transform = soundGroupHelper.transform;
transform.SetParent(m_InstanceRoot);
transform.localScale = Vector3.one;
if (m_AudioMixer != null)
{
AudioMixerGroup[] audioMixerGroups =
m_AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}", soundGroupName));
if (audioMixerGroups.Length > 0)
{
soundGroupHelper.AudioMixerGroup = audioMixerGroups[0];
}
else
{
soundGroupHelper.AudioMixerGroup = m_AudioMixer.FindMatchingGroups("Master")[0];
}
}
if (!m_SoundManager.AddSoundGroup(soundGroupName, soundGroupAvoidBeingReplacedBySamePriority,
soundGroupMute, soundGroupVolume, soundGroupHelper))
{
return false;
}
for (int i = 0; i < soundAgentHelperCount; i++)
{
if (!AddSoundAgentHelper(soundGroupName, soundGroupHelper, i))
{
return false;
}
}
return true;
}
/// <summary>
/// 获取所有正在加载声音的序列编号。
/// </summary>
/// <returns>所有正在加载声音的序列编号。</returns>
public int[] GetAllLoadingSoundSerialIds()
{
return m_SoundManager.GetAllLoadingSoundSerialIds();
}
/// <summary>
/// 获取所有正在加载声音的序列编号。
/// </summary>
/// <param name="results">所有正在加载声音的序列编号。</param>
public void GetAllLoadingSoundSerialIds(List<int> results)
{
m_SoundManager.GetAllLoadingSoundSerialIds(results);
}
/// <summary>
/// 是否正在加载声音。
/// </summary>
/// <param name="serialId">声音序列编号。</param>
/// <returns>是否正在加载声音。</returns>
public bool IsLoadingSound(int serialId)
{
return m_SoundManager.IsLoadingSound(serialId);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName)
{
return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, null, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority)
{
return PlaySound(soundAssetName, soundGroupName, priority, null, null, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams)
{
return PlaySound(soundAssetName, soundGroupName, DefaultPriority, playSoundParams, null, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="bindingEntity">声音绑定的实体。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, Entity bindingEntity)
{
return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, bindingEntity, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="worldPosition">声音所在的世界坐标。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, Vector3 worldPosition)
{
return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, worldPosition, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, object userData)
{
return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, null, userData);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority,
PlaySoundParams playSoundParams)
{
return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, null, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority,
PlaySoundParams playSoundParams, object userData)
{
return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, null, userData);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="bindingEntity">声音绑定的实体。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority,
PlaySoundParams playSoundParams, Entity bindingEntity)
{
return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, bindingEntity, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="bindingEntity">声音绑定的实体。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority,
PlaySoundParams playSoundParams, Entity bindingEntity, object userData)
{
return m_SoundManager.PlaySound(soundAssetName, soundGroupName, priority, playSoundParams,
PlaySoundInfo.Create(bindingEntity, Vector3.zero, userData)).Result;
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="worldPosition">声音所在的世界坐标。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority,
PlaySoundParams playSoundParams, Vector3 worldPosition)
{
return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, worldPosition, null);
}
/// <summary>
/// 播放声音。
/// </summary>
/// <param name="soundAssetName">声音资源名称。</param>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="priority">加载声音资源的优先级。</param>
/// <param name="playSoundParams">播放声音参数。</param>
/// <param name="worldPosition">声音所在的世界坐标。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>声音的序列编号。</returns>
public int PlaySound(string soundAssetName, string soundGroupName, int priority,
PlaySoundParams playSoundParams, Vector3 worldPosition, object userData)
{
return m_SoundManager.PlaySound(soundAssetName, soundGroupName, priority, playSoundParams,
PlaySoundInfo.Create(null, worldPosition, userData)).Result;
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <returns>是否停止播放声音成功。</returns>
public bool StopSound(int serialId)
{
return m_SoundManager.StopSound(serialId);
}
/// <summary>
/// 停止播放声音。
/// </summary>
/// <param name="serialId">要停止播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
/// <returns>是否停止播放声音成功。</returns>
public bool StopSound(int serialId, float fadeOutSeconds)
{
return m_SoundManager.StopSound(serialId, fadeOutSeconds);
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
public void StopAllLoadedSounds()
{
m_SoundManager.StopAllLoadedSounds();
}
/// <summary>
/// 停止所有已加载的声音。
/// </summary>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void StopAllLoadedSounds(float fadeOutSeconds)
{
m_SoundManager.StopAllLoadedSounds(fadeOutSeconds);
}
/// <summary>
/// 停止所有正在加载的声音。
/// </summary>
public void StopAllLoadingSounds()
{
m_SoundManager.StopAllLoadingSounds();
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
public void PauseSound(int serialId)
{
m_SoundManager.PauseSound(serialId);
}
/// <summary>
/// 暂停播放声音。
/// </summary>
/// <param name="serialId">要暂停播放声音的序列编号。</param>
/// <param name="fadeOutSeconds">声音淡出时间,以秒为单位。</param>
public void PauseSound(int serialId, float fadeOutSeconds)
{
m_SoundManager.PauseSound(serialId, fadeOutSeconds);
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
public void ResumeSound(int serialId)
{
m_SoundManager.ResumeSound(serialId);
}
/// <summary>
/// 恢复播放声音。
/// </summary>
/// <param name="serialId">要恢复播放声音的序列编号。</param>
/// <param name="fadeInSeconds">声音淡入时间,以秒为单位。</param>
public void ResumeSound(int serialId, float fadeInSeconds)
{
m_SoundManager.ResumeSound(serialId, fadeInSeconds);
}
/// <summary>
/// 增加声音代理辅助器。
/// </summary>
/// <param name="soundGroupName">声音组名称。</param>
/// <param name="soundGroupHelper">声音组辅助器。</param>
/// <param name="index">声音代理辅助器索引。</param>
/// <returns>是否增加声音代理辅助器成功。</returns>
private bool AddSoundAgentHelper(string soundGroupName, SoundGroupHelperBase soundGroupHelper, int index)
{
SoundAgentHelperBase soundAgentHelper =
Helper.CreateHelper(m_SoundAgentHelperTypeName, m_CustomSoundAgentHelper, index);
if (soundAgentHelper == null)
{
Log.Error("Can not create sound agent helper.");
return false;
}
soundAgentHelper.name = Utility.Text.Format("Sound Agent Helper - {0} - {1}", soundGroupName, index);
Transform transform = soundAgentHelper.transform;
transform.SetParent(soundGroupHelper.transform);
transform.localScale = Vector3.one;
if (m_AudioMixer != null)
{
AudioMixerGroup[] audioMixerGroups =
m_AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", soundGroupName, index));
if (audioMixerGroups.Length > 0)
{
soundAgentHelper.AudioMixerGroup = audioMixerGroups[0];
}
else
{
soundAgentHelper.AudioMixerGroup = soundGroupHelper.AudioMixerGroup;
}
}
m_SoundManager.AddSoundAgentHelper(soundGroupName, soundAgentHelper);
return true;
}
private void OnPlaySoundSuccess(object sender, GameFrameX.Sound.PlaySoundSuccessEventArgs eventArgs)
{
PlaySoundInfo playSoundInfo = (PlaySoundInfo)eventArgs.UserData;
if (playSoundInfo != null)
{
SoundAgentHelperBase soundAgentHelper = (SoundAgentHelperBase)eventArgs.SoundAgent.Helper;
if (playSoundInfo.BindingEntity != null)
{
soundAgentHelper.SetBindingEntity(playSoundInfo.BindingEntity);
}
else
{
soundAgentHelper.SetWorldPosition(playSoundInfo.WorldPosition);
}
}
m_EventComponent.Fire(this, eventArgs);
}
private void OnPlaySoundFailure(object sender, GameFrameX.Sound.PlaySoundFailureEventArgs eventArgs)
{
string logMessage =
Utility.Text.Format(
"Play sound failure, asset name '{0}', sound group name '{1}', error code '{2}', error message '{3}'.",
eventArgs.SoundAssetName, eventArgs.SoundGroupName, eventArgs.ErrorCode, eventArgs.ErrorMessage);
if (eventArgs.ErrorCode == PlaySoundErrorCode.IgnoredDueToLowPriority)
{
Log.Info(logMessage);
}
else
{
Log.Warning(logMessage);
}
m_EventComponent.Fire(this, eventArgs);
}
private void OnPlaySoundUpdate(object sender, GameFrameX.Sound.PlaySoundUpdateEventArgs eventArgs)
{
m_EventComponent.Fire(this, eventArgs);
}
private void OnLoadSceneSuccess(object sender, GameFrameX.Scene.LoadSceneSuccessEventArgs e)
{
RefreshAudioListener();
}
private void OnLoadSceneFailure(object sender, GameFrameX.Scene.LoadSceneFailureEventArgs e)
{
RefreshAudioListener();
}
private void OnUnloadSceneSuccess(object sender, GameFrameX.Scene.UnloadSceneSuccessEventArgs e)
{
RefreshAudioListener();
}
private void OnUnloadSceneFailure(object sender, GameFrameX.Scene.UnloadSceneFailureEventArgs e)
{
RefreshAudioListener();
}
private void OnSceneLoaded(UnityEngine.SceneManagement.Scene scene, LoadSceneMode loadSceneMode)
{
RefreshAudioListener();
}
private void OnSceneUnloaded(UnityEngine.SceneManagement.Scene scene)
{
RefreshAudioListener();
}
private void RefreshAudioListener()
{
m_AudioListener.enabled = FindObjectsOfType<AudioListener>().Length <= 1;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8e5ee2e7720d430fbe254b2c6beb26b9
timeCreated: 1712714824

View File

@ -0,0 +1,37 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Sound;
using UnityEngine;
using UnityEngine.Audio;
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 声音组辅助器基类。
/// </summary>
public abstract class SoundGroupHelperBase : MonoBehaviour, ISoundGroupHelper
{
[SerializeField]
private AudioMixerGroup m_AudioMixerGroup = null;
/// <summary>
/// 获取或设置声音组辅助器所在的混音组。
/// </summary>
public AudioMixerGroup AudioMixerGroup
{
get
{
return m_AudioMixerGroup;
}
set
{
m_AudioMixerGroup = value;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c51c8a8caa384261b6bc4740614af11c
timeCreated: 1712714824

View File

@ -0,0 +1,24 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFrameX.Sound;
using UnityEngine;
namespace GameFrameX.Sound.Runtime
{
/// <summary>
/// 声音辅助器基类。
/// </summary>
public abstract class SoundHelperBase : MonoBehaviour, ISoundHelper
{
/// <summary>
/// 释放声音资源。
/// </summary>
/// <param name="soundAsset">要释放的声音资源。</param>
public abstract void ReleaseSoundAsset(object soundAsset);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2a438954854347319232d7fc9e416337
timeCreated: 1712714824

8
Tests.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e630cd0c6d7b2d94da581cddbd575508
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
{
"name": "GameFrameX.Sound.Tests",
"references": [
"GameFrameX.Sound.Runtime"
],
"rootNamespace": "GameFrameX.Sound.Tests",
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d8145fe4c43fbeb4ba5d435e6c74467d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

37
Tests/UnitTests.cs Normal file
View File

@ -0,0 +1,37 @@
using System;
using NUnit.Framework;
namespace GameFrameX.Sound.Tests
{
internal class UnitTests
{
private DateTime dateTime, dateTime1;
[SetUp]
public void Setup()
{
dateTime = DateTime.Now;
dateTime1 = DateTime.Now.AddHours(1);
}
// Here is an example of a unit test for the IsUnixSameDay method
[Test]
public void TestIsUnixSameDay()
{
// Arrange
// long timestamp1 = 1617842400; // April 7, 2021 12:00:00 AM UTC
// long timestamp2 = 1617896400; // April 7, 2021 12:00:00 PM UTC
// Act
}
[Test]
public void Test1()
{
Assert.That(dateTime1.Year, Is.EqualTo(dateTime.Year));
Assert.That(dateTime1.Month, Is.EqualTo(dateTime.Month));
Assert.That(dateTime1.Day, Is.EqualTo(dateTime.Day));
}
}
}

11
Tests/UnitTests.cs.meta Normal file
View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c468cff1391a8d34fa4eab52ca639d93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

23
package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "com.alianblank.gameframex.sound",
"displayName": "Game Frame X Sound",
"category": "Game Framework X",
"description": "Game Frame X Sound Component",
"version": "1.0.0",
"unity": "2017.1",
"keywords": [
"Game Framework X"
],
"repository": {
"name": "com.alianblank.gameframex.sound",
"url": "https://github.com/AlianBlank/com.alianblank.gameframex.unity.sound.git",
"type": "git"
},
"author": {
"name": "Blank",
"email": "alianblank@outlook.com",
"url": "https://alianblank.com/"
},
"dependencies": {
}
}

7
package.json.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c91723af18ccda14590bab24a408e73c
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: