using System.Collections.Generic; using Core.Audio; using Core.Triiger; using Core.Utility; using GameLogic.Combat.CombatTool; using GameLogic.Combat.Hero; using GameLogic.Combat.Skill; using UnityEditor; using UnityEngine; using UTool.CustomizeTimeLogic.FxLogic.TimeLineEventinterface; namespace Common.Combat.FxAILogic { [AddComponentMenu("特效脚本/弹道/功法通用弹道")] public class FxParabolaBulletLogic : FxAILogicBasic { public float speed; private IUnRegister UnRegister = null; public enum CurveType { DynamicCurve, Beeline, CustomizeCurve, } [Header("曲线类型")] public CurveType parabolaCurveType; [Header("释放碰撞到地面时结束")] public bool isTriggerGroundEnd; [Header("碰撞到地面时的特效")] public string GroundHitFxName; [Header("是否使用X曲线跟随角色")] public bool isUseX; [Header("自定义曲线")] public BesselPath BesselPath; private Vector3 endPos; private Vector3 dir; public float maxDis = 20; protected float maxDisSpr; // private BesselPath _besselPath; protected BesselPath moveBezierPath; private float _addTime; protected Vector3 startDir; private float dirLerpTime; protected override void ProInit() { maxDisSpr = maxDis * maxDis; UnRegister = gameObject.OnTriggerEnterEvent(this, OnTriggerEnterEvent); if (isUseCustomTargetEndPos) { endPos = TimeLineEventParticleLogicBasic.customizePos[ customTargetEndPosIndex]; } else { endPos = AttTarget.GetSpecialDotInfo("hitpos").GetWorlPos(); // endPos = new Vector3(endPos.x, CurrPos.y, endPos.z); } if (parabolaCurveType == CurveType.DynamicCurve) { Vector3 off = _currPos - CombatHeroEntity.GameObject.transform.position; float x = Mathf.Sign(Random.Range(-1, 1)); if (isUseX) { Vector3 pos = CombatHeroEntity.GameObject.transform.InverseTransformPoint(gameObject.transform.position); x = Mathf.Sign(pos.x); } startDir = CombatHeroEntity.GameObject.transform.TransformPoint(off + new Vector3( x, Random.Range(0.1f, 1f), Random.Range(0.1f, 5f))); startDir = (startDir - _currPos).normalized; dirLerpTime = 0; dir = (endPos - CurrPos).normalized; gameObject.transform.rotation = Quaternion.LookRotation(dir); } else if (parabolaCurveType == CurveType.Beeline) { dir = (endPos - _currPos).normalized; gameObject.transform.rotation = Quaternion.LookRotation(dir); } else if (parabolaCurveType == CurveType.CustomizeCurve) { gameObject.transform.rotation = CombatHeroEntity.GameObject.transform.rotation; Vector3 pos = CombatHeroEntity.GameObject.transform.InverseTransformPoint(gameObject.transform.position); if (moveBezierPath == null) { moveBezierPath = new BesselPath(); } moveBezierPath.controlPoints.Clear(); for (int i = 0; i < BesselPath.controlPoints.Count; i++) { Vector3 p = BesselPath.controlPoints[i]; if (isUseX) { if (i == 1) { p.x = pos.x > 0 ? p.x * -1 : p.x; } } moveBezierPath.controlPoints.Add(gameObject.transform.TransformPoint(p / (size * size))); } moveBezierPath.SetLengthAtT(); currTime = 0; } } private float GetMoveSpeed() { float v = speed * extraMoveSpeed; return speed + v; } void TriggerGround() { ITimeLineTriggerEvent timeLineTriggerEvent = TimeLineEventParticleLogicBasic.ITimeLineTriggerEntity as ITimeLineTriggerEvent; FinishHit(new Vector3(_currPos.x, 0.5f, _currPos.z), GroundHitFxName); AudioManager.Instance.PlayAudio(hitAudioName, false); if (timeLineTriggerEvent != null) { timeLineTriggerEvent.TimeLineTriggerGround( TimeLineEventParticleLogicBasic.TimeLineEventLogicGroup.groupName, this, triggerData); } AudioManager.Instance.PlayAudio(hitAudioName, false); Dispose(); } protected void GetTargetPos() { if (isUseCustomTargetEndPos) { endPos = TimeLineEventParticleLogicBasic.customizePos[ customTargetEndPosIndex]; } else { endPos = AttTarget.GetSpecialDotInfo("hitpos").GetWorlPos(); // endPos = new Vector3(endPos.x, CurrPos.y, endPos.z); } } protected void OnTriggerEnterEvent(Collider collision, ITriggerEntity triggerEntity) { if (isTriggerGroundEnd) { if (collision.gameObject.CompareTag("dimian")) { TriggerGround(); return; } } FxAILogicBasic fxAILogicBasic = triggerEntity as FxAILogicBasic; if (fxAILogicBasic != null) //击中其他的功法 { SkillFeaturesData skillFeaturesData = fxAILogicBasic.SkillFeaturesData; if (skillFeaturesData.isEnemy == SkillFeaturesData.isEnemy) { return; } CombatCalculateTool.Instance.GongFaPengZhuang(SkillFeaturesData, skillFeaturesData, CombatHeroEntity, fxAILogicBasic.CombatHeroEntity); if (SkillFeaturesData.hp > 0) { fxAILogicBasic.PlayHit(); fxAILogicBasic.Dispose(); } else if (skillFeaturesData.hp > 0) { Dispose(); PlayHit(); } else { fxAILogicBasic.PlayHit(); fxAILogicBasic.Dispose(); Dispose(); PlayHit(); } return; } else { HeroEntityMono heroEntityMono = collision.gameObject.GetComponent(); if (heroEntityMono != null) { TriggerHero(collision, heroEntityMono); return; } BarrierEntityMono barrierEntityMono = collision.gameObject.GetComponent(); if (barrierEntityMono != null) { TriggerBarrier(collision, barrierEntityMono); } } } protected void TriggerBarrier(Collider collision, BarrierEntityMono barrierEntityMono) { if (barrierEntityMono == null) { return; } CombatHeroEntity target = barrierEntityMono.Barrier.Own as CombatHeroEntity; if (target.IsEnemy == CombatHeroEntity.IsEnemy || target is CombatMagicWeaponEntity) { return; } if (TimeLineEventParticleLogicBasic.TimeLineEventLogicGroup.groupName == null) { Dispose(); return; } bool isOk = barrierEntityMono.Barrier.CollideTriiger(this); if (!isOk) //被主档 { triggerData.IBarrier = barrierEntityMono.Barrier; ITimeLineTriggerEvent timeLineTriggerEvent = TimeLineEventParticleLogicBasic.ITimeLineTriggerEntity as ITimeLineTriggerEvent; if (timeLineTriggerEvent != null) { timeLineTriggerEvent.TimeLineTrigger( TimeLineEventParticleLogicBasic.TimeLineEventLogicGroup.groupName, target.GetMainHotPoin(), this, triggerData); if (!string.IsNullOrEmpty(hitFxName)) { FinishHit(collision.ClosestPoint(gameObject.transform.position), hitFxName); } AudioManager.Instance.PlayAudio(hitAudioName, false); if (!isPenetrate) { Dispose(); } } } } protected void TriggerHero(Collider collision, HeroEntityMono heroEntityMono) { if (heroEntityMono == null) { return; } CombatHeroEntity target = heroEntityMono.combatHeroEntity; if (target.IsEnemy == CombatHeroEntity.IsEnemy || target is CombatMagicWeaponEntity) { return; } if (TimeLineEventParticleLogicBasic.TimeLineEventLogicGroup.groupName == null) { Dispose(); return; } ITimeLineTriggerEvent timeLineTriggerEvent = TimeLineEventParticleLogicBasic.ITimeLineTriggerEntity as ITimeLineTriggerEvent; if (timeLineTriggerEvent != null) { timeLineTriggerEvent.TimeLineTrigger(TimeLineEventParticleLogicBasic.TimeLineEventLogicGroup.groupName, target.GetMainHotPoin(), this, triggerData); if (!string.IsNullOrEmpty(hitFxName)) { FinishHit(collision.ClosestPoint(gameObject.transform.position), hitFxName); } AudioManager.Instance.PlayAudio(hitAudioName, false); if (!isPenetrate) { Dispose(); } } } private void FinishHit(Vector3 pos, string hitFxName) { if (!string.IsNullOrEmpty(hitFxName)) { CombatController.currActiveCombat.GameTimeLineParticleFactory.CreateParticle(hitFxName, pos, null, false, null, null); } } protected override void ProCombatUpdate(float time) { switch (parabolaCurveType) { case CurveType.Beeline: Beeline(time); break; case CurveType.DynamicCurve: DynamicCurve(time); break; case CurveType.CustomizeCurve: CustomizeCurve(time); break; } // if (Vector3.Distance(endPos, _currPos) < 0.5f) // { // Dispose(); // } } private void Beeline(float time) { GetTargetPos(); Vector3 dir = (endPos - _currPos).normalized; // dir = Vector3.Lerp(startDir, dir, dirLerpTime).normalized; // startDir= dir; Vector3 lasetPos = _currPos; _currPos += dir * GetMoveSpeed() * time; gameObject.transform.position = _currPos; gameObject.transform.rotation = Quaternion.LookRotation(dir); } private void CustomizeCurve(float time) { _addTime = 1.0f / (moveBezierPath.allDis / GetMoveSpeed()); currTime += _addTime * time; GetTargetPos(); moveBezierPath.controlPoints[3] = endPos; // moveBezierPath.controlPoints[0] = (gameObject.transform.TransformPoint(BesselPath.controlPoints[0])); Vector3 p = moveBezierPath.CalculatePoint(currTime); Vector3 p2 = moveBezierPath.CalculatePoint(currTime - 0.01f); gameObject.transform.position = p; gameObject.transform.rotation = Quaternion.LookRotation((p - p2).normalized); } private void DynamicCurve(float time) { dirLerpTime += time * 4F; if (dirLerpTime > 1) { dirLerpTime = 1; } GetTargetPos(); Vector3 dir = (endPos - _currPos).normalized; dir = Vector3.Lerp(startDir, dir, dirLerpTime).normalized; // startDir= dir; Vector3 lasetPos = _currPos; _currPos += dir * GetMoveSpeed() * time; gameObject.transform.position = _currPos; gameObject.transform.rotation = Quaternion.LookRotation(dir); } protected override void ProDispose() { if (UnRegister != null) { UnRegister.UnRegister(); } UnRegister = null; } private void OnDrawGizmos() { if (parabolaCurveType != CurveType.CustomizeCurve) { return; } if (BesselPath.controlPoints.Count < 4) { BesselPath.controlPoints.Add(Vector3.zero); BesselPath.controlPoints.Add(new Vector3(-1, 1, -1)); BesselPath.controlPoints.Add(new Vector3(0, 0, 2)); BesselPath.controlPoints.Add(new Vector3(0, 0, 5)); return; } Gizmos.color = Color.blue; // 绘制控制点 // 绘制曲线 Vector3 previousPoint = BesselPath.CalculatePoint(0) + transform.position; int segments = 50; for (int i = 1; i <= segments; i++) { float t = i / (float)segments; Vector3 currentPoint = BesselPath.CalculatePoint(t) + transform.position; // Gizmos.DrawSphere(currentPoint, 0.03f); Gizmos.DrawLine(previousPoint, currentPoint); previousPoint = currentPoint; } } #if UNITY_EDITOR [CustomEditor(typeof(FxParabolaBulletLogic))] public class MovableCoordinateEditor : Editor { void OnSceneGUI() { FxParabolaBulletLogic fxParabolaBulletLogic = target as FxParabolaBulletLogic; if (fxParabolaBulletLogic.parabolaCurveType != CurveType.CustomizeCurve) { return; } if (fxParabolaBulletLogic.BesselPath.controlPoints.Count < 4) { return; } // 使用 Handles.PositionHandle 提供一个可拖动的控制柄 for (int i = 0; i < fxParabolaBulletLogic.BesselPath.controlPoints.Count; i++) { EditorGUI.BeginChangeCheck(); Vector3 newPosition = Handles.PositionHandle( fxParabolaBulletLogic.BesselPath.controlPoints[i] + fxParabolaBulletLogic.gameObject.transform.position, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(fxParabolaBulletLogic, "Move Coordinate"); fxParabolaBulletLogic.BesselPath.controlPoints[i] = newPosition - fxParabolaBulletLogic.gameObject.transform.position; } } } } #endif } }