【宝贝项目001】【开发日志001】【Unity】玩家角色的基础移动
什么?!我要开始做游戏了,那首先,当然是搞一个可以移动的角色,但是在Unity中,该怎么做角色的移动呢。
角色移动挂载的组件
首先有两个方法:
- 非物理驱动:挂上
Character Controller
自带简化的胶囊体碰撞,不受 Unity 物理引擎的力(重力、推力)控制。它的移动完全靠代码指定位移(Move()),手感极其精准、无惯性。 - 物理驱动:挂上
Rigidbody和CapsuleCollider
完全交给 Unity 物理引擎控制,靠改变速度velocity或加力AddForce来实现移动。
根据自己的需求,进行选择,这里我选择了Character Controller。
按键的绑定
在实际开发中,必须避免硬编码按键,Unity 提供了两种标准方式来同时适配键盘与手柄:
-
方案 A:旧版 Input Manager(适合快速搭建原型)
-
打开 Unity 菜单:
Edit -> Project Settings -> Input Manager。

-
展开
Axes,将Size加 1,新建一个映射项,命名为Action。 -
配置绑定:
- Positive Button:
e(键盘 E 键) - Alt Positive Button:
joystick button 3(手柄 Y 键/△ 键,根据需求设置)
- Positive Button:
-
代码中直接调用:
if (Input.GetButtonDown("Action")) { // 执行动作 }
-
-
方案 B:New Input System 插件(适合中大型项目/正式版本)
-
在 Package Manager 中安装
Input System。 -
新建一个
Input Actions资源,创建一个 Action 命名为Action。 -
为
Action添加两个 Binding:一个连键盘E键,另一个连Gamepad -> buttonNorth(手柄上方按键)。

-
在代码中通过回调或者
InputAction.WasPressedThisFrame()读取,完全无需关心输入源是手柄还是键盘。 -
需要在C#中使用,需要**勾选 Generate C# Class **噢。
调用方式inputActions . [Action Map 名称] . [Action 名称] │ │ ▼ ▼ 左侧栏 (例如 Player) 中间栏 (例如 Move / Jump)
-
New Input System 插件实践
在实现移动输入时,因为需要的是 2D Vector,而键盘按键只是0-1输入,所以需要在对应Action中,点击加号,选择 Add Up\Down\Left\Right Composite,然后将对应上下左右按键绑定上去,如下图。

New Input System 该怎么在游戏内改绑按键呢?
New Input System 原生提供了 InputActionRebindingExtensions 接口,甚至官方自带了一个 Rebind Action UI 组件,可以直接把按键重绑定绑定到 UI 按钮上。
状态机的实践
为实现玩家角色的移动控制,我选择使用状态机的方法。
这里使用状态机预加载模式,在玩家类的Awake()中先将所有状态实例化。
首先,先创建StateMachine类和IState接口,StateMachine是用来控制状态的变化的,而IState就是具体的状态。
创建玩家状态基类PlayerBaseState继承IState接口,并继承PlayerBaseState类创建玩家具有的多个类。
IState接口核心是有Enter()、Update()、Exit()这三个方法。
为了可以清晰了解自己的角色有哪种状态,会怎么变化,可以进行绘图。
镜头跟随的实践
这里使用 Cinemachine 插件。
在场景中创建Virtual Camera,然后将要跟随的对象拉入其中的Follow就好,简单易用。
Main Camera 与 Virtual Camera 是怎么联合工作的?
在 Unity 中,真正负责把画面渲染到屏幕上的,永远只有 Main Camera 上的 Camera 组件。
我们可以把它们想象成拍电影的剧组:
- Main Camera(真正发射射线的实体摄像机):就像一台昂贵的重型摄影机。场景里只需要有这唯一台真正的摄影机来画面输出。当安装了
Cinemachine后,Main Camera上会挂载一个名为Cinemachine Brain的组件。- Virtual Camera(虚拟相机):它不是真正的摄像机,它没有渲染画面的能力,本质上只是一个数据计算器 / 摄像位点。
它们联合工作的原理:
- Virtual Camera 负责计算:“我现在应该在哪个位置?镜头什么角度?FOV/正交 Size 是多少?”
- Main Camera 上的 CinemachineBrain 每帧去读取最优先的那个 Virtual Camera 的数据。
- CinemachineBrain 像一只无形的大手,强制将 Main Camera(实机)瞬间或平滑地拖动到 Virtual Camera(虚机)计算出的位置与角度上。
这样做的好处:
如果场景里有多个镜头,你只需要在不同地方放多个 Virtual Camera。切换镜头时,Main Camera 就会在 CinemachineBrain 的控制下平滑滑向新视角的 Virtual Camera,完全不需要你自己用代码写平滑位移动画。
额外内容
Unity小技巧
- 在类前加上
[RequireComponent(typeof(XXXX))]是 Unity 中的一个 类特性(Attribute),用于声明当前脚本依赖于某个组件。
当你把这个脚本挂到一个 GameObject 上时,如果该物体上没有 XXX 组件,Unity 会自动添加它,从而避免运行时报错或忘记手动添加依赖组件。 - 在变量前面加上
[head("XXX")],在Unity上会显示标题; - 在私有变量前添加
[SerializeField]属性,用于强制Unity对私有字段进行序列化。默认情况下,Unity只会序列化公共字段,但如果你希望Unity也能序列化私有字段,可以通过添加 SerializeField 属性来实现。 - 在变量上一行添加
[Tooltip("xxx")]属性,可以在Unity上这个变量看见“xxx”。 - 在变量上一行添加
[Range(0, 100)]属性,可以设定在Unity上变量范围。
C#小技巧
{ get; private set; }是 C# 中自动属性(Auto-Implemented Property)的一种写法,核心作用是实现"外部只读、内部可写"的封装效果。- C# 变量后面加 ? 再调用函数
这是 C# 6.0 引入的 空条件运算符(Null-Conditional Operator),语法是 ?.
如果变量不为 null,正常调用方法;如果变量为 null,直接跳过,不会抛出 NullReferenceException 异常。 public int a => b.c简短的封装属性。它在底层编译后本质上就是一个Get函数(比如get_IsGrounded()),外部调用它时就像在调用一个方法,只是不需要写()括号。
其他
-
变量命名建议
语法类型 C# 命名规范 代码示例 作用与权限 私有字段 (Field) 小驼峰 ( camelCase)private float moveSpeed;内部私有保存数据 公共属性 (Property) 大驼峰 ( PascalCase)public float MoveSpeed => moveSpeed;对外暴露只读或封装逻辑 方法 (Method) 大驼峰 ( PascalCase)public void Move() { }执行一段动作逻辑

浙公网安备 33010602011771号