为《Chop Chop Together》自制实体钓鱼竿控制器:从 UE5 收线机制到硬件原型

AI3D 发表于 4 周前 浏览 1 分类 创作分享

引言

从本质上讲,Chop Chop Together 是一款在 Unreal Engine 5 中打造的、节奏明快、混乱不堪的 1 至 4 人合作派对游戏。玩家会被丢进共享的高压工作空间中,这些空间被划分为三种截然不同的职业:钓鱼、仓库管理和打铁。虽然每种工作都拥有完全不同的核心机制和内部系统,但根本目标始终如一:在严酷的时间限制下完成不断到来的订单,从而推进到越来越不留情面的关卡。

喜剧效果与混乱源于四个人试图同时执行多步骤流程而又不撞在一起,同时还要在动态的地图危险中求生,比如湿滑的冰面地板、偷走订单的海鸥、把玩家拽走的龙卷风、乱窜的汽车以及路过的有轨电车。

Chop Chop Together
Chop Chop Together
Chop Chop Together
Chop Chop Together
Chop Chop Together
Chop Chop Together

从童年怀旧到 Gamescom 的愿景

我们对实体替代控制器的痴迷由来已久。它源于一种非常古老、根本性的对触感游戏的热爱——那种纯粹的快乐始于街机时代用 NES Zapper 打鸭子,后来演变成把塑料配件咔哒扣到 Wii Remote 上。我们始终相信,亲手触碰游戏世界会改变玩家与体验之间的连接。

这根定制钓鱼竿并非始于会议室里精心算计的营销噱头;它始于深夜分享的一段视频和突然迸发的灵感。我们的联合创始人兼游戏开发者 Melike 正在网上浏览时,偶然看到了一段非传统数字互动展览的影像。与常规游戏展会不同,这个展览展示了定制的超大实体交互界面:一把巨大的机械剪刀,每剪一下都会在屏幕上触发数字剪切;还有一个巨大的垃圾桶,能把实际投掷纸张的动作识别为软件输入。

她立刻把视频丢进我们的团队聊天,只附了一句话:“我找到我们在 Gamescom 上抢尽风头的方法了。”

在庞大拥挤的会展大厅里,把参观者从 AAA 展台吸引过来是出了名的困难。但在内心深处,我们知道一个令人无法抗拒的实体钩子就是答案。(剧透警告:它的效果比我们想象得还要好。)

这个想法一落地,我们的另一位联合创始人兼游戏开发者 Kerem——一位拥有多台 3D 打印机、有着自制定制科技产品经历的硬核硬件爱好者——立刻着手把这个视觉概念变成可用的硬件。

他一头扎进硬件论坛、微控制器数据手册和机器人相关的 Reddit 子版块,梳理出所需的精确传感器阵列和信号路径。在一个元件到货之前,Kerem 就在 Blender 中调出我们游戏内的鱼竿模型,彻底拆解其内部几何结构,以设计定制的安装点、电池仓和走线通道。蓝图敲定、零件下单之后,我们便直接从软件设计转入实体制造。

游戏内钓鱼机制与物理映射

在游戏中,收线是右摇杆上的一个持续旋转手势。重要的一点——也正是它决定了之后所有的设计决策——是游戏实际测量的东西。它不在乎摇杆的位置。它关心的是摇杆角度变化的速度,以及变化的方向。

具体来说:输入向量通过 Atan2 转换成一个角度,与上一帧角度的差值以考虑环绕(wrap-safe)的方式计算,这样跨越 360° 就不会被记录为一个巨大的跳变;该差值的符号给出顺时针还是逆时针,而差值的大小除以经过的时间得到旋转速度。小游戏实际使用的就是速度和方向。

为什么这个细节决定了硬件选型:因为游戏读取的是角速度而不是位置,所以控制器完全不需要复刻一个拇指摇杆。它需要做的是产生一个可信的旋转向量。正因如此,我们才能用曲柄上的旋转编码器来驱动游戏:固件上报的不是摇杆被推到哪个位置,而是合成一个以曲柄转动速率绕圆运动的点。

由此,物理映射方案便自然而然地确定了:

  • 卷线曲柄:旋转。一比一的映射,也是这个项目存在的主要原因。
  • 抛竿:一次真实的挥动。这是你的手臂本就熟悉的动作,由加速度计和陀螺仪来检测,而不是靠按钮。
  • 行走:握把上的一个拇指摇杆。不算光鲜但必不可少;在两次钓鱼之间你仍然需要在船上走动,而为此再递给玩家一个手柄会破坏沉浸感。
  • 拾取物品和使用物品:拇指下方的一个按钮,短按和长按作为两种不同的操作,因此一个按钮涵盖了两个动词。
Building Custom Fishing Rod Controller For Chaotic Party Game

第一个原型与早期实验

第一个原型是一个台面组装件:没有外壳,没有鱼竿,只有信号通路。一块 Seeed XIAO ESP32-S3,后来是一块 Heltec V3 板,其板载 OLED 让我们无需连接 PC 就能观察实时数值,还有三个传感器:

  • 用于卷线器的 AS5600 12 位磁性旋转编码器。一个径向磁化的磁铁位于曲柄轴上,芯片以非接触方式读取其角度。我们选择它而不是电位器,因为电位器会磨损,并且在绕回处存在死区;也而不是光学编码器,因为后者需要开槽圆盘和更多组装工作。
  • 用于抛投手势的 LSM6DS3TR-C 六轴加速度计和陀螺仪。
  • 用于移动的 KY-023 摇杆模块。

两个传感器都是 I²C 接口,而且都接在一条可插拔的连接器链上,这意味着在我们还在决定鱼竿内部结构长什么样的时候,传感器组件几秒钟内就能重新排布。

蓝牙版本,以及它为什么被弃用:最初的传输方式是 BLE:微控制器把自己广播为一个蓝牙 HID 手柄,所以既不需要接收器,也不需要线缆。它确实能用。Windows 识别到了手柄,轴会动,按键也会响应。

然后它撞上了一堵与我们代码毫无关系的墙。在 Windows 上,蓝牙手柄始终是 HID/DirectInput 设备,永远不可能成为 XInput 设备。XInput 是微软专有的,第三方无法实现任何无线 XInput 协议。大量游戏和工具只看 XInput。我们的鱼竿出现在 Windows 控制器面板里,在那里轴能动,但在游戏里毫无反应。

有一个变通方案,我们也用了:一个虚拟手柄驱动加上一个映射器应用,把 DirectInput 在 PC 上转换成合成的 XInput 设备。功能可用、经过测试,在开发者自己的机器上没问题。但作为产品毫无用处。这意味着主播打开盒子后,在钓到一条鱼之前,得先安装一个内核级驱动,还要在直播中配置映射器。这不是一套营销套件,而是一张技术支持工单。

重做后的方案必须满足什么:需求变成了:PC 必须在零安装的情况下识别它。由此立刻引出两个后果:

  • 第一,无线链路和 USB 链路必须分开。鱼竿保留自己的电池和无线电;一个小的 USB 接收器成为 PC 实际看到的东西,而这个接收器就是一个普通的 USB 手柄,任何操作系统都能直接识别。
  • 第二,芯片选择不再是一种偏好,而变成了硬性约束,因为只有部分型号能够充当 USB 设备。我们研究过 ESP32-C5,发现它不支持 USB-OTG 设备模式,Espressif 自己的跟踪表把它标记为 “Won’t Do”。而 S2、S3 和 C6 可以。这替我们选定了接收器:LILYGO T-Dongle-S3,一款 USB-A 棒状外形的 ESP32-S3,恰好还带有一块小尺寸彩色 LCD。

在无线通信方面,我们从 BLE 转向了 ESP-NOW——乐鑫的无连接 2.4 GHz 协议。它采用广播方式,因此没有配对握手,更关键的是,拆箱的人也不需要面对任何配对界面。

最终的实体搭建

它最终定型为两个物件:

钓竿(电池供电):

  • 一块 Adafruit ESP32 Feather V2 作为大脑;
  • AS5600 编码器负责读取卷线轴,IMU 用于抛投检测,二者都挂在 I²C 链上;
  • 摇杆及其按压开关;
  • 两节 18650 电池并联,提供 6400 mAh,正极线路上串联一个滑动开关,通过板子自带的 USB 口充电;
  • 3D 打印的机身分成若干段,用卡口接头连接,因此可以拆解收纳再组装。

加密狗(总线供电):

  • T-Dongle-S3,直接插入 USB-A 端口;
  • 其 80×160 的 LCD 屏幕运行实时诊断视图:连接状态、数据包速率、信号强度、鱼竿电池电量、一个代表拇指摇杆的圆点、一个绕环运行代表卷线器的圆点(中央显示实时 RPM),以及三个按钮的指示灯。

三个源于数据手册、而非个人喜好的决定:

  • 电芯并联,绝不串联。两节 18650 串联就是 8.4 V,会烧毁电路板。这一对电芯在连接之前要先做电压匹配;
  • 模拟输入只存在于第一组 ADC 通道上。在经典 ESP32 上,第二组 ADC 通道与 WiFi 射频共享;射频开启时去读那里的引脚,读到的值就是垃圾数据。数据手册上的这一行决定了摇杆的接线方式;
  • 那块板子上的 I²C 传感器供电轨由某个 GPIO 做电源门控,启动时必须将其拉高,否则传感器就根本不会出现。这是一个两行代码的修复,但如果你不知道,就得花掉一个下午。

软件、工具与遥测

  • 使用 Blender 制作竿身和卡口分段关节,并通过 FDM 打印;
  • 使用 Arduino IDE 和 ESP32 核心开发两套固件,再加上 Adafruit 的传感器和显示库;
  • 用于验证的平台检查工具:Windows 控制器面板、Linux 输入设备列表(`evtest`)以及浏览器游戏手柄测试器;
  • 虚幻引擎自带的输入诊断:原始输入插件的详细日志记录和实时动作值调试叠加层。

调校界面:

鱼竿本身就是自己的调校界面。它会启动一个 WiFi 接入点并托管一个实时页面:用手机连上它,当鱼竿握在你手中时,你可以查看实时的加速度与旋转量、峰值保持追踪器、卷线器 RPM、摇杆原始数值以及磁铁状态,并用滑块调整每一个阈值。更改即时生效;保存按钮会将其写入闪存,使其在断电重启后依然保留。

用笔记本电脑、还得用 USB 线拴住你需要挥动的那个东西来校准挥竿,既痛苦又会得出糟糕的数据。而口袋里揣一部手机,几分钟就能搞定,而且你校准的是真实手势,而不是趴在桌前做出来的近似动作。值得了解的约束:接入点被固定在和 ESP-NOW 链路相同的无线电信道上。WiFi 和 ESP-NOW 共享射频,所以如果这块板子曾经加入过普通网络,它就会跟随那个网络的信道,鱼竿到接收器的链路便会悄无声息地停止工作。

把遥测作为一项刻意设计的功能:接收器每秒打印一行状态:链路状态、数据包速率、信号强度、电量,以及它即将交给操作系统的确切字节。这个项目里几乎每一个棘手的 bug 都是某种形式的“其中某一层在骗我”,而让每一层明明白白地说出它刚刚做了什么,每一次都能让这个问题迎刃而解。

通信与 Unreal 集成

通信经过三跳,每一跳都向下一跳隐藏自己的复杂性:
鱼竿(编码器 + IMU + 摇杆)→ 接收器(ESP-NOW 50 Hz,20 字节数据包)→ Unreal Engine(USB HID,4 轴/8 按键)

  • 鱼竿到接收器:每秒广播 50 次的 ESP-NOW,携带一个紧凑的 20 字节数据包:设备 ID、计数器、4 个摇杆轴、按键位域、卷线器 RPM 遥测、电池百分比和标志字节。广播省去了配对握手。设备 ID 允许多根鱼竿和多个接收器在同一房间内工作而不会互相串扰。
  • 接收器到 PC:接收器呈现为一个标准 USB 游戏手柄,带有手写的报告描述符(4 个无符号 8 位轴,以中点为居中值,8 个按键)。不需要外部驱动。
  • PC 到 Unreal:Unreal Engine 的原始输入插件被配置为识别我们特定的供应商 ID 和产品 ID。我们直接发出标准游戏手柄按键,让鱼竿以看起来像 Xbox 手柄的身份出现(卷线器 = 右摇杆,摇杆 = 左摇杆,动作 = 面键)。

由于鱼竿最终映射为普通的游戏手柄按键,游戏的输入映射完全不需要任何针对鱼竿的专门条目。项目里没有任何部分知道鱼竿的存在。如果接收器在 300 毫秒内没有收到任何信号,它会自动将轴归中并释放所有按键,以防止角色失控移动。

设计挑战、改进与 Bug 修复

让旋转感觉连续:当摇柄停止转动时,将虚拟摇杆归中会产生严重的瞬时角度差尖峰,导致游戏内出现微小卡顿(即“咔嗒”声)。解决方法是:当摇柄停止时,将虚拟摇杆向量冻结在圆周上的原位置,使角度差保持为零。

摄像机旋转的边缘情况:冻结摇杆位置会导致第三人称摄像机无休止地旋转(因为摇杆被保持在 95% 的偏移量上)。我们加入了一个 500 毫秒的超时:在不足一秒的摇柄间歇中继续保持冻结,但如果超过半秒没有活动,就视为空闲,并将摇杆向量重置到中心。

手势校准:当线性加速度和角速度都超过既定阈值时,抛竿检测便会触发。固件中内置了峰值保持跟踪器,用于记录真实的手臂挥动,并将阈值设定为峰值的 60–70%,随后设置一个冷却期,以防止单次挥动触发两次抛竿。

开关去抖:轻触开关的微小抖动会重置长按计时器,破坏长按功能。软件去抖解决了这个问题,并更新了逻辑,使短按在松开时只触发一次(仅当从未越过长按阈值时)。

硬件诊断:为了在没有万用表的情况下发现硬件损坏或排针偏移,固件启动检查会利用内部上拉和下拉电阻探测引脚,以自动检测断路或短路。

USB 充电兼容性:USB-C 直通延长线缺少配置电阻引脚(CC 引脚),导致现代 C-to-C 智能充电器无法供电。该鱼竿通过传统的 USB-A 转 USB-C 线缆可以可靠充电。

试玩测试洞察与迭代

每一次改进都是由真实的人类观察驱动,而不是靠代码检查:

  • “tak-tak”问题最初由试玩者反馈时,并不是作为数学异常提出,而是说“卷线器感觉像在卡住或发涩”。
  • 一旦试玩测试从固定相机测试场景转到动态第三人称设置,无限相机旋转问题立刻就被发现了;
  • 挥竿加速度的桌面端计算与玩家自然动作完全不符,促使我们创建了实时遥测追踪器。

给制作自定义控制器的独立开发者的建议

  • 先做信号链原型,再做外壳建模: 一个曲柄、编码器、面包板和实时屏幕数值,一个下午能给出的答案比一个 3D 外壳更多。
  • 尽早决定是否必须即插即用: 要求安装驱动会立刻限制采用率。
  • 理解硬件与平台限制: 无线 XInput 无法自定义实现,而且并非所有微控制器都支持 USB HID。
  • 构建无线调参界面: 校准参数在物理测试期间会不断变化。
  • 在所有层级提供清晰遥测: 给每个边界加上监测,以便快速隔离 bug。
  • 在连接其他外设的外部机器上测试: 发现隐藏的驱动或控制器映射冲突。
  • 让游戏逻辑保持硬件无关: 将自定义硬件映射到标准游戏控制器输入,避免长期维护开销。
  • 确保物理动作服务于现有机制: 自定义硬件应改善现有输入的手感,而不是为了给硬件找理由而发明新机制。

Dango Dynamics,独立游戏工作室

采访由 David Jagneaux 进行

相关链接

原文链接:https://80.lv/articles/building-custom-fishing-rod-controller-for-chaotic-party-game

喜欢这篇内容吗?