添加对象池并更新KeySettingManager的README
This commit is contained in:
@@ -20,7 +20,7 @@ namespace AnnoyingUtils.KeyboardInput
|
|||||||
if (_instance) return _instance;
|
if (_instance) return _instance;
|
||||||
_instance = FindObjectOfType<KeySettingManager>();
|
_instance = FindObjectOfType<KeySettingManager>();
|
||||||
if (_instance) return _instance;
|
if (_instance) return _instance;
|
||||||
var go = new GameObject("KeySettingManager");
|
var go = new GameObject(nameof(KeySettingManager));
|
||||||
_instance = go.AddComponent<KeySettingManager>();
|
_instance = go.AddComponent<KeySettingManager>();
|
||||||
|
|
||||||
return _instance;
|
return _instance;
|
||||||
|
|||||||
@@ -2,17 +2,20 @@
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class KeyMapping
|
public class KeyMapping
|
||||||
{
|
{
|
||||||
public string actionName;
|
public string actionName;
|
||||||
public KeyCode keyCode;
|
public KeyCode keyCode;
|
||||||
|
|
||||||
public KeyMapping(string actionName, KeyCode keyCode)
|
public KeyMapping(string actionName, KeyCode keyCode)
|
||||||
{
|
{
|
||||||
this.actionName = actionName;
|
this.actionName = actionName;
|
||||||
this.keyCode = keyCode;
|
this.keyCode = keyCode;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<code>KeySettingManager</code>为单例类
|
<code>KeySettingManager</code>为单例类
|
||||||
//todo
|
在<code>LoadKeySettings()</code>中填写自己需要的键位对即可。
|
||||||
|
调用<code>GetKey(string actionName)</code>获取行为对应的KeyCode
|
||||||
|
|
||||||
|
调用<code>SetKey(string actionName, KeyCode newKeyCode)</code>设置行为对应KeyCode
|
||||||
29
Pool/Editor/SingletonObjectPoolerInitializer.cs
Normal file
29
Pool/Editor/SingletonObjectPoolerInitializer.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AnnoyingUtils.Pool.Editor
|
||||||
|
{
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public static class SingletonObjectPoolInitializer
|
||||||
|
{
|
||||||
|
static SingletonObjectPoolInitializer()
|
||||||
|
{
|
||||||
|
CreateSingletonInstances();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateSingletonInstances()
|
||||||
|
{
|
||||||
|
var types = typeof(SingletonObjectPool<>).Assembly.GetTypes();
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
if (!type.IsSubclassOf(typeof(MonoBehaviour)) || !type.BaseType.IsGenericType ||
|
||||||
|
type.BaseType.GetGenericTypeDefinition() != typeof(SingletonObjectPool<>)) continue;
|
||||||
|
var existingInstances = UnityEngine.Object.FindObjectsOfType(type);
|
||||||
|
if (existingInstances.Length != 0) continue;
|
||||||
|
var obj = new GameObject(type.Name);
|
||||||
|
obj.AddComponent(type);
|
||||||
|
Debug.Log(type.Name + " 单例实力已创建");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Pool/README.md
Normal file
42
Pool/README.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
新建一个对象池类继承SingletonObjectPool后,在UnityEditor中会自动创建以类名为名称的单例实例。
|
||||||
|
```csharp
|
||||||
|
public class EnemyPool : SingletonObjectPool<Enemy>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
用法示例如下方刷怪圈
|
||||||
|
```csharp
|
||||||
|
public class EnemySpawner : MonoBehaviour
|
||||||
|
{
|
||||||
|
public GameObject enemyPrefab;
|
||||||
|
public int initialPoolSize = 5;
|
||||||
|
public int maxPoolSize = 10;
|
||||||
|
public float spawnInterval = 3f;
|
||||||
|
public int spawnCount = 1;
|
||||||
|
public float spawnRadius = 5f;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
SingletonObjectPool<Enemy>.Instance.Init(enemyPrefab.GetComponent<Enemy>(), initialPoolSize, maxPoolSize);
|
||||||
|
StartCoroutine(SpawnEnemiesCoroutine());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator SpawnEnemiesCoroutine()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(spawnInterval);
|
||||||
|
SpawnEnemies();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpawnEnemies()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < spawnCount; i++)
|
||||||
|
{
|
||||||
|
var spawnPosition = transform.position + (Vector3)Random.insideUnitCircle * spawnRadius;
|
||||||
|
SingletonObjectPool<Enemy>.Instance.Spawn(transform).transform.position = spawnPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
103
Pool/SingletonObjectPooler.cs
Normal file
103
Pool/SingletonObjectPooler.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Pool;
|
||||||
|
|
||||||
|
namespace AnnoyingUtils.Pool
|
||||||
|
{
|
||||||
|
public class SingletonObjectPool<T> : MonoBehaviour where T : MonoBehaviour
|
||||||
|
{
|
||||||
|
#region 单例
|
||||||
|
|
||||||
|
private static SingletonObjectPool<T> _instance;
|
||||||
|
|
||||||
|
public static SingletonObjectPool<T> Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance) return _instance;
|
||||||
|
_instance = FindObjectOfType<SingletonObjectPool<T>>();
|
||||||
|
if (_instance) return _instance;
|
||||||
|
var obj = new GameObject(typeof(SingletonObjectPool<T>).Name);
|
||||||
|
_instance = obj.AddComponent<SingletonObjectPool<T>>();
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
private ObjectPool<T> _pool;
|
||||||
|
private T _prefab;
|
||||||
|
private Queue<T> _activeObjects;
|
||||||
|
private int _maxActiveObjects;
|
||||||
|
|
||||||
|
public void Init(T prefab, int defaultCapacity = 1, int maxSize = 10)
|
||||||
|
{
|
||||||
|
if (prefab is null)
|
||||||
|
{
|
||||||
|
Debug.LogError("预制体为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_prefab = prefab;
|
||||||
|
_maxActiveObjects = maxSize;
|
||||||
|
_pool = new ObjectPool<T>(CreateFunc, ActionOnGet, ActionOnRelease, ActionOnDestroy, true, defaultCapacity,
|
||||||
|
maxSize);
|
||||||
|
_activeObjects = new Queue<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private T CreateFunc()
|
||||||
|
{
|
||||||
|
return Instantiate(_prefab);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActionOnGet(T obj)
|
||||||
|
{
|
||||||
|
obj.gameObject.SetActive(true);
|
||||||
|
_activeObjects.Enqueue(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActionOnRelease(T obj)
|
||||||
|
{
|
||||||
|
obj.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActionOnDestroy(T obj)
|
||||||
|
{
|
||||||
|
Destroy(obj.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
//供滴人死亡、子弹命中等调用
|
||||||
|
public void Release(T obj)
|
||||||
|
{
|
||||||
|
if (_pool is null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning(typeof(T).Name + " 对象池未实例化");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeObjects.Dequeue();
|
||||||
|
_pool.Release(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Spawn(Transform parent)
|
||||||
|
{
|
||||||
|
if (_pool is null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning(typeof(T).Name + " 对象池未实例化");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查是否超出容量
|
||||||
|
if (_activeObjects.Count >= _maxActiveObjects)
|
||||||
|
{
|
||||||
|
var oldestObject = _activeObjects.Peek();
|
||||||
|
Release(oldestObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
var temp = _pool.Get();
|
||||||
|
temp.transform.position = parent.position;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user