| | |
| | | // 技能释放主逻辑:广播事件、高亮目标、执行释放 |
| | | public virtual void Cast() |
| | | { |
| | | #if UNITY_EDITOR |
| | | // [前冲诊断] Cast() 入口:记录 skillId/caster/BattleType/当前位置/当前是否还在 tween。 |
| | | // 用来判断新技能是否在上一个技能的回位 tween 还没完成时就进入 Cast()。 |
| | | { |
| | | Vector2 castEntryPos = (caster != null && caster.GetRectTransform() != null) |
| | | ? caster.GetRectTransform().anchoredPosition : Vector2.zero; |
| | | bool casterTweening = caster != null && caster.GetRectTransform() != null |
| | | && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform()); |
| | | BattleDebug.LogError($"[前冲诊断] Cast 入口 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} castMode={skillSkinConfig?.castMode} anchoredPos={castEntryPos} casterTweening={casterTweening}"); |
| | | } |
| | | #endif |
| | | // 广播技能释放事件 |
| | | string guid = battleField.guid; |
| | | // 获取释放者数据:Hero 传递 teamHero,Mingge 传递 null(因为事件监听器只处理 Hero 数据) |
| | |
| | | // 执行移动-施法-返回序列:通用的移动攻击流程 |
| | | private void ExecuteMoveAndCastSequence(RectTransform target, Action onReturnComplete) |
| | | { |
| | | #if UNITY_EDITOR |
| | | BattleDebug.LogError($"[前冲诊断] ExecuteMoveAndCastSequence 开始 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} CastDistance={skillSkinConfig?.CastDistance} castMode={skillSkinConfig?.castMode}"); |
| | | #endif |
| | | ShadowIllutionCreate(true); |
| | | MoveToTarget(target, new Vector2(skillSkinConfig.CastDistance, 0), () => |
| | | { |
| | | #if UNITY_EDITOR |
| | | BattleDebug.LogError($"[前冲诊断] 前冲完成 skillId={skillConfig?.SkillID} caster={caster?.ObjID} 准备 CastImpl"); |
| | | #endif |
| | | if (skillSkinConfig.CastDistance < 9999 && skillSkinConfig.SkinllSFX2 != 0) |
| | | { |
| | | battleField.soundManager.PlayEffectSound(skillSkinConfig.SkinllSFX2, false); |
| | |
| | | // 移动到目标位置:处理角色的移动动画和逻辑 |
| | | protected void MoveToTarget(RectTransform target, Vector2 offset, Action _onComplete = null, float speed = 750f) |
| | | { |
| | | #if UNITY_EDITOR |
| | | // [前冲诊断] 记录入口参数:CastDistance、offset、speed;以及当前 caster 的锚点位置。 |
| | | Vector2 fromPos = caster != null && caster.GetRectTransform() != null |
| | | ? caster.GetRectTransform().anchoredPosition : Vector2.zero; |
| | | bool mttTweening = caster != null && caster.GetRectTransform() != null |
| | | && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform()); |
| | | BattleDebug.LogError($"[前冲诊断] MoveToTarget 入口 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} CastDistance={skillSkinConfig?.CastDistance} offset={offset} speed={speed} fromPos={fromPos} casterTweening={mttTweening}"); |
| | | #endif |
| | | if (skillSkinConfig.CastDistance >= 9999) |
| | | { |
| | | #if UNITY_EDITOR |
| | | BattleDebug.LogError($"[前冲诊断] CastDistance>=9999 直接跳过移动 skillId={skillConfig?.SkillID} caster={caster?.ObjID}"); |
| | | #endif |
| | | _onComplete?.Invoke(); |
| | | return; |
| | | } |
| | | |
| | | caster.PlayAnimation(MotionName.run, true); |
| | | #if UNITY_EDITOR |
| | | // [前冲诊断] 记录 target 的名字/世界坐标/父节点 scale,便于定位镜像坐标系导致 offset 方向反转 |
| | | string targetName = target != null ? target.name : "(null)"; |
| | | Vector3 targetWorld = target != null ? target.position : Vector3.zero; |
| | | Vector3 targetLossyScale = target != null ? (Vector3)target.lossyScale : Vector3.one; |
| | | Vector2 targetAnchored = target != null ? target.anchoredPosition : Vector2.zero; |
| | | BattleDebug.LogError($"[前冲诊断] target信息 skillId={skillConfig?.SkillID} caster={caster?.ObjID} casterCamp={caster?.Camp} target.name={targetName} target.anchoredPos={targetAnchored} target.worldPos={targetWorld} target.lossyScale={targetLossyScale}"); |
| | | #endif |
| | | var tweener = BattleUtility.MoveToTarget(caster.GetRectTransform(), target, offset, () => |
| | | { |
| | | #if UNITY_EDITOR |
| | | Vector2 toPos = caster != null && caster.GetRectTransform() != null |
| | | ? caster.GetRectTransform().anchoredPosition : Vector2.zero; |
| | | BattleDebug.LogError($"[前冲诊断] MoveToTarget 完成 skillId={skillConfig?.SkillID} caster={caster?.ObjID} toPos={toPos}"); |
| | | #endif |
| | | // tween 完成时清除 caster 上的 activeMoveTween 句柄,放开 CanCastSkillAnimation 的闸门。 |
| | | if (caster != null) |
| | | { |
| | | caster.activeMoveTween = null; |
| | | } |
| | | caster.PlayAnimation(MotionName.idle, true); |
| | | _onComplete?.Invoke(); |
| | | }, speed); |
| | | // 记录到 caster,让 CanCastSkillAnimation 能精确等待这一个 tween(而不是 caster 身上任意 tween)。 |
| | | if (caster != null) |
| | | { |
| | | caster.activeMoveTween = tweener; |
| | | } |
| | | battleField.battleTweenMgr.OnPlayTween(tweener); |
| | | } |
| | | |
| | |
| | | // 攻击完成后的处理:转身、恢复状态、播放待机动画 |
| | | protected void OnAttackFinish() |
| | | { |
| | | #if UNITY_EDITOR |
| | | // [前冲诊断] OnAttackFinish 入口:记录帧号和当前位置,和 Cast()/MoveToTarget 日志对齐。 |
| | | { |
| | | Vector2 finPos = (caster != null && caster.GetRectTransform() != null) |
| | | ? caster.GetRectTransform().anchoredPosition : Vector2.zero; |
| | | bool finTweening = caster != null && caster.GetRectTransform() != null |
| | | && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform()); |
| | | BattleDebug.LogError($"[前冲诊断] OnAttackFinish skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} anchoredPos={finPos} casterTweening={finTweening}"); |
| | | } |
| | | #endif |
| | | TurnBack(null, 1f); |
| | | OnAllAttackMoveFinished(); |
| | | caster.PlayAnimation(MotionName.idle, true); |