using System; using AibisDream.FixSystem; using AibisDream.Utility; using UnityEngine; namespace AibisDream { public class EngineSystem : MonoBehaviour { [SerializeField] private float oilDownRatio; [SerializeField] private float oilUpRatio; [SerializeField] private float acceleratedSpeed; [SerializeField] private float resistance; [SerializeField] private float airMaxRatio; [SerializeField] private float airMinRatio; [SerializeField] private float baseAirMax; [SerializeField] public int maxLevel; [SerializeField] public float invalidTime; private bool IsValid => engineData.isValid.Value; [Header("系统数据")] [SerializeField] private EngineData engineData; public event Action UpdateDashboard; private void Awake() { FixSystemCenter.SystemDic.Register(this); } private void OnEnable() { engineData = new EngineData(invalidTime); } private void Update() { // 更新部分按时间自然计算的指标 DataAutoChange(); // 更新看板 UpdateDashboard?.Invoke(engineData); } private void DataAutoChange() { // 自然减速 engineData.OilChange(-oilDownRatio); engineData.CalcAir(airMaxRatio, airMinRatio, baseAirMax); // 推算速度 engineData.CalcSpeed(acceleratedSpeed, resistance); } /// /// 加速过程 /// public void AddOil() { if (IsValid) { engineData.OilChange(oilUpRatio); } // 失效期无法加油门 } public void UpdateAirLevel(int curLevel) { engineData.UpdateAirLevel(curLevel, maxLevel); } } [Serializable] public struct EngineData { public float curSpeed; public float curOil; public float curAir; public float curAirMin; public float curAirMax; public int curAirLevel; public AutoFlipBool isValid; public bool inAirRange; public EngineData(float flipDelayTime) { isValid = new AutoFlipBool(flipDelayTime, true); curSpeed = 0; curOil = 0; curAir = 0; curAirMin = 0; curAirMax = 0; curAirLevel = 0; inAirRange = false; } public void OilChange(float oilChangeRatio) { curOil = CommonUtil.LimitedAdd(curOil, oilChangeRatio * Time.deltaTime, 1f, 0f); } public void CalcSpeed(float acceleratedSpeed, float resistance) { var addNum = inAirRange && isValid.Value ? (curOil * acceleratedSpeed - curSpeed * resistance) * Time.deltaTime : -curSpeed * resistance * Time.deltaTime; curSpeed = CommonUtil.LimitedAdd(curSpeed, addNum, 1f, 0f); } public void CalcAir(float airMaxRatio, float airMinRatio, float baseAirMax) { curAirMax = curSpeed * (curAirLevel + 1) * airMaxRatio + baseAirMax; curAirMin = curSpeed * (curAirLevel + 1) * airMinRatio; curAir = curOil; // 如果离开范围且当前在系统有效期,就进入一段失效期 var curInAirRange = curAir <= curAirMax && curAir >= curAirMin; if (inAirRange && !curInAirRange && isValid.Value) { isValid.Value = false; } } public void UpdateAirLevel(int level, int maxLevel) { curAirLevel = level; if (curAirLevel > maxLevel) { curAirLevel = maxLevel - 1; } if (curAirLevel < 0) { curAirLevel = 0; } } } }