Files
aibis-dream/Assets/Scripts/SceneManagement/SpawnerKit/Spawner.cs
T
2025-08-01 15:18:12 +08:00

151 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using AibisDream.Framework;
using UnityEngine;
using Random = UnityEngine.Random;
namespace AibisDream
{
public class Spawner : MonoBehaviour
{
[SerializeField] public MobileObjectData[] mobileObjectDatas;
[SerializeField] public bool playOnAwake;
[SerializeField] private InitMode initMode;
[SerializeField] private bool isDistanceMode = true;
[SerializeField] private float existTime;
[SerializeField] private float existDistance;
[SerializeField] protected Vector2 intervalRange;
protected ISelector<MobileObjectData> selector;
protected MobileObjectFactory factory;
public readonly List<AbsMobileObject> mobileObjects = new();
protected float curInterval;
protected float targetInterval;
protected bool isSpawning;
private void Awake()
{
if (playOnAwake)
{
Init();
}
}
public void Init()
{
// 先为Data赋一些公共值
var newMobileDatas = SetPublicVariable();
// 处理随机权重
selector = CreateSelector(newMobileDatas);
// 创建工厂
factory = new MobileObjectFactory(transform);
// 收集初始物体
CollectDefaultMobiles();
// 生成第一个物体
targetInterval = Random.Range(intervalRange.x, intervalRange.y);
SpawnFirst();
}
protected void SpawnFirst()
{
switch (initMode)
{
case InitMode.Immediate:
curInterval = 0;
Spawn();
break;
case InitMode.Random:
curInterval = Random.Range(0, targetInterval);
break;
case InitMode.Next:
curInterval = 0;
break;
default:
throw new ArgumentOutOfRangeException();
}
isSpawning = true;
}
protected virtual ISelector<MobileObjectData> CreateSelector(IEnumerable<MobileObjectData> datas)
{
return new SingleSelector<MobileObjectData>(datas, data => data.weight);
}
private List<MobileObjectData> SetPublicVariable()
{
var res = new List<MobileObjectData>();
foreach (var temp in mobileObjectDatas)
{
var dataItem = temp;
dataItem.isDistanceMode = isDistanceMode;
dataItem.existTime = existTime;
dataItem.existDistance = existDistance;
res.Add(dataItem);
}
return res;
}
private void CollectDefaultMobiles()
{
// 为工厂收集一些初始物体
var initObjects = GetComponentsInChildren<AbsMobileObject>();
factory.AddRecycleMobiles(initObjects);
foreach (var initObject in initObjects)
{
// 赋公共值
initObject.mobileObjectData.isDistanceMode = isDistanceMode;
initObject.mobileObjectData.existTime = existTime;
initObject.mobileObjectData.existDistance = existDistance;
// 启动
initObject.Init();
mobileObjects.Add(initObject);
initObject.OnDisposed += o => mobileObjects.Remove(o);
}
}
private void Update()
{
if (isSpawning)
{
OnUpdate();
}
}
protected virtual void OnUpdate()
{
curInterval += Time.deltaTime;
// 按时间间隔生成物体
if (curInterval >= targetInterval)
{
Spawn();
curInterval = 0;
targetInterval = Random.Range(intervalRange.x, intervalRange.y);
}
}
protected virtual void Spawn()
{
// 生成物体
var data = selector.Select();
var mobileObj = factory.CreateMobileObject(data);
mobileObjects.Add(mobileObj);
// 销毁时同样记录
mobileObj.OnDisposed += o => mobileObjects.Remove(o);
}
}
public enum InitMode
{
Immediate,
Random,
Next
}
}