151 lines
4.5 KiB
C#
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 RandomSelector<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
|
|
}
|
|
} |