一探究竟 · · 阅读约12分钟

Kortress Beach 制作记:从并肩坐下,到一起听歌的夜间海滩

本文目录
  1. 在海边可以做什么
  2. 在一起坐下和行走的场景里,放进过去的记忆
  3. 牵起手后,手腕的偏差最先显现
  4. 地面应该在海浪触及之后才变湿
  5. 引线被点燃的瞬间,也是场景的一部分
  6. 把仙女棒画出的线,接到角色的手上
  7. 同一段音乐,让坐在一起的时间延续
  8. 其他人也应该看到此刻的海滩
  9. 抵达漂亮场景之前的操作,也在继续打磨
  10. 亲自逛逛,继续阅读
  11. 实现与拍摄基准

한국어 · English · 日本語 · 简体中文

我想做一个可以一起望着夜海、点燃手中烟花、听同一首歌的空间。 Kortress Beach 的起点是山寺。 不必说很多话,也能和其他人待在同一个空间里,这一点给了我启发。 把这个想法带到自己网站的角色和记忆中的场景里,就成了 Beach。

最初,我想过另外制作一个像山寺那样朴拙又可爱的角色。 最后还是决定使用 Kortress 的吉祥物 Korsh。 我让原本在 Kortress 中使用的 Korsh,也出现在 Beach 里。 为了营造亲密的氛围,也让角色的外观更加多样,我还加入了女性 Korsh。 她的名字还没有决定。

当前版本中并肩坐着的 Korsh。2026 年 11 月 4 日在本地模拟模式下拍摄,旁边出现的是电脑角色。

当前版本中并肩坐着的 Korsh。2026 年 11 月 4 日在本地模拟模式下拍摄,旁边出现的是电脑角色。

这篇制作记既介绍功能,也记录画面背后修正过的问题。 代码以 2026 年 11 月 4 日的 0280637 提交为基准进行查看。 文中区分了新拍摄的当前画面和保留下来的开发中录像。 录像里的 Mina 是测试对象的昵称,并不是女性 Korsh 的名字。

如果想了解带来启发的空间,可以先读在山寺观察到的无言互动。

在海边可以做什么

进入 Kortress Beach 后,先选择昵称和角色。 之后可以在海滩上走动,或选择工具点燃烟花。 可以独自看看四周,也可以向其他人发起共同动作的邀请。

目前工具菜单除了空手之外,还有五种工具。 分别是手持仙女棒、手持连发烟花,以及放在地面的喷泉烟花、爆裂连发烟花和大花连发烟花。 手边闪耀的火光,与升上远处天空的烟花,观看距离本来就不同。 不同工具的手持方式或地面放置过程也不一样。

想做的事画面中的操作值得一起观察的部分
逛逛海滩移动、转动画面或缩放角色与地平线之间的距离
点燃小烟花选择仙女棒或手持连发烟花后点火手与工具末端的动作
在地面放烟花摆放喷泉、连发烟花并点火工具间距、点火姿势与发射方向
用光写字在仙女棒书写画面中直接画线输入的线条与角色手臂的连接
一起停留邀请对方并肩坐下或牵手散步接受之后的距离与视线
听同一首歌通过一起听音乐共享 YouTube 音乐同时保持坐下、行走与音乐状态

桌面端可以用 WASD 或方向键移动,拖动来旋转视角。 滚轮调整距离,Shift 用于奔跑,Space 用于跳跃。 F 会根据场景用于放置或点火。 刚开始,与其记住快捷键,跟着屏幕上的工具名称和动作按钮操作更容易。 移动端则有独立的移动摇杆和跳跃按钮。

在一起坐下和行走的场景里,放进过去的记忆

并肩坐下、一起散步和听歌这些功能里,包含着我过去的记忆。 即使烟花暂时停歇,也可以继续坐在一起;坐着的时候,也能听同一段音乐。 想在 Beach 营造亲密氛围的念头,不只体现在角色外观,也延续到了这些行为上。

观看视频:彼此对望——开发中的原型

共同动作的流程是:选择对方,发出邀请,然后等待接受。 看起来好像只要把两个角色放进场景,播放一个预设动画就够了,实际却有许多准备工作。 如果彼此离得远,就需要先靠近;各自模型准备完成的时间也不同。 等待过程中可能取消,也可能断开连接。 必须避免已经取消的准备任务迟迟完成后,又覆盖新的状态。

因此,代码里同时有请求、靠近、准备、激活状态和取消处理。 靠近和准备阶段设有超时,会重复发送准备就绪信号,也会筛掉过期的异步任务。 两人相伴的短暂场景,也必须在两个不同画面上按相同顺序成立。 如果点击按钮后,看起来什么都没发生的时间太长,用户可能还没等到那个场景就失去了兴趣。

尤其是在接受邀请的瞬间,复制实际角色骨架、测量手掌表面和步态数据,这些工作造成了负担。 我把不必每次重复的测量移入预先准备的数据,并复用现有材质和步态表。 同时检查指纹,避免模型或计算方式变化后,还继续使用旧数据。 这里想缩短的,不是画面中动作持续的时间,而是开始动作前反复执行的准备工作。

相关修改和验证范围,保留在仓库的 deploy/couple-stability-2026-11-03.md 中。

牵起手后,手腕的偏差最先显现

观看视频:牵手散步——开发中的原型

牵手散步时,比起让两个角色以相同速度移动,更难的是手接触时的形状。 只把手的位置放近,可能会让手掌方向错开,或把手臂拉扯得不自然。 如果只靠一个手腕的旋转来解决,皮肤就可能像糖果包装纸一样扭起来。

当前实现以手掌中心和方向为基准建立接触关系,并反复修正两侧手臂。 遇到手臂长度不够的姿势时,也会调整接触点。 还有一层处理,会把扭转分摊到肩膀和前臂,避免旋转都集中在手腕。 手指握紧和交握的形状,也作为姿态的一部分来处理。

这里使用的 IK,是先确定手应该到达的位置,再调整手臂关节的方法。 比起名称,结果更重要。 即使身体移动、头部转动,手也应当保持与对方的关系。 需要一起检查:静止画面里看着还不错的手,开始行走之后会不会变得别扭。

彼此对望时的头部旋转,以及从行走到停止时的权重和速度,也都改为逐渐变化。 不过,目前并不是所有坐下、起身的转换,都已经连成一套完整的全身动画。 我想把已经打磨的部分,与以后还需要变得更自然的部分区分开。

当前版本中的彼此对望功能。与本地模拟中的电脑角色一起拍摄。

当前版本中的彼此对望功能。与本地模拟中的电脑角色一起拍摄。

地面应该在海浪触及之后才变湿

海水与会变湿的地面,是我特别花心思的部分。 只给水面加一些闪光、把沙地调暗,并不能让它像真正的水边。 细小的先后顺序一旦错了,海浪就容易变成一种背景特效。

代码中实际保留的反馈就指出:湿地先出现,随后海浪才涌入,看起来顺序反了。 旧方式会在新一轮海浪开始时,预先把它稍后才能到达的最远位置也视为湿润。 进入下一轮海浪时,上一轮痕迹的形状也会突然变化。 湿痕先于水出现,以及痕迹不连续,这两个问题叠在了一起。

改善前:水边的海浪表现——开发中的原型

改善后:水边的海浪表现——开发中的原型

这两段视频是开发时海浪表现的对比资料,并不是单独验证下述当前湿润处理方式的对照实验。

现在只记录本轮海浪实际到达的最远位置。 同时,另外记住上一轮海浪留下的终点、纹理,以及退水时间。 不会因为新一轮海浪开始,就把先前的痕迹也改成新纹理。 上一轮留下的痕迹按自己的时间逐渐干燥,下一轮则只在水实际进入的范围内生成新痕迹。

按顺序写下来,流程是这样的。

  1. 白色水波向岸边靠近。
  2. 随着水触及的范围,扩大湿润区域。
  3. 水退去,但湿痕留下。
  4. 随时间逐渐降低残留痕迹的暗度和光泽。
  5. 下一轮海浪到来时,仍把尚未消失的上一轮痕迹一起计算。

湿润程度以 exp(-age/9) 的形式降低。 这不是一个 9 秒后突然完全干燥的计时器,而是随时间逐渐减弱的衰减。 这个值会继续影响沙地颜色、光泽、天空反射,以及对烟花光照的响应。 在考虑哪里有多闪亮之前,先让“为什么这里仍然是湿的”变得有据可循。

海浪涌入和退去的时机,也会与拍岸声对齐。 近海的白线、涌向岸边的线条,以及后面残留的泡沫,各有不同的作用。 我并没有制作完整的流体模拟。 这是一个用程序化演出,让眼睛看到的痕迹和耳朵听到的声音指向同一轮海浪的海面。

这次修改说明,风景的说服力不只来自某一帧,也来自场景之间的连续性。 前一幕的结果,应该在下一幕里留下来。 对湿沙而言,这份短暂的记忆就是海浪的痕迹。

引线被点燃的瞬间,也是场景的一部分

我也在烟花工具的真实感上下了功夫。 按下按钮后,会展示角色操作工具并点火的过程。 手持工具和放在地面的工具,点火姿势首先就应该不同。

观看点火动作——伸手点燃工具的开发中原型

当前代码分别设置手持工具和地面工具到达点火位置所需的时间,以及整个动作的时长。 点燃地面工具时,角色会转身并压低身体。 如果这时只弯下躯干,脚看起来也可能跟着滑动。 因此,会保存脚的位置和方向,并修正腿部关节,让脚留在原处。

右手握着的点火棒,也会通过重新调整手臂,让末端接触引线。 点火结束后,还留出回到持物姿势的时间。 重要的不只是烟花的亮度,而是手、棒尖和引线要呈现同一件事。 如果火已经点着,手却指着别处,使用工具的感觉就会减弱。

当前版本海滩上的工具摆放与点火周边场景。在本地模拟中拍摄。

当前版本海滩上的工具摆放与点火周边场景。在本地模拟中拍摄。

我也区分了各类工具的效果性格。 仙女棒表现手边持续的光,喷泉烟花表现从地面向上喷出的火花。 连发烟花和大花烟花则有发射与爆开的先后过程。 这种区分,并不意味着精确复现了所有火药的物理过程。 它是在画面内,让放在哪里、怎样点火、会出现什么光,都显得合理的工作。

当前版本中,手持仙女棒照亮了面部与周围。在本地模拟中以近距离角度拍摄。

当前版本中,手持仙女棒照亮了面部与周围。在本地模拟中以近距离角度拍摄。

把仙女棒画出的线,接到角色的手上

用光写字——开发中的坐标映射对比视频

仙女棒书写,不同于输入文字后把它显示出来的功能。 它把用户亲手画出的线,连接到角色所持工具的轨迹上。 上方视频是在开发中调整输入与手臂动作的对比画面;当前 UI 使用全屏画布。

鼠标或手指移动的是平面屏幕,而角色的手位于三维空间。 如果直接把屏幕坐标映射到宽阔空间,就可能产生手够不到的点。 需要同时确定角色的臂长、工具方向,以及用于书写的平面大小。

现在会先按画布对输入坐标进行归一化,再映射到手臂能够触及的书写空间。 扩大输入面积,与放大角色的动作,并不是同一件事。 需要让小屏幕上也容易画,同时又不能让场景中的手过度伸展。 改用全屏书写 UI,也是整理这段输入体验的过程之一。

对读者来说,这只是一个短暂的画线动作;制作时,却需要同时处理屏幕输入与角色身体。 烟花的轨迹,与手持工具的移动相连接。

同一段音乐,让坐在一起的时间延续

一起听音乐的 UI——开发中的原型·无声录像

一起听同一首歌的功能,也承载了过去的记忆。 因此,开始音乐时,不会要求先结束坐下或行走。 可以向已经一起坐着或走着的对象,叠加音乐。 代码里也会保留现有的同行行为,并把音乐状态连接进去。

音乐使用 YouTube 播放。 发起请求的一方会定期发送作为基准的播放时间,接收方则考虑传输后经过的时间。 如果播放位置偏差超过 2 秒,就跳到对应位置。 两个画面并不是由完全相同的音频时钟驱动,也不会共享彼此的缓冲状态。

外部视频的嵌入限制,以及浏览器自动播放政策,也会产生影响。 代码中有在播放受阻时提示错误,以及无法自动播放时引导用户手动播放的处理路径。

上方视频使用测试对象来演示共享 UI,应与实际两人通过网络播放的验证录像区分开。

其他人也应该看到此刻的海滩

独自观看的烟花,与和其他人一起观看的烟花,需要解决不同的实现问题。 后来进入的人,也应该看到已经摆在地上的工具。 如果有人点火,其他画面中的那件工具也应该处于点燃状态。 还需要处理这样的情况:坐下者的手势,在旁观者看来却成了错误姿势。

Beach 并没有采用持续发送所有烟花粒子坐标的方式。 它分开发送工具类型、位置、进行状态和时间等信息,再由各个画面构建效果。 变化较快的手持工具、角色移动,以及停留较久的地面工具,也使用不同的发送周期。 地面工具会通过重新发送完整列表补齐缺失状态,也会发送空列表来清除过期工具。

共同动作中角色的姿态,也不只共享一个动作名称。 代码里有发送、还原动画与关节修正后实际姿态的处理,连手指握紧的形状也包括在内。 因为某个人“正在坐着”,与他现在以什么姿势坐着,是不同的信息。

虽然加入了连接与后进入者恢复状态的机制,但这并不意味着所有卡顿都已消除。 目前房间人数上限这类配置值,也不同于在多台实际设备上确认流畅运行的性能测试。

抵达漂亮场景之前的操作,也在继续打磨

最近的改动包括奔跑、跳跃、入场引导和移动端操作改进。 奔跑从单纯提高行走播放速度,改成了独立的 Run 动画。 在保留现有骨架和动画的同时加入奔跑数据,并测量实际鞋子与手部的形状来确认动作。 之后也继续留下了调整手臂、手腕和步幅节奏的记录。

用于检查两位 Korsh 奔跑动作的开发预览

这是用于检查两位 Korsh 奔跑动画的开发预览,并非海滩中的游玩画面。

移动端上,不可见的移动判定区域曾经比看得见的摇杆更大,导致想转动视角时角色却移动了。 我整理了移动区域与拇指接触位置,同时考虑屏幕边缘和工具栏。 确认小屏幕上按钮是否重叠,与检查真实手机的发热和帧率,需要分别进行。

入场流程也调整为:角色准备完成之前,不开始接受操作。 如果等待过久或发生错误,会告知状态并允许重试。 进入后,则会介绍移动方法。 来到海边却不知道能做什么,或等待时感觉画面卡住,也都是制作中需要解决的部分。

接下来要检查的,同样是这些细小的中断。 判断标准包括:第一次来的访客能否理解移动方式,是否知道发出邀请后为什么需要等待,以及两人结束动作时是否自然。 即使有牵手听歌的功能,如果到达那个场景的过程太难,意图也无法充分传达。

山寺带来的启发,在 Beach 里延伸成了 Korsh、大海、烟花和音乐。 我花心思做的,是把细小动作和痕迹接起来,让相伴的时间不显得生硬。

亲自逛逛,继续阅读

实现与拍摄基准

实现说明对照了 Beach 仓库的 web/index.html、网络代码、2026 年 11 月 3~4 日的变更记录,以及同行稳定性报告。 当前画面是在 2026 年 11 月 4 日公开部署版本的本地模拟模式下拍摄的。 开发录像是另行保存的原型资料,没有作为真实访客或运营性能的证据使用。 详细依据和媒体原始文件清单,另外保存在写作用的调查报告中。

1 / 1