Skip to content

Commit c9dc6cf

Browse files
committed
RimeFramework v0.1.0
1 parent 76eee26 commit c9dc6cf

File tree

4 files changed

+276
-49
lines changed

4 files changed

+276
-49
lines changed

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Rime Framework
1+
# Rime Framework v0.0.1
22
「Rime Framework」很轻,就像雾凇上的白霜一般,覆之于上,将其包裹着的物体装饰的冰洁、神圣。
33

4-
「Rime Framework」是Unity的一个超轻量级框架,目的是提供简洁的接口,使用起来不会破坏原代码的结构,就像没有一样。目前目前主要有八个模块:Consoles、Controls、States、Pools、Cycles、Animators、Scenes、Navigations。RimeManager负责启动模块。
4+
「Rime Framework」是Unity的一个超轻量级框架,目的是提供简洁的接口,使用起来不会破坏原代码的结构,就像没有一样。目前目前主要有九个模块:Consoles、Controls、States、Pools、Cycles、Animators、Scenes、Navigations、Audios。RimeManager负责启动模块。
55

66
Consoles 💻
77

@@ -37,46 +37,46 @@ Rime Framework的导航组,对游戏中的所有面板进行导航,并且有
3737

3838
Audios 🔊
3939

40-
即将到来,敬请期待!
40+
Rime Framework的音效师,管理游戏中的所有声音,并且与Pools联动
4141

4242
------
4343

44-
The "Rime Framework" is lightweight, akin to the white frost on rime ice, enveloping objects in an ice-like purity and sanctity.
44+
The "Rime Framework" is lightweight, like the white frost on rime ice, enveloping objects and adorning them with purity and sanctity.
4545

46-
The "Rime Framework" is an ultra-lightweight framework for Unity, designed to provide a concise interface that won't disrupt the original code structure—it's as if it's not even there. Currently, there are eight main modules: ConsolesControlsStatesPoolsCyclesAnimatorsScenes and Navigations. The RimeManager is responsible for launching these modules.
46+
The "Rime Framework" is an ultra-lightweight framework for Unity, designed to provide a concise interface that does not disrupt the structure of the original code, making it feel almost invisible. Currently, it features nine main modules: Consoles, Controls, States, Pools, Cycles, Animators, Scenes, Navigations, and Audios. The RimeManager is responsible for initializing these modules.
4747

4848
**Consoles 💻**
4949

50-
The console of the Rime Framework is responsible for printing logs from the Rime Framework, supporting the printing of instances and types.
50+
The console of the Rime Framework, responsible for printing out the logs of RimeFramework. It supports logging for instances and types.
5151

5252
**Controls 🎮**
5353

54-
The controller of the Rime Framework is developed based on the InputSystem. It uses event-driven mechanisms to control input events, supports hot-swapping of devices, long press charging, and is easily extensible and adaptable.
54+
The controller of the Rime Framework, developed based on the InputSystem. It uses event-driven mechanisms to manage input events, supports hot-swapping of devices, and allows for long press actions. It is also easily extensible and customizable.
5555

5656
**States 🗡️**
5757

58-
The state machine of the Rime Framework is very simple and easy to use, allowing collaboration with Controls to facilitate character control development. It also effectively handles state transitions and animation switches.
58+
The state machine of the Rime Framework, which is simple and easy to use, can work in conjunction with Controls to facilitate the development of character manipulation, and effectively handle state and animation transitions.
5959

6060
**Pools 💧**
6161

62-
The object pool of the Rime Framework supports threefold management of Objects, Monobehaviours, and GameObjects, and works with Cycles to achieve a complete Unity lifecycle for non-Mono classes.
62+
The object pool of the Rime Framework, which supports triple management of Objects, Monobehaviour, and GameObjects, and integrates well with Cycles to achieve a complete Unity lifecycle without using Mono.
6363

6464
**Cycles 🕙**
6565

66-
The lifecycle management of the Rime Framework, in conjunction with Pools, optimizes memory usage and allows for straightforward integration of non-Mono classes into the Unity loop.
66+
The lifecycle management of the Rime Framework, which optimizes memory in conjunction with Pools and makes it easy to add non-Mono classes into the Unity loop.
6767

6868
**Animators ✍️**
6969

70-
The animator of the Rime Framework registers animations for playback, facilitates animation blending and groups, and supports success and failure callbacks, allowing independence from Animator connections.
70+
The animator of the Rime Framework, which registers animations for playback, blending animations, and supports callback mechanisms for success and failure, allowing it to operate independently of Animator connections.
7171

7272
**Scenes 🎬**
7373

74-
The scenographer of the Rime Framework is responsible for the asynchronous loading and unloading of scenes, supporting completion callbacks and cancellation callbacks.
74+
The scene manager of the Rime Framework, responsible for asynchronously loading and unloading scenes, supporting completion callbacks and cancellation callbacks.
7575

7676
**Navigations ➡️**
7777

78-
The navigation group of the Rime Framework manages navigation for all panels in the game, featuring a loop prevention mechanism.
78+
The navigation group of the Rime Framework, which manages navigation for all panels in the game and includes a mechanism to prevent loops.
7979

8080
**Audios 🔊**
8181

82-
Coming soon, stay tuned!
82+
The sound engineer of the Rime Framework, which manages all audio in the game and interacts with Pools.

RimeFramework/Core/Animators/Animators.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ public class Animators : Singleton<Animators>
2525
/// </summary>
2626
/// <param name="groupName">组名</param>
2727
/// <param name="animations">序列动画名</param>
28-
public static void Register(string groupName,params string[] animations)
29-
{
30-
_dicGroups[groupName] = animations;
31-
}
28+
public static void Register(string groupName,params string[] animations) => _dicGroups[groupName] = animations;
3229

3330
/// <summary>
3431
/// 播放 动画/动画组,组优先级 > 动画
Lines changed: 231 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,242 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
14
using RimeFramework.Tool;
5+
using UnityEngine;
26

37
namespace RimeFramework.Core
48
{
59
/// <summary>
6-
/// 霜 · 声音 🔊
10+
/// 霜 · 音效师 🔊
711
/// </summary>
12+
/// <b> 支持多通道播放声音、BGM淡入淡出、3D音效、循环播放、提供最简单的调用接口
13+
/// <see cref="PlayS3D(MonoBehaviour,string,PlayingCall,bool)"/> 播放3D声音,需要一个拥有者
14+
/// <see cref="PlayS3D(string,PlayingCall,bool)"/> 播放2D声音
15+
/// <see cref="PlaySUI(string,PlayingCall,bool)"/> 播放UI声音
16+
/// <see cref="PlayS3D(string)"/> 播放BGM,淡入淡出
17+
/// <remarks>Author: AstoraGray</remarks>
18+
[RequireComponent(typeof(AudioSource))]
819
public class Audios : Singleton<Audios>
920
{
21+
private static AudioSource _audioMusic; // BGM音轨
22+
23+
public static readonly float musicVolume = 1; // BGM音量
24+
25+
public static readonly float s2dVolume = 1; // 2D音量
26+
27+
public static readonly float s3dVolume = 1; // 3D音量
28+
29+
public static readonly float suiVolume = 1; // UI音量
30+
31+
private static readonly Dictionary<string, AudioClip> _dicClips = new(); // 缓存音频
32+
33+
private static Coroutine _coroutineMusicFade; // 淡入淡出协程
34+
35+
private static AudioClip _clipCurMusic; // 当前BGM
36+
37+
private const float FADE_TIME = 2f; // 淡入淡出时间(真实时间)
38+
39+
private const string AUDIO_PATH = "Audios/"; // 音频文件路径
40+
41+
private enum AudioType
42+
{
43+
S2D, // 2D声音(无距离、可多个)
44+
S3D, // 3D声音(有距离、可多个)
45+
SUI, // UI声音(无距离、可多个)
46+
Music // BGM(无距离、单一、淡入淡出)
47+
}
48+
49+
private enum FadeType
50+
{
51+
In, // 淡入
52+
Out // 淡出
53+
}
54+
/// <summary>
55+
/// 初始化
56+
/// </summary>
57+
protected override void Awake()
58+
{
59+
base.Awake();
60+
_audioMusic = GetComponent<AudioSource>();
61+
_audioMusic.loop = true;
62+
_audioMusic.volume = 0f;
63+
}
64+
65+
/// <summary>
66+
/// 播放3D声音
67+
/// </summary>
68+
public static void PlayS3D(MonoBehaviour own, string name,PlayingCall call = null,bool loop = false) => Play(own, name, AudioType.S3D,call,loop);
69+
/// <summary>
70+
/// 播放2D声音
71+
/// </summary>
72+
public static void PlayS2D(string name,PlayingCall call = null,bool loop = false) => Play(null, name, AudioType.S2D,call,loop);
73+
/// <summary>
74+
/// 播放UI声音
75+
/// </summary>
76+
public static void PlaySUI(string name,PlayingCall call = null,bool loop = false) => Play(null, name, AudioType.SUI,call,loop);
77+
/// <summary>
78+
/// 播放BGM
79+
/// </summary>
80+
public static void PlayMusic(string name) => Play(null, name, AudioType.Music,null,true);
81+
/// <summary>
82+
/// 播放声音
83+
/// </summary>
84+
/// <param name="own">拥有者</param>
85+
/// <param name="name">音频名称</param>
86+
/// <param name="type">音频类型</param>
87+
/// <param name="call">播放回调</param>
88+
/// <param name="loop">是否循环</param>
89+
private static void Play(MonoBehaviour own, string name, AudioType type,PlayingCall call,bool loop)
90+
{
91+
AudioClip clip;
92+
if (!_dicClips.ContainsKey(name))
93+
{
94+
string path = $"{AUDIO_PATH}{name}";
95+
clip = Resources.Load<AudioClip>(path);
96+
if (clip == null)
97+
{
98+
Consoles.Print(typeof(Audios),$"找不到音频文件{path}");
99+
return;
100+
}
101+
_dicClips[name] = clip;
102+
}
103+
104+
clip = _dicClips[name];
105+
106+
AudioSource audio = null;
107+
switch (type)
108+
{
109+
case AudioType.S2D:
110+
audio = Pools.Take<AudioSource>();
111+
audio.clip = clip;
112+
audio.volume = s2dVolume;
113+
audio.spatialBlend = 0;
114+
audio.loop = loop;
115+
Instance.StartCoroutine(PlaySound(null, audio,call));
116+
break;
117+
case AudioType.S3D:
118+
if (own == null)
119+
{
120+
Consoles.Print(typeof(Audios),$"播放{name}声音失败,3D声音需要指定一个拥有者");
121+
return;
122+
}
123+
audio = Pools.Take<AudioSource>();
124+
audio.clip = clip;
125+
audio.volume = s3dVolume;
126+
audio.spatialBlend = 1;
127+
audio.loop = loop;
128+
Instance.StartCoroutine(PlaySound(own, audio,call));
129+
break;
130+
case AudioType.SUI:
131+
audio = Pools.Take<AudioSource>();
132+
audio.clip = clip;
133+
audio.volume = suiVolume;
134+
audio.spatialBlend = 0;
135+
audio.loop = loop;
136+
Instance.StartCoroutine(PlaySound(null, audio,call));
137+
break;
138+
case AudioType.Music:
139+
if (clip == _clipCurMusic)
140+
{
141+
return;
142+
}
143+
144+
_clipCurMusic = clip;
145+
146+
if (_audioMusic.isPlaying)
147+
{
148+
Consoles.Print(typeof(Audios),$"开始淡出BGM {_audioMusic.name}");
149+
_coroutineMusicFade = Instance.StartCoroutine(FadeMusic(_audioMusic.volume,0,FADE_TIME,FadeType.Out, () =>
150+
{
151+
_audioMusic.clip = clip;
152+
Consoles.Print(typeof(Audios),$"开始淡入BGM {name}");
153+
_coroutineMusicFade = Instance.StartCoroutine(FadeMusic(_audioMusic.volume,musicVolume,FADE_TIME,FadeType.In));
154+
}));
155+
}
156+
else
157+
{
158+
_audioMusic.clip = clip;
159+
Consoles.Print(typeof(Audios),$"开始淡入BGM {name}");
160+
_coroutineMusicFade = Instance.StartCoroutine(FadeMusic(_audioMusic.volume,musicVolume,FADE_TIME,FadeType.In));
161+
}
162+
break;
163+
}
164+
}
165+
/// <summary>
166+
/// 淡入淡出BGM
167+
/// </summary>
168+
/// <param name="startVolume">开始音量</param>
169+
/// <param name="endVolume">结束音量</param>
170+
/// <param name="duration">持续时间</param>
171+
/// <param name="fadeType">淡入/淡出</param>
172+
/// <param name="onComplete">结束回调</param>
173+
/// <returns></returns>
174+
private static IEnumerator FadeMusic(float startVolume, float endVolume, float duration,FadeType fadeType, Action onComplete = null)
175+
{
176+
yield return null;
177+
Coroutine coroutine = _coroutineMusicFade;
178+
float startTime = Time.time;
179+
_audioMusic.volume = startVolume;
180+
181+
if (fadeType == FadeType.In)
182+
{
183+
_audioMusic.Play();
184+
}
185+
186+
while (Time.time < startTime + duration)
187+
{
188+
if (coroutine != _coroutineMusicFade)
189+
{
190+
yield break;
191+
}
192+
_audioMusic.volume = Mathf.Lerp(startVolume, endVolume, 1 - (startTime + duration - Time.time) / duration);
193+
yield return null;
194+
}
195+
196+
_audioMusic.volume = endVolume;
197+
198+
if (fadeType == FadeType.Out)
199+
{
200+
_audioMusic.Stop();
201+
}
202+
203+
onComplete?.Invoke();
204+
}
205+
/// <summary>
206+
/// 播放条件(可空)
207+
/// </summary>
208+
public delegate bool PlayingCall(MonoBehaviour own, string name);
10209

210+
/// <summary>
211+
/// 播放声音协程
212+
/// </summary>
213+
/// <param name="own">拥有者</param>
214+
/// <param name="audio">音频</param>
215+
/// <param name="call">播放条件回调</param>
216+
/// <returns></returns>
217+
private static IEnumerator PlaySound(MonoBehaviour own, AudioSource audio, PlayingCall call)
218+
{
219+
audio.Play();
220+
float clipLength = audio.clip.length;
221+
float endTime = Time.time + clipLength;
222+
223+
while (call?.Invoke(own,audio.clip.name) ?? (audio.loop || Time.time < endTime))
224+
{
225+
if (own != null)
226+
{
227+
audio.transform.position = own.transform.position;
228+
}
229+
230+
if (!audio.isPlaying)
231+
{
232+
break;
233+
}
234+
235+
yield return null;
236+
}
237+
238+
audio.Stop();
239+
Pools.Put(audio);
240+
}
11241
}
12242
}

0 commit comments

Comments
 (0)