NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Vehicle/Battery/BaseBattery.cs

154 lines
4.5 KiB
C#

using System;
using System.Linq;
using cfg.FightCfg;
using Cysharp.Threading.Tasks;
using Framework;
using Gameplay.Unit;
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<BaseBaterryState> _fsm;
/// <summary>
/// 炮台动画比较简单,直接使用Animator
/// </summary>
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 = rawConfig.ModelPath;
GameUnitManager.instance.RecordLoadPath(batteryPath);
var sampleObj = await AssetManager.Instance.LoadAssetAsync<GameObject>(batteryPath);
if (sampleObj == null)
{
DebugUtil.LogError("加载炮台失败: {0}", batteryPath);
return;
}
rootObj = Object.Instantiate(sampleObj, parent);
rootObj.transform.ResetLocals();
var allTrans = rootObj.GetComponentsInChildren<Transform>();
rawAnim = rootObj.GetComponentInChildren<Animator>();
rotateTrans = rootObj.transform;
_fireTrans = allTrans.First(t => t.name == "Fire");
}
private void _InitFsm()
{
_fsm = new NStateMachine<BaseBaterryState>();
_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);
}
}
}