using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; /// /// 荒野猎手技能:穿心猎矛体系(1/3/6/10 级完整阶梯) /// 1级【穿心猎矛】:蓄力重投飞矛,自动锁定全场【距离自身最远的目标(优先狙杀敌方后排)】,造成 180% 物理伤害;且【距离越远伤害越高】(每相距 1 米额外提升 5% 伤害,最高 +45%)!附带金色破空流光特效! /// 3级【极速重贯】:飞矛飞行速度 +40%,基础伤害提升至 230%,暴击率额外 +20%,远距离狙杀威慑力大增! /// 6级【破阵震退】:蓄力重矛命中目标时产生破空震荡,【将其向后强力击退 2.0 米】(纯物理后退,打乱敌方后排阵型,且不产生眩晕冗余)! /// 10级【绝命猎杀】:飞矛附带风暴雷霆之势,基础伤害飙升至 340% 极限制导高伤;【若成功斩杀目标,立即返还 50% 技能能量】,快速准备下一发致命狙杀! /// public class WildHunterSkill : UnitSkill { [Header("技能飞矛配置")] [Tooltip("技能重矛预制体 (Assets/Prefabs/武器飞行物/技能重矛.prefab)")] public GameObject skillSpearPrefab; [Tooltip("每米增加的伤害比例 (默认 5%)")] public float damageBonusPerMeter = 0.05f; [Tooltip("距离伤害加成上限 (默认 45%)")] public float maxDistanceBonus = 0.45f; [Tooltip("6级击退距离 (米)")] public float knockbackDistance = 2.0f; private bool isSkillPending = false; private GameObject currentSkillTarget; private void EnsureUnit() { if (unit == null) { unit = GetComponent(); } } /// /// 当能量蓄满时触发:锁定最远目标,播放投掷技能动作 /// public override void ReleaseSkill() { EnsureUnit(); if (unit == null) return; WorldHealthBar healthBar = unit.GetComponent(); if (healthBar == null || healthBar.IsDead) return; // 1级核心机制:自动锁定全场距离自身最远的敌方目标(后排核心/远程单位) currentSkillTarget = FindFurthestEnemy(); if (currentSkillTarget == null) return; // 技能施法朝向:应用 unit.modelFacingOffset 保证与普攻一致的朝向修正 Vector3 toTarget = currentSkillTarget.transform.position - unit.transform.position; toTarget.y = 0f; if (toTarget.sqrMagnitude > 0.001f) { Quaternion targetRotation = Quaternion.LookRotation(toTarget.normalized, Vector3.up); unit.transform.rotation = Quaternion.Euler(0f, targetRotation.eulerAngles.y + unit.modelFacingOffset, 0f); } isSkillPending = true; // 播放投掷动画,由 OnSkillHit1 帧投出重矛 unit.PlaySkillAnimation(OnSkillAnimationFinished, 2.0f); Debug.Log($"【荒野猎手】开始蓄力【穿心猎矛】! 目标锁定全场最远敌方: {currentSkillTarget.name} (距离: {Vector3.Distance(unit.transform.position, currentSkillTarget.transform.position):F1}m)"); } /// /// 动画事件帧方法:在手臂向后蓄力后猛烈投掷的瞬间触发 (OnSkillHit1) /// public void OnSkillHit1() { if (!isSkillPending) return; isSkillPending = false; EnsureUnit(); if (unit == null) return; GameObject opponent = (currentSkillTarget != null && currentSkillTarget.activeInHierarchy) ? currentSkillTarget : FindFurthestEnemy(); if (opponent == null) return; int level = unit.level; // 1. 确定重矛预制体 (技能重矛自带金色破空粒子拖尾 SparkleMissileYellow) GameObject prefab = skillSpearPrefab; #if UNITY_EDITOR if (prefab == null) { prefab = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Prefabs/武器飞行物/技能重矛.prefab"); } #endif if (prefab == null) prefab = unit.projectilePrefab; if (prefab == null) return; // 2. 确定出生点 (右手 pos) Transform spawnPoint = unit.projectileSpawnPoint != null ? unit.projectileSpawnPoint : unit.transform; Vector3 spawnPos = spawnPoint.position; // 3. 计算伤害与距离加成 (1级 180%, 3级 230%, 10级 340%) float baseMultiplier = 1.80f; if (level >= 10) baseMultiplier = 3.40f; else if (level >= 3) baseMultiplier = 2.30f; float distance = Vector3.Distance(unit.transform.position, opponent.transform.position); float distanceBonus = Mathf.Min(distance * damageBonusPerMeter, maxDistanceBonus); float finalMultiplier = baseMultiplier * (1f + distanceBonus); // 3级解锁:暴击率额外 +20%,飞行速度提升 40% float spearSpeed = (level >= 3) ? (unit.projectileSpeed * 1.4f) : unit.projectileSpeed; bool isCrit = (level >= 3) && (Random.value < (unit.critRate + 0.20f)); float totalDamage = unit.attackPower * finalMultiplier * (isCrit ? unit.critMultiplier : 1.0f); // 4. 实例化技能重矛 Vector3 flatDirection = (opponent.transform.position - spawnPos); flatDirection.y = 0f; Quaternion rot = Quaternion.LookRotation(flatDirection.normalized, Vector3.up); GameObject spearGo = Instantiate(prefab, spawnPos, rot); // 5. 挂载技能专属落弹与结算处理脚本 var runner = spearGo.AddComponent(); runner.Launch(opponent, spawnPos, totalDamage, unit, spearSpeed, level, knockbackDistance); Debug.Log($"【穿心猎矛】破空投出! 目标: {opponent.name}, 基础倍率: {baseMultiplier * 100:F0}%, 距离加成: +{distanceBonus * 100:F0}%, 最终伤害: {totalDamage:F1} (等级: {level})"); } /// /// 寻找全场距离自身最远的存活敌方目标 /// private GameObject FindFurthestEnemy() { if (unit == null) return null; UnitTeam myTeam = unit.GetComponent(); var allTeams = Object.FindObjectsOfType(); GameObject furthestEnemy = null; float maxDistanceSq = -1f; Vector3 myPos = unit.transform.position; foreach (var t in allTeams) { if (t == null || !t.gameObject.activeInHierarchy) continue; bool isEnemy = (myTeam != null && myTeam.IsEnemy(t.gameObject)) || (unit.CompareTag("Friend") && (t.CompareTag("Enemy") || t.gameObject.name.Contains("小怪") || t.gameObject.name.Contains("敌方"))); if (!isEnemy) continue; var targetUnit = t.GetComponentInParent(); if (targetUnit != null && targetUnit.IsDead) continue; var bar = t.GetComponentInParent(); if (bar != null && bar.IsDead) continue; GameObject enemyGo = targetUnit != null ? targetUnit.gameObject : t.gameObject; float distSq = (enemyGo.transform.position - myPos).sqrMagnitude; if (distSq > maxDistanceSq) { maxDistanceSq = distSq; furthestEnemy = enemyGo; } } return furthestEnemy != null ? furthestEnemy : unit.Target; } private void OnSkillAnimationFinished() { isSkillPending = false; } private void OnDestroy() { isSkillPending = false; } } /// /// 负责技能重矛的抛物线飞行、目标命中、距离伤害结算、6级后仰击退与10级击杀返还能量 /// public class WildHunterSpearRunner : MonoBehaviour { private GameObject target; private float damage; private UnitBase ownerUnit; private float speed; private int skillLevel; private float knockbackDist; private bool hasHit = false; private Vector3 startPosition; private float totalDistance; private float traveledDistance; public void Launch(GameObject targetObj, Vector3 startPos, float totalDmg, UnitBase owner, float moveSpeed, int level, float kbDist) { target = targetObj; damage = totalDmg; ownerUnit = owner; speed = moveSpeed > 5f ? moveSpeed : 18f; skillLevel = level; knockbackDist = kbDist; // 接管飞行,禁用自带的普通直线 Projectile 组件 var defaultProj = GetComponent(); if (defaultProj != null) defaultProj.enabled = false; startPosition = startPos; traveledDistance = 0f; if (targetObj != null) { Vector3 diff = targetObj.transform.position - startPosition; diff.y = 0f; totalDistance = Mathf.Max(0.5f, diff.magnitude); } else { totalDistance = 10f; } Destroy(gameObject, 5f); } private void Update() { if (hasHit) return; if (target == null || !target.activeInHierarchy) { Destroy(gameObject); return; } Vector3 targetCurrentPos = target.transform.position; Vector3 offset = targetCurrentPos - transform.position; Vector3 flatOffset = new Vector3(offset.x, 0f, offset.z); float step = speed * Time.deltaTime; traveledDistance += step; if (step >= flatOffset.magnitude || flatOffset.sqrMagnitude <= 0.05f) { HitTargetAndExecuteEffects(target); return; } // 自然抛物线推进 float t = Mathf.Clamp01(traveledDistance / totalDistance); Vector3 groundPos = Vector3.Lerp(new Vector3(startPosition.x, 0.1f, startPosition.z), new Vector3(targetCurrentPos.x, 0.1f, targetCurrentPos.z), t); float startY = startPosition.y; float targetY = targetCurrentPos.y + 0.8f; float baseY = Mathf.Lerp(startY, targetY, t); float arcY = 4f * 1.35f * t * (1f - t); // 1.35m 拱起高度 Vector3 nextPos = new Vector3(groundPos.x, baseY + arcY, groundPos.z); // 矛头朝向飞行轨迹切线 Vector3 velocity = nextPos - transform.position; if (velocity.sqrMagnitude > 1e-5f) { transform.rotation = Quaternion.LookRotation(velocity.normalized, Vector3.up); } transform.position = nextPos; } private void HitTargetAndExecuteEffects(GameObject hitTarget) { if (hasHit) return; hasHit = true; UnitBase targetUnit = hitTarget.GetComponentInParent(); WorldHealthBar targetBar = hitTarget.GetComponentInParent(); if (targetBar == null && targetUnit != null) { targetBar = targetUnit.GetComponent(); } float hpBefore = targetBar != null ? targetBar.currentHealth : 0f; // 1. 造成伤害 if (targetUnit != null) { targetUnit.ReceiveDamage(damage, ownerUnit != null ? ownerUnit.gameObject : null); } else if (targetBar != null) { targetBar.TakeDamage(damage, ownerUnit != null ? ownerUnit.gameObject : null); } Debug.Log($"【穿心猎矛】命中! 目标: {hitTarget.name}, 承受伤害: {damage:F1} (目标血量: {hpBefore:F1} -> {(targetBar != null ? targetBar.currentHealth : 0f):F1})"); // 2. 6级解锁【破阵震退】:后仰强力击退 2.0 米(顺着投矛飞行方向向后推) if (skillLevel >= 6 && hitTarget != null && hitTarget.activeInHierarchy) { Vector3 pushDir = (hitTarget.transform.position - startPosition); pushDir.y = 0f; if (pushDir.sqrMagnitude < 0.001f) pushDir = Vector3.forward; pushDir.Normalize(); ApplySmoothKnockback(hitTarget, pushDir * knockbackDist); } // 3. 10级解锁【绝命猎杀】:若成功斩杀目标,立即返还 50% 技能能量 bool isKilled = (targetBar != null && (targetBar.IsDead || targetBar.currentHealth <= 0f)) || (targetUnit != null && targetUnit.IsDead); if (skillLevel >= 10 && isKilled && ownerUnit != null) { WorldHealthBar ownerBar = ownerUnit.GetComponent(); if (ownerBar != null) { // 返还 50% 能量(即 50 点技能充能) ownerBar.currentEnergy = Mathf.Clamp(ownerBar.currentEnergy + ownerBar.maxEnergy * 0.50f, 0f, ownerBar.maxEnergy); Debug.Log($"【绝命猎杀】成功斩杀后排目标! 立即返还 50% 技能能量!(当前能量: {ownerBar.currentEnergy:F0}/{ownerBar.maxEnergy:F0})"); } } Destroy(gameObject); } private void ApplySmoothKnockback(GameObject victim, Vector3 displacement) { NavMeshAgent agent = victim.GetComponent(); Vector3 targetPos = victim.transform.position + displacement; // 利用 NavMesh 采样保证不推出边界或障碍物 if (NavMesh.SamplePosition(targetPos, out NavMeshHit hit, 2.0f, NavMesh.AllAreas)) { targetPos = hit.position; } if (agent != null && agent.enabled && agent.isOnNavMesh) { agent.Warp(targetPos); } else { victim.transform.position = targetPos; } Debug.Log($"【破阵震退】触发! 目标 {victim.name} 被重矛强力震退 {displacement.magnitude:F1} 米!"); } }