using Sirenix.OdinInspector; using UnityEngine; public class chargeDownward : MonoBehaviour { // 状态枚举 private enum MovementState { Idle, Dashing, Breaking, Rising } private MovementState currentState = MovementState.Idle; public Enemy owner; private AttackController attackController; private Rigidbody rb; [Header("移动参数")] [LabelText("目标上升高度")] private float Height; public float targetRiseHeight = 8f; public float maxRiseHeight = 16f; public float upHeight = 4f; [LabelText("冲刺速度")] public float dashSpeed = 1f; public float riseSpeed = 1f; [LabelText("冷却时间")] public float breakDuration = 0.5f; [LabelText("冲刺方向")] public Vector3 dashDirection = Vector3.down; public Vector3 riseDirection = Vector3.up; [LabelText("能否冲刺")] public bool canDash = true; [LabelText("是否使用本地坐标")] public bool useLocalSpace = true; [Header("力控制")] [LabelText("阻尼系数")] public float drag = 0.5f; [LabelText("最大速度")] public float maxSpeed = 30f; public GameObject foot; public GameObject waterRing; [Header("碰撞检测")] [LabelText("地面层")] public LayerMask groundLayer; [LabelText("检测半径")] public float groundCheckRadius = 0.2f; [LabelText("地面检测点")] public Transform groundCheckPoint; private Vector3 riseStartPosition; // 记录上升起始位置,用于计算相对高度 private float breakStartTime; // 冷却开始时间 private Vector3 targetVelocity = Vector3.zero; void Awake() { Height = targetRiseHeight; attackController = GetComponent(); rb = GetComponent(); } public void Update() { if (owner.state != CharacterState.Attack) { StopAllMovements(); if (owner.state == CharacterState.Rise) { foot.GetComponent().trigGroundList.Clear(); foot.SetActive(false); } else { foot.SetActive(true); } return; } switch (currentState) { case MovementState.Idle: if (attackController.isAttackTriggerOn && canDash) { StartDash(); currentState = MovementState.Dashing; } else if (!canDash && !attackController.isAttackTriggerOn) { StartRise(); currentState = MovementState.Rising; } break; case MovementState.Dashing: UpdateDashing(); break; case MovementState.Breaking: UpdateBreaking(); break; case MovementState.Rising: UpdateRising(); break; } } private void FixedUpdate() { if (currentState == MovementState.Dashing || currentState == MovementState.Rising) { Vector3 desiredVelocity = targetVelocity - rb.velocity; float forceMagnitude = (currentState == MovementState.Dashing) ? dashSpeed : riseSpeed; Vector3 force = desiredVelocity * forceMagnitude; if (rb.velocity.magnitude < maxSpeed || Vector3.Dot(rb.velocity, targetVelocity) < 0) { rb.AddForce(force, ForceMode.Force); } } } public void StartDash() { foot.SetActive(false); if (IsDashing) return; IsDashing = true; canDash = false; Vector3 direction = useLocalSpace ? transform.TransformDirection(dashDirection) : dashDirection; if (direction.y > 0) direction.y = -direction.y; // 确保向下 targetVelocity = direction * dashSpeed; } private void UpdateDashing() { if (!IsDashing) return; if (IsGrounded()) { if (targetRiseHeight < maxRiseHeight) { targetRiseHeight += upHeight; owner.flyHeight = targetRiseHeight; dashSpeed *= targetRiseHeight/Height; riseSpeed *= 1+(targetRiseHeight / Height-1)/2f; } owner.ani.speed = 3.33f / breakDuration; owner.ani.Play("attack_fall", 0, 0); IsDashing = false; isBreaking = true; breakStartTime = Time.time; currentState = MovementState.Breaking; rb.velocity = Vector3.zero; return; } //Vector3 direction = useLocalSpace ? transform.TransformDirection(dashDirection) : dashDirection; //if (direction.y > 0) direction.y = -direction.y; //targetVelocity = direction * dashSpeed; } public void StartRise() { if (IsRising || isBreaking) return; riseStartPosition = transform.position; // 记录上升起点 IsRising = true; owner.ani.speed = 1f; owner.ani.Play("walk", 0, 0); Vector3 direction = useLocalSpace ? transform.TransformDirection(riseDirection) : riseDirection; if (direction.y < 0) direction.y = -direction.y; // 确保向上 targetVelocity = direction * riseSpeed; } private void UpdateRising() { if (!IsRising) return; float heightDifference = Mathf.Abs(transform.position.y - targetRiseHeight); if (heightDifference < 1f) { IsRising = false; canDash = true; currentState = MovementState.Idle; owner.ChangeState(CharacterState.Idle); foot.GetComponent().trigGroundList.Clear(); foot.SetActive(true); return; } //// 持续更新上升方向和速度 //Vector3 direction = useLocalSpace ? transform.TransformDirection(riseDirection) : riseDirection; //if (direction.y < 0) direction.y = -direction.y; //targetVelocity = direction * riseSpeed; } private void UpdateBreaking() { if (!isBreaking) return; if (Time.time - breakStartTime >= breakDuration) { isBreaking = false; currentState = MovementState.Idle; } } public void StopAllMovements() { IsDashing = false; IsRising = false; isBreaking = false; currentState = MovementState.Idle; } private bool IsGrounded() { if (Physics.CheckSphere(groundCheckPoint.position, groundCheckRadius, LayerMask.GetMask("Ground"))) { GameObject Fx =PoolManager.Instantiate(waterRing); Fx.transform.position = new Vector3(this.transform.position.x, 0, transform.position.z); ParticleSystem water = Fx.GetComponent(); water.Play(); } return Physics.CheckSphere(groundCheckPoint.position, groundCheckRadius, groundLayer); } public bool IsDashing { get; private set; } public bool IsRising { get; private set; } [ShowInInspector, ReadOnly] private bool isBreaking; }