using System; using System.Linq; using cfg.FightCfg; using Cysharp.Threading.Tasks; using Framework; using Gameplay.Unit; using Gameplay.Utils; using Gameplay.Vehicle.Impl; using LTGame; using PhxhSDK; namespace Gameplay.Vehicle { using UnityEngine; public class BaseBattery { public readonly NormalVehicle owner; public GameObject rootObj; private Transform _fireTrans; public Transform fireTrans { get { return _fireTrans; } } public DataBattery rawConfig; public int remainBulletCount { get; set; } public GameUnit lockEnemy; private NStateMachine _fsm; /// /// 炮台动画比较简单,直接使用Animator /// public Animator rawAnim; public Transform parent; public Transform rotateTrans; public BaseBattery(BaseVehicle owner, Transform parent) { this.parent = parent; this.owner = owner as NormalVehicle; if (this.owner == null) { throw new Exception("炮台必须挂载在NormalVehicle上"); } rawConfig = TableManager.Instance.Tables.BatteryConfig.GetOrDefault(owner.configData.weaponId); } public async UniTask CreateView() { var batteryPath = PathEx.GetBatteryModelPath(rawConfig.ModelPath); GameUnitManager.instance.RecordLoadPath(batteryPath); var sampleObj = await AssetManager.Instance.LoadAssetAsync(batteryPath); if (sampleObj == null) { DebugUtil.LogError("加载炮台失败: {0}", batteryPath); return; } rootObj = Object.Instantiate(sampleObj, parent); rootObj.transform.ResetLocals(); var allTrans = rootObj.GetComponentsInChildren(); rawAnim = rootObj.GetComponentInChildren(); rotateTrans = rootObj.transform; _fireTrans = allTrans.First(t => t.name == "Fire"); } private void _InitFsm() { _fsm = new NStateMachine(); _fsm.Add(new BatteryStateIdle(this)); _fsm.Add(new BatteryStateShoot(this)); _fsm.Add(new BatteryStateReload(this)); _fsm.Add(new BatteryStateDestroyed(this)); _fsm.Add(new BatteryStateAttackEnd(this)); _fsm.ChangeState(EBatteryState.Idle); } public void Init() { _InitProp(); _InitFsm(); } private void _InitProp() { remainBulletCount = owner.fightData.maxBulletCount; } public bool RotateTower(GameUnit targetEnemy, float dt) { if (rotateTrans == null) { return false; } var turnSpeed = rawConfig.TurnSpeed; var turnDt = turnSpeed * dt; var isMatchAngle = false; if (targetEnemy == null || targetEnemy.isDisposed) { // 炮台回正 var localYaw = rotateTrans.localEulerAngles.z; var newYaw = Mathf.MoveTowardsAngle(localYaw, 0, turnDt); rotateTrans.localEulerAngles = new Vector3(0, 0, newYaw); } else { // 炮台转向目标 var targetPos = targetEnemy.transData.pos; var selfPos = rootObj.transform.position; var toTarget = targetPos - selfPos; toTarget.y = 0; var ownerForward = owner.transform.forward; var targetYaw = Vector3.SignedAngle(ownerForward, toTarget, Vector3.up); var nowYaw = rotateTrans.localEulerAngles.z; var deltaAngle = Mathf.Abs(Mathf.DeltaAngle(nowYaw, targetYaw)); if (deltaAngle < turnDt) { rotateTrans.localEulerAngles = new Vector3(0, 0, targetYaw); isMatchAngle = true; } else { var newYaw = Mathf.MoveTowardsAngle(nowYaw, targetYaw, turnDt); rotateTrans.localEulerAngles = new Vector3(0, 0, newYaw); } } return isMatchAngle; } public void LogicUpdate(float dt) { _fsm.LogicUpdate(dt); } } }