首先在unity assets获取喜欢的角色和动画选择好后保存到自己的assets在unity编辑器界面选择window/package manager进行下载和导入。如此这些资源会在你的项目文件夹中可以随意使用其次把人物放在场景中并添加人物动画通过键盘控制其前后左右移动再导入的npc文件夹中找到prefabs选择一个人物放在你的unity场景内。人物放进去后可以通过unity修改其外观颜色但是衣服发型等只能用你下载好的资源。但是这个时候人物是没办法受控制移动的。要想人物自然移动还需要添加人物的动画animator controller否则的话人物只会在场景“漂移”。首先选择你需要修改的人物在其inspector界面添加组件animator。这时候的animator controller显示为none需要自己搭建一个自己需要的controller。在animator界面拖入下载的动画资源里的人物动作。我先拖入了idle和walk_forward进行测试查看效果拖入后使idle为默认状态walk和idle直接用双箭头链接起来右键选择make transition链接并添加一个参数为bool IsWalking。把该animator挂载在需要控制的人物上。最后写一个控制脚本挂载在被控人物上。【可借助ai完成】测试通过后我希望通过键盘控制人物前后左右的移动不再简单的只能向前。这时候在animator新建一个状态选择blend tree命名为locomotion。在animator添加变量float MoverX 和float MoverZ。将entry连接到locomotionidle链接到locomotion。进入blend tree按照一下图像进行设置。motion选择的都是下载的人物动作资源。人物挂载的控制脚本实现了键盘wasd控制人物在环境中的“行走”using UnityEngine; public class NPCMove : MonoBehaviour { public float speed 2f; private Animator animator; void Start() { animator GetComponentAnimator(); } void Update() { // 获取输入 float moveX Input.GetAxis(Horizontal); // A/D 或 左/右 float moveZ Input.GetAxis(Vertical); // W/S 或 前/后 // 传入 Animator animator.SetFloat(MoveX, moveX); animator.SetFloat(MoveZ, moveZ); // 移动人物 Vector3 move new Vector3(moveX, 0, moveZ); if (move.magnitude 0.01f) // 有输入才移动 { transform.Translate(move * speed * Time.deltaTime, Space.World); // 让人物朝移动方向旋转 transform.forward move; } else { // 没有输入人物静止 // Animator 会自动播放 PosX0, PosY0 的 Idle 动画 } } }最后实现人物的轨迹移动。在之前的小球轨迹控制移动的基础上增加人物控制脚本注意要对被控人物增加waypoint同样可以通过手动拖动waypoint修改曲线形状即运动的轨迹。using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterBezierMove : MonoBehaviour { public Transform wayPoint1; public Transform wayPoint2; public Transform wayPoint3; public float moveSpeed 2f; // 人物移动速度 public float lifeTime 5f; // 走完整条曲线的时间 private float t 0f; private Vector3 position0; private Vector3 position1; private Vector3 position2; private Vector3 position3; private Animator animator; void Start() { animator GetComponentAnimator(); position0 transform.position; position1 wayPoint1.position; if (wayPoint2 ! null) position2 wayPoint2.position; if (wayPoint3 ! null) position3 wayPoint3.position; } void Update() { MoveAlongBezier(); } void MoveAlongBezier() { if (t 1f) { animator.SetFloat(Speed, 0); return; } Vector3 currentPos transform.position; Vector3 nextPos; // 根据不同阶数计算曲线 if (wayPoint2 null) { nextPos BezierCurve.Point(position0, position1, t); } else if (wayPoint3 null) { nextPos BezierCurve.Point(position0, position1, position2, t); } else { nextPos BezierCurve.Point(position0, position1, position2, position3, t); } // ✅ 计算方向关键让人物朝前 Vector3 direction (nextPos - currentPos).normalized; // ✅ 移动比直接赋值更自然 transform.position Vector3.MoveTowards(currentPos, nextPos, moveSpeed * Time.deltaTime); // ✅ 朝向 if (direction ! Vector3.zero) { transform.forward direction; } // ✅ 动画控制 float speedPercent moveSpeed; animator.SetFloat(Speed, speedPercent); // ✅ 推进t t Time.deltaTime / lifeTime; } private void OnDrawGizmos() { wayPoint1 transform.Find(WayPoint1); wayPoint2 transform.Find(WayPoint2); wayPoint3 transform.Find(WayPoint3); float deltaT 0.02f; Gizmos.color Color.green; // 人物路径用绿色区分 for (float t 0; t 1; tdeltaT) { if (wayPoint2 null) { Gizmos.DrawSphere(BezierCurve.Point(transform.position, wayPoint1.position, t), 0.05f); } else if (wayPoint3 null) { Gizmos.DrawSphere(BezierCurve.Point(transform.position, wayPoint1.position, wayPoint2.position, t), 0.05f); } else { Gizmos.DrawSphere(BezierCurve.Point(transform.position, wayPoint1.position, wayPoint2.position, wayPoint3.position, t), 0.05f); } } } }这时候人物还是飘着的并没有行走的动画。新创建了一个animator添加blend tree修改代码为using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterBezierMove : MonoBehaviour { public Transform wayPoint1; public Transform wayPoint2; public Transform wayPoint3; public float moveSpeed 2f; // 人物移动速度 public float lifeTime 5f; // 走完整条曲线的时间 private float t 0f; private Vector3 position0; private Vector3 position1; private Vector3 position2; private Vector3 position3; private Animator animator; void Start() { animator GetComponentAnimator(); position0 transform.position; position1 wayPoint1.position; if (wayPoint2 ! null) position2 wayPoint2.position; if (wayPoint3 ! null) position3 wayPoint3.position; } void Update() { MoveAlongBezier(); } void MoveAlongBezier() { if (t 1f) { animator.SetFloat(SpeedX, 0); animator.SetFloat(SpeedZ, 0); return; } Vector3 currentPos transform.position; Vector3 nextPos; if (wayPoint2 null) nextPos BezierCurve.Point(position0, position1, t); else if (wayPoint3 null) nextPos BezierCurve.Point(position0, position1, position2, t); else nextPos BezierCurve.Point(position0, position1, position2, position3, t); Vector3 direction (nextPos - currentPos).normalized; // 移动人物 transform.position Vector3.MoveTowards(currentPos, nextPos, moveSpeed * Time.deltaTime); // 朝向 if (direction ! Vector3.zero) transform.forward direction; // 根据方向计算Animator参数 Vector3 localDir transform.InverseTransformDirection(direction); animator.SetFloat(SpeedX, localDir.x); animator.SetFloat(SpeedZ, localDir.z); // 推进t t Time.deltaTime / lifeTime; } private void OnDrawGizmos() { wayPoint1 transform.Find(WayPoint1); wayPoint2 transform.Find(WayPoint2); wayPoint3 transform.Find(WayPoint3); float deltaT 0.02f; Gizmos.color Color.green; // 人物路径用绿色区分 for (float t 0; t 1; tdeltaT) { if (wayPoint2 null) { Gizmos.DrawSphere(BezierCurve.Point(transform.position, wayPoint1.position, t), 0.05f); } else if (wayPoint3 null) { Gizmos.DrawSphere(BezierCurve.Point(transform.position, wayPoint1.position, wayPoint2.position, t), 0.05f); } else { Gizmos.DrawSphere(BezierCurve.Point(transform.position, wayPoint1.position, wayPoint2.position, wayPoint3.position, t), 0.05f); } } } }