又是吹DeepSeek的一天,让他帮我写游戏

标题1111

在这里插入图片描述

以下是基于Unity实现的MoveCurve脚本,允许物体沿三次贝塞尔曲线移动,并提供场景中的可视化路径:

using UnityEngine;

[RequireComponent(typeof(Transform))]
public class MoveCurve : MonoBehaviour
{
    
    
    [Header("Control Points")]
    [Tooltip("Control points for the cubic Bezier curve (4 required)")]
    public Transform[] controlPoints;

    [Header("Movement Settings")]
    [Tooltip("Duration of the movement in seconds")]
    public float duration = 3f;
    [Tooltip("Whether to loop the movement")]
    public bool loop = true;
    [Tooltip("Rotate object to face movement direction")]
    public bool faceMovementDirection = false;

    private float elapsedTime;
    private Vector3 previousPosition;

    void Start()
    {
    
    
        ValidateControlPoints();
        previousPosition = transform.position;
    }

    void Update()
    {
    
    
        if (controlPoints.Length < 4) return;

        elapsedTime += Time.deltaTime;
        float t = Mathf.Clamp01(elapsedTime / duration);

        UpdatePosition(t);
        HandleRotation();

        if (t >= 1f) HandleCompletion();
    }

    private void UpdatePosition(float t)
    {
    
    
        Vector3 newPosition = CalculateBezierPoint(t,
            controlPoints[0].position,
            controlPoints[1].position,
            controlPoints[2].position,
            controlPoints[3].position);

        transform.position = newPosition;
    }

    private void HandleRotation()
    {
    
    
        if (faceMovementDirection)
        {
    
    
            Vector3 direction = transform.position - previousPosition;
            if (direction != Vector3.zero)
            {
    
    
                transform.rotation = Quaternion.LookRotation(direction);
            }
            previousPosition = transform.position;
        }
    }

    private void HandleCompletion()
    {
    
    
        if (loop)
        {
    
    
            elapsedTime = 0f;
        }
        else
        {
    
    
            enabled = false;
        }
    }

    private Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
    {
    
    
        float u = 1 - t;
        float uu = u * u;
        float uuu = uu * u;
        float tt = t * t;
        float ttt = tt * t;

        return uuu * p0 + 
               3 * uu * t * p1 + 
               3 * u * tt * p2 + 
               ttt * p3;
    }

    private void ValidateControlPoints()
    {
    
    
        if (controlPoints == null || controlPoints.Length < 4)
        {
    
    
            Debug.LogError("MoveCurve requires 4 control points!");
            enabled = false;
        }
    }

    void OnDrawGizmos()
    {
    
    
        if (controlPoints == null || controlPoints.Length < 4) return;

        Gizmos.color = Color.green;
        const int segments = 20;
        Vector3 prevPoint = controlPoints[0].position;

        for (int i = 1; i <= segments; i++)
        {
    
    
            float t = i / (float)segments;
            Vector3 currentPoint = CalculateBezierPoint(t,
                controlPoints[0].position,
                controlPoints[1].position,
                controlPoints[2].position,
                controlPoints[3].position);

            Gizmos.DrawLine(prevPoint, currentPoint);
            prevPoint = currentPoint;
        }
    }
}

使用说明:

  1. 将脚本附加到需要移动的游戏对象上
  2. 在Inspector中配置:
    • Control Points:拖入4个控制点的Transform(按顺序:起点、控制点1、控制点2、终点)
    • Duration:完成整个路径所需时间(秒)
    • Loop:是否循环移动
    • Face Movement Direction:是否让物体面向移动方向
  3. 在Scene视图中可以看到绿色的路径预览线

功能特点:

  1. 基于三次贝塞尔曲线的平滑移动
  2. 可调节移动速度和循环模式
  3. 实时场景路径可视化
  4. 可选的面朝移动方向功能
  5. 自动参数验证和错误处理

扩展建议:

  1. 要创建更复杂的路径,可以:

    • 在场景中排列多个贝塞尔曲线段
    • 使用空物体作为路径节点
    • 添加多个MoveCurve组件并顺序激活
  2. 要添加匀速移动支持,可以通过:

    • 预计算曲线长度
    • 建立弧长参数化表
    • 调整时间参数t基于实际移动距离
  3. 要创建自定义编辑器工具:

    • 添加路径自动生成功能
    • 创建控制点自动布局系统
    • 添加速度曲线编辑功能

该实现提供了基础的曲线移动功能,开发者可以根据具体需求进行扩展和定制。

2222

在这里插入图片描述
以下是封装后的独立曲线移动系统实现,分为核心逻辑类和MonoBehaviour适配器:

using UnityEngine;
using System;

/// <summary>
/// 三次贝塞尔曲线移动系统(非MonoBehaviour)
/// </summary>
public class CubicBezierMover
{
    
    
    #region 配置参数
    public Vector3[] ControlPoints {
    
     get; private set; }
    public float Duration {
    
     get; set; } = 3f;
    public bool IsLooping {
    
     get; set; } = true;
    public bool FaceMovementDirection {
    
     get; set; } = false;
    #endregion

    #region 运行时状态
    private float elapsedTime;
    private bool isMoving;
    private Vector3 previousPosition;
    private Action<Vector3> positionUpdater;
    private Action<Quaternion> rotationUpdater;
    #endregion

    #region 事件
    public event Action OnMovementStarted;
    public event Action OnMovementCompleted;
    public event Action OnLoopCompleted;
    #endregion

    /// <summary>
    /// 初始化移动器
    /// </summary>
    /// <param name="controlPoints">四个控制点(起点、控制点1、控制点2、终点)</param>
    /// <param name="positionUpdater">位置更新回调</param>
    /// <param name="rotationUpdater">旋转更新回调(可选)</param>
    public CubicBezierMover(Vector3[] controlPoints, 
                          Action<Vector3> positionUpdater,
                          Action<Quaternion> rotationUpdater = null)
    {
    
    
        ValidateControlPoints(controlPoints);
        ControlPoints = controlPoints;
        this.positionUpdater = positionUpdater;
        this.rotationUpdater = rotationUpdater;
    }

    /// <summary>
    /// 开始/继续移动
    /// </summary>
    public void BeginMovement()
    {
    
    
        isMoving = true;
        OnMovementStarted?.Invoke();
    }

    /// <summary>
    /// 暂停移动
    /// </summary>
    public void PauseMovement()
    {
    
    
        isMoving = false;
    }

    /// <summary>
    /// 重置移动状态
    /// </summary>
    public void ResetMovement()
    {
    
    
        elapsedTime = 0f;
        previousPosition = GetPosition(0);
        UpdateTransform(0);
    }

    /// <summary>
    /// 更新移动逻辑
    /// </summary>
    /// <param name="deltaTime">时间增量(秒)</param>
    public void UpdateMovement(float deltaTime)
    {
    
    
        if (!isMoving || ControlPoints.Length < 4) return;

        elapsedTime += deltaTime;
        float t = Mathf.Clamp01(elapsedTime / Duration);

        UpdateTransform(t);

        if (t >= 1f)
        {
    
    
            HandleCompletion();
        }
    }

    #region 核心逻辑
    private void UpdateTransform(float t)
    {
    
    
        Vector3 newPos = CalculateBezierPoint(t);
        positionUpdater?.Invoke(newPos);

        if (FaceMovementDirection && rotationUpdater != null)
        {
    
    
            UpdateRotation(newPos);
        }
    }

    private void UpdateRotation(Vector3 newPosition)
    {
    
    
        Vector3 direction = newPosition - previousPosition;
        if (direction != Vector3.zero)
        {
    
    
            rotationUpdater?.Invoke(Quaternion.LookRotation(direction));
        }
        previousPosition = newPosition;
    }

    private void HandleCompletion()
    {
    
    
        OnLoopCompleted?.Invoke();

        if (IsLooping)
        {
    
    
            elapsedTime = 0f;
        }
        else
        {
    
    
            isMoving = false;
            OnMovementCompleted?.Invoke();
        }
    }

    public Vector3 GetPosition(float t)
    {
    
    
        return CalculateBezierPoint(Mathf.Clamp01(t));
    }

    private Vector3 CalculateBezierPoint(float t)
    {
    
    
        float u = 1 - t;
        float uu = u * u;
        float uuu = uu * u;
        float tt = t * t;
        float ttt = tt * t;

        return 
            uuu * ControlPoints[0] + 
            3 * uu * t * ControlPoints[1] + 
            3 * u * tt * ControlPoints[2] + 
            ttt * ControlPoints[3];
    }
    #endregion

    #region 校验方法
    private void ValidateControlPoints(Vector3[] points)
    {
    
    
        if (points == null || points.Length != 4)
        {
    
    
            throw new ArgumentException("贝塞尔曲线需要4个控制点");
        }
    }
    #endregion
}

/// <summary>
/// MonoBehaviour适配器组件(可选)
/// </summary>
public class BezierMoverComponent : MonoBehaviour
{
    
    
    [Header("控制点")]
    [Tooltip("按顺序:起点、控制点1、控制点2、终点")]
    public Transform[] controlTransforms;

    [Header("移动设置")]
    public float duration = 3f;
    public bool loop = true;
    public bool faceMovementDirection = false;

    private CubicBezierMover mover;

    void Start()
    {
    
    
        InitializeMover();
    }

    void Update()
    {
    
    
        if (mover != null)
        {
    
    
            // 更新控制点实际位置
            Vector3[] points = new Vector3[4];
            for (int i = 0; i < 4; i++) 
            {
    
    
                points[i] = controlTransforms[i].position;
            }
            mover.ControlPoints = points;

            mover.UpdateMovement(Time.deltaTime);
        }
    }

    private void InitializeMover()
    {
    
    
        if (controlTransforms.Length != 4)
        {
    
    
            Debug.LogError("需要4个控制点");
            enabled = false;
            return;
        }

        Vector3[] points = new Vector3[4];
        for (int i = 0; i < 4; i++)
        {
    
    
            points[i] = controlTransforms[i].position;
        }

        mover = new CubicBezierMover(
            points,
            UpdatePosition,
            faceMovementDirection ? UpdateRotation : null
        );

        mover.Duration = duration;
        mover.IsLooping = loop;
        mover.FaceMovementDirection = faceMovementDirection;

        mover.OnMovementStarted += () => Debug.Log("移动开始");
        mover.OnMovementCompleted += () => Debug.Log("移动完成");
        mover.OnLoopCompleted += () => Debug.Log("循环完成");

        mover.BeginMovement();
    }

    private void UpdatePosition(Vector3 newPosition)
    {
    
    
        transform.position = newPosition;
    }

    private void UpdateRotation(Quaternion newRotation)
    {
    
    
        transform.rotation = newRotation;
    }

    // 示例控制方法
    public void Pause() => mover.PauseMovement();
    public void Resume() => mover.BeginMovement();
    public void Restart() => mover.ResetMovement();
}

/// <summary>
/// 路径可视化组件(独立)
/// </summary>
public class BezierPathVisualizer : MonoBehaviour
{
    
    
    public CubicBezierMover mover;
    public int resolution = 20;
    public Color pathColor = Color.green;

    void OnDrawGizmos()
    {
    
    
        if (mover == null || mover.ControlPoints == null) return;

        Gizmos.color = pathColor;
        Vector3 prevPoint = mover.ControlPoints[0];

        for (int i = 1; i <= resolution; i++)
        {
    
    
            float t = i / (float)resolution;
            Vector3 currentPoint = mover.GetPosition(t);
            Gizmos.DrawLine(prevPoint, currentPoint);
            prevPoint = currentPoint;
        }
    }
}

结构说明

  1. CubicBezierMover(核心逻辑类)

    • 完全独立,不继承MonoBehaviour
    • 通过构造函数注入:
      • 控制点(Vector3数组)
      • 位置更新回调
      • 可选旋转更新回调
    • 提供完整控制接口:
      • BeginMovement() 开始/继续移动
      • PauseMovement() 暂停
      • ResetMovement() 重置
      • UpdateMovement() 手动更新
  2. BezierMoverComponent(适配器组件)

    • 处理与Unity的集成
    • 提供Inspector配置界面
    • 自动转换Transform控制点为Vector3数组
    • 示例事件处理
  3. BezierPathVisualizer(独立可视化组件)

    • 可附加到任意物体
    • 自动绘制贝塞尔曲线路径

使用方式

纯代码调用示例:

// 初始化控制点
Vector3[] points = new Vector3[] {
    
    
    new Vector3(0,0,0),
    new Vector3(1,2,0),
    new Vector3(3,2,0),
    new Vector3(4,0,0)
};

// 创建移动器
var mover = new CubicBezierMover(
    points,
    pos => Debug.Log($"新位置:{
      
      pos}"),  // 位置更新回调
    rot => Debug.Log($"新旋转:{
      
      rot}")   // 旋转更新回调
);

// 配置参数
mover.Duration = 5f;
mover.IsLooping = true;

// 订阅事件
mover.OnMovementStarted += () => Debug.Log("移动开始");
mover.OnLoopCompleted += () => Debug.Log("完成一次循环");

// 开始移动
mover.BeginMovement();

// 在游戏循环中更新
void Update()
{
    
    
    mover.UpdateMovement(Time.deltaTime);
}

组件化使用:

  1. BezierMoverComponent附加到游戏对象
  2. 在Inspector中配置控制点
  3. 可选附加BezierPathVisualizer用于路径可视化

优势特点

  1. 关注点分离

    • 核心算法与Unity解耦
    • 可视化与逻辑分离
    • 更新机制可自定义
  2. 灵活调用方式

    • 可完全代码驱动
    • 可通过组件快速集成
    • 支持多实例并行
  3. 扩展性强

    • 方便添加匀速移动算法
    • 容易实现路径拼接
    • 可结合其他移动系统
  4. 线程安全设计

    • 无Unity API依赖
    • 核心类可在非主线程使用(需自行处理位置同步)
  5. 事件驱动架构

    • 提供完整生命周期事件
    • 支持多订阅者模式

扩展建议

  1. 添加匀速移动支持
public class CubicBezierMover
{
    
    
    // 在类中添加以下成员
    private bool useConstantSpeed = false;
    private AnimationCurve arcLengthMap;

    public void EnableConstantSpeed()
    {
    
    
        // 预计算弧长参数化表
        // 创建时间t到实际弧长的映射
        // 在UpdateMovement中使用映射表转换时间参数
    }
}
  1. 实现路径拼接
public class CompositePathMover
{
    
    
    private List<CubicBezierMover> segments;
    private int currentSegment;

    public void AddSegment(CubicBezierMover segment)
    {
    
    
        segment.OnMovementCompleted += () => {
    
    
            currentSegment++;
            if(currentSegment < segments.Count){
    
    
                segments[currentSegment].BeginMovement();
            }
        };
    }
}
  1. 添加编辑器扩展
#if UNITY_EDITOR
[CustomEditor(typeof(BezierMoverComponent))]
public class BezierMoverEditor : Editor
{
    
    
    void OnSceneGUI()
    {
    
    
        // 添加控制点手柄
        // 实现路径实时编辑
    }
}
#endif