【宝贝项目001】【开发日志001】【Unity】玩家角色的基础移动

什么?!我要开始做游戏了,那首先,当然是搞一个可以移动的角色,但是在Unity中,该怎么做角色的移动呢。

角色移动挂载的组件

首先有两个方法:

  • 非物理驱动:挂上Character Controller
    自带简化的胶囊体碰撞,不受 Unity 物理引擎的力(重力、推力)控制。它的移动完全靠代码指定位移(Move()),手感极其精准、无惯性。
  • 物理驱动:挂上 Rigidbody 和 CapsuleCollider
    完全交给 Unity 物理引擎控制,靠改变速度 velocity 或加力 AddForce来实现移动。

根据自己的需求,进行选择,这里我选择了Character Controller。

按键的绑定

在实际开发中,必须避免硬编码按键,Unity 提供了两种标准方式来同时适配键盘与手柄:

  • 方案 A:旧版 Input Manager(适合快速搭建原型)

    1. 打开 Unity 菜单:Edit -> Project Settings -> Input Manager。
      image

    2. 展开 Axes,将 Size 加 1,新建一个映射项,命名为 Action。

    3. 配置绑定:

      • Positive Button:e(键盘 E 键)
      • Alt Positive Button:joystick button 3(手柄 Y 键/△ 键,根据需求设置)
    4. 代码中直接调用:

      if (Input.GetButtonDown("Action"))
      {
      	// 执行动作
      }
      
  • 方案 B:New Input System 插件(适合中大型项目/正式版本)

    1. 在 Package Manager 中安装 Input System。

    2. 新建一个 Input Actions 资源,创建一个 Action 命名为 Action。

    3. 为 Action 添加两个 Binding:一个连键盘 E 键,另一个连 Gamepad -> buttonNorth(手柄上方按键)。
      image

    4. 在代码中通过回调或者 InputAction.WasPressedThisFrame() 读取,完全无需关心输入源是手柄还是键盘。

    5. 需要在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,然后将对应上下左右按键绑定上去,如下图。
image

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()),外部调用它时就像在调用一个方法,只是不需要写 () 括号。

其他

  1. 变量命名建议

    语法类型 C# 命名规范 代码示例 作用与权限
    私有字段 (Field) 小驼峰 (camelCase) private float moveSpeed; 内部私有保存数据
    公共属性 (Property) 大驼峰 (PascalCase) public float MoveSpeed => moveSpeed; 对外暴露只读或封装逻辑
    方法 (Method) 大驼峰 (PascalCase) public void Move() { } 执行一段动作逻辑
posted @ 2026-09-28 17:24  SEHOD  阅读(8)  评论(0)    收藏  举报