using UnityEngine; namespace BrewMonster { /// /// Homing missile movement with rotation toward target. /// Mirrors C++ CGfxMissileMove exactly (A3DSkillGfxEvent2.cpp:94-142). /// 追踪导弹移动(向目标旋转),完全镜像C++ CGfxMissileMove。 /// public class CGfxMissileMove : CGfxMoveBase { protected Vector3 m_vOrgPos; protected float m_fCurVel; private const float _missile_acc = 20.0f; // acceleration, same as C++ private const float _missile_vel = 5.0f; // initial velocity, same as C++ private const float _missile_rot = Mathf.PI * 1.5f; // rotation speed (radians per second), same as C++ private float _angle_limit = Mathf.Cos(15.0f * Mathf.Deg2Rad); // 15 degree limit, same as C++ public CGfxMissileMove(GfxMoveMode mode) : base(mode) { } /// /// Initialize missile movement from host to target. /// 初始化从施法者到目标的导弹移动。 /// public override void StartMove(Vector3 vHost, Vector3 vTarget) { if (m_bArea) { CalcRange((vTarget - vHost).normalized); m_vOrgPos = m_vPos = vHost + GetRandOff(); } else { m_vOrgPos = m_vPos = vHost; } m_vMoveDir = vTarget - m_vPos; m_vMoveDir.y = 0; Normalize(ref m_vMoveDir); // Random initial angle around Y axis (PI/2 to 3*PI/2 range) // 围绕Y轴的随机初始角度(PI/2到3*PI/2范围) float fAngle = Mathf.PI / 2.0f + Mathf.PI * Random.value; Quaternion q = Quaternion.AngleAxis(fAngle * Mathf.Rad2Deg, Vector3.up); m_vMoveDir = q * m_vMoveDir; m_fCurVel = _missile_vel; } /// /// Tick missile movement. Returns true when target is hit. /// 更新导弹移动。当命中目标时返回true。 /// public override bool TickMove(uint dwDeltaTime, Vector3 vHostPos, Vector3 vTargetPos) { float fTime = dwDeltaTime / 1000.0f; Vector3 vDir = vTargetPos - m_vPos; float fDist = m_fCurVel * fTime; if (fDist >= Normalize(ref vDir)) { return true; } float fAngle = Vector3.Dot(m_vMoveDir, vDir); if (fAngle > _angle_limit) { // Close enough to target direction, accelerate and move directly // 足够接近目标方向,加速并直接移动 m_fCurVel += _missile_acc * fTime; m_vPos += vDir * fDist; m_vMoveDir = vDir; } else { // Rotate toward target // 向目标旋转 m_vPos += m_vMoveDir * fDist; Vector3 vUp = Vector3.Cross(m_vMoveDir, vDir); Normalize(ref vUp); Quaternion q = Quaternion.AngleAxis(_missile_rot * fTime * Mathf.Rad2Deg, vUp); m_vMoveDir = q * m_vMoveDir; } return false; } } }