You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Unity Enemy脚本使其沿弧线往复移动?

实现敌人往复弧线移动逻辑修改

问题分析

  • 原代码用Mathf.PingPong同时控制X、Y轴偏移,无法实现你需要的「Y到上限后X继续正向、Y反向;Y回起点后沿弧线返回」的独立方向逻辑
  • 直接判断y == range会因为浮点数精度误差失效,必须用范围判断
  • 用CompareTag("Ground")触发方向反转逻辑不准确,应该直接检测Y轴是否回到起始位置

修改后的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : Enemy_Damage
{
    [SerializeField] private float range;     // Y轴移动上限范围
    [SerializeField] private float speed;     // 移动速度
    [SerializeField] private float arcFactor = 1f; // 弧线弯曲系数,值越大弧线越陡

    private Vector3 startPosition;
    private bool isGoingUp = true; // 是否处于上升阶段
    private bool isReturning = false; // 是否处于返回起始点阶段
    private float journeyProgress = 0f; // 移动进度(0到1)

    private void Start()
    {
        startPosition = transform.position;
    }

    private void Update()
    {
        if (!isReturning)
        {
            // 正常移动阶段:上升→下降
            if (isGoingUp)
            {
                journeyProgress += Time.deltaTime * speed / range;
                journeyProgress = Mathf.Clamp01(journeyProgress);

                // 计算弧线位置:X随进度线性增加,Y用二次曲线模拟弧线
                float xOffset = journeyProgress * range;
                float yOffset = arcFactor * journeyProgress * (2 - journeyProgress) * range;
                transform.position = startPosition + new Vector3(xOffset, yOffset, 0);

                // 判断是否到达Y轴上限(用范围避免浮点数精度问题)
                if (journeyProgress >= 1f)
                {
                    isGoingUp = false;
                }
            }
            else
            {
                journeyProgress -= Time.deltaTime * speed / range;
                journeyProgress = Mathf.Clamp01(journeyProgress);

                // 下降阶段:X继续增加,Y随进度下降
                float xOffset = journeyProgress * range + range;
                float yOffset = arcFactor * journeyProgress * (2 - journeyProgress) * range;
                transform.position = startPosition + new Vector3(xOffset, yOffset, 0);

                // 判断是否回到地面(Y轴起始位置)
                if (journeyProgress <= 0f)
                {
                    isReturning = true;
                    journeyProgress = 0f;
                }
            }
        }
        else
        {
            // 返回起始点阶段:沿对称弧线返回
            journeyProgress += Time.deltaTime * speed / (range * 2);
            journeyProgress = Mathf.Clamp01(journeyProgress);

            // 计算返回的弧线位置,与去程对称
            float xOffset = range * 2 * (1 - journeyProgress);
            float yOffset = arcFactor * (1 - journeyProgress) * (1 + journeyProgress) * range;
            transform.position = startPosition + new Vector3(xOffset, yOffset, 0);

            // 判断是否回到起始点
            if (journeyProgress >= 1f)
            {
                isReturning = false;
                isGoingUp = true;
                journeyProgress = 0f;
            }
        }
    }
}

关键逻辑说明

  • 用journeyProgress(0-1范围)跟踪移动阶段,彻底避免浮点数直接比较的精度问题
  • 将移动拆分为三个阶段:上升(X+、Y+)→下降(X+、Y-)→返回起始点(X-、Y先+后-),通过布尔变量切换阶段
  • 用二次曲线模拟弧线运动,调整arcFactor可以改变弧线的弯曲程度
  • 所有阶段切换都用进度范围判断(journeyProgress >=1或<=0),逻辑更稳定

内容的提问来源于stack exchange,提问作者BNK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:45:27