组件池(Component Pool)
组件池介绍
组件池是此框架内置的适用于Unity的Component的引用池,当组件Component进入该引用池时,此组件会被隐藏(默认是Component所挂在的GameObject将被SetActive(false)),而当Component从该引用池拿出时,此组件会被显示或者说取消隐藏(默认是Component所挂在的GameObject将被自动SetActive(true))。
内置的组件池策略实现
实现的是 IPoolPolicy,主要是DefaultComponentPoolPolicy,用于传给 DefaultPool和 DefaultConcurrentPool作为实例化参数。
https://github.com/VMware233/VMFramework/blob/main/Assets/VMFramework/Main/Core/Collections/Pools/ComponentPool/ComponentPoolPolicy.cs
https://github.com/VMware233/VMFramework/blob/main/Assets/VMFramework/Main/Core/Collections/Pools/ComponentPool/DefaultComponentPoolPolicy.cs
https://github.com/VMware233/VMFramework/blob/main/Assets/VMFramework/Main/Core/Collections/Pools/ComponentPool/CustomComponentPoolPolicy.cs
示例
以下是一个组件池的使用示例,实现一个简单的音效管理器:
https://github.com/VMware233/VMFramework/blob/main/Assets/Examples/Core/Pools/AudioSpawner.cs
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Cysharp.Threading.Tasks;
using Sirenix.OdinInspector;
using UnityEngine;
using VMFramework.Core;
using VMFramework.Core.Pools;
namespace VMFramework.Examples
{
public class AudioSpawner : UniqueMonoBehaviour<AudioSpawner>
{
#region Config
/// <summary>
/// The default transform parent for the AudioSource components.
/// </summary>
[SerializeField]
private Transform audioSourceDefaultContainer;
#endregion
// The pool dictionary for the AudioSource components.
[ShowInInspector]
private static Dictionary<AudioClip, DefaultPool<AudioSource>> audioSourcePoolDictionary = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static DefaultPool<AudioSource> CreatePool(AudioClip audioClip)
{
return new(new CustomComponentPoolPolicy<AudioSource>(() =>
{
var audioSource = new GameObject(audioClip.name).AddComponent<AudioSource>();
audioSource.clip = audioClip;
return audioSource;
}, returnFunc: audioSource =>
{
audioSource.transform.SetParent(instance.audioSourceDefaultContainer);
audioSource.SetActive(false);
return true;
}));
}
[Button]
public static AudioSource Play(AudioClip audioClip, Vector3 position, bool autoCheckStop,
Transform parent = null)
{
if (audioClip == null)
{
Debug.LogError("AudioClip is null");
return null;
}
if (audioSourcePoolDictionary.TryGetValue(audioClip, out var audioSourcePool) == false)
{
audioSourcePool = CreatePool(audioClip);
audioSourcePoolDictionary.Add(audioClip, audioSourcePool);
}
var audioSource = audioSourcePool.Get(parent);
audioSource.transform.position = position;
audioSource.loop = false;
audioSource.Play();
if (autoCheckStop)
{
_ = CheckStop(audioSource);
}
return audioSource;
}
[Button]
public static void Return(AudioSource audioSource)
{
audioSource.Stop();
if (audioSource.gameObject.activeSelf)
{
audioSource.transform.SetParent(instance.audioSourceDefaultContainer);
if (audioSource.clip == null)
{
Debug.LogError("AudioSource.clip is null");
return;
}
if (audioSourcePoolDictionary.TryGetValue(audioSource.clip, out var audioSourcePool) == false)
{
audioSourcePool = CreatePool(audioSource.clip);
audioSourcePoolDictionary.Add(audioSource.clip, audioSourcePool);
}
audioSourcePool.Return(audioSource);
}
}
/// <summary>
/// Check if the audio has ended and return it if it has.
/// </summary>
/// <param name="audioSource"></param>
/// <returns></returns>
private static async UniTaskVoid CheckStop(AudioSource audioSource)
{
await UniTask.WaitUntil(() => audioSource.isPlaying == false);
Return(audioSource);
}
}
}如果顺利编译,并把此脚本挂到一个GameObject上,则应如下所示:

最后更新于
这有帮助吗?