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 selector; protected MobileObjectFactory factory; public readonly List 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 CreateSelector(IEnumerable datas) { return new SingleSelector(datas, data => data.weight); } private List SetPublicVariable() { var res = new List(); 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(); 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 } }