跳转到内容

31. 玩家进来的前三十秒

约 35 分钟 难度:新手 动手章

VRChat 的世界列表里有一个普遍现象:很多世界缩略图很漂亮,玩家点进去十秒不到就退了。

退出的原因常常不是世界做得不好,是进门那一刹那「不知道自己在哪、不知道该看哪、不知道该往哪走」。当一个空间没回答这三件事,玩家会先退出再去翻评论区,再决定要不要回来。

这章只做一件事:把出生点周围那三十秒,做成可以看懂的三十秒。

打开第二部以来一直在搭的小屋,找到 Hierarchy 里那个 Spawn 空 GameObject。Inspector 里看到的是它的 Position 和 Rotation。第 5 章把它当成「玩家会出现的位置」用。

实际上 Spawn 提供的不止位置,还有方向。VRChat 把玩家放到 Spawn 时,玩家面朝的方向就是 Spawn 的 Z 轴正方向(Scene 视图里那个蓝色箭头)。这意味着 Spawn 是一台相机,决定玩家出生时第一帧看到的画面。

做一个最直接的对照:

  1. 选中 Spawn,Rotation Y 改成 0
  2. Build & Test 进世界,记下第一眼看到的是什么。
  3. 退出,Rotation Y 改成 180,再进一次。
  4. 同样记下第一眼看到什么。

同一个房间,两次进去看到的画面完全不同。第一次也许看到的是房间深处那盏暖灯,第二次也许只看到一面白墙加一扇门关着的背面。

第二种情况就是出生点没立住。

把上面那个原则翻成可执行的规矩,差不多是这四条:

  1. 不要面朝墙壁、面朝边角、面朝紧闭的门。这三种角度都会让玩家感到「被堵住了」。
  2. 第一帧要看见房间的主轴。让出生点面向房间最有信息密度的一面:壁炉、舞台、吧台、窗外景观。
  3. 第一帧要能看见至少一个其他可去的方向。如果玩家身后还有路,让那条路在画面里以余光形式出现,比如门框斜出现在画面边缘。完全只对着前方一堵景观墙的世界,玩家会原地呆站。
  4. 出生点上方留出空间,下方留出落点。VRChat 玩家身高默认是 1.6 米左右(玩家可校准),Spawn Y 设到 0 时玩家的眼睛在 1.6 上下。Spawn 上方至少要有 2 米头顶空间,下方要落在可踩的地面上。这两条不满足,VR 用户可能直接卡进墙或穿过地板。

打开自己的世界,对着这四条检查一次。一次出生点改 5 度旋转,比写多少代码都改善体验。

一个出生不够的时候:让玩家不要堆叠

Section titled “一个出生不够的时候:让玩家不要堆叠”

第 5 章为了简单只放了一个 Spawn。一个 Spawn 在多人世界里有个尴尬:十个人同时进世界,会全部出生在同一个点上,重叠成一团。

VRChat 支持给 VRC Scene Descriptor 配多个出生点,玩家进来时按规则随机或顺序选其中一个。

回到 Hierarchy,找到挂着 VRC Scene Descriptor 的物体(通常就是场景根物体)。Inspector 里展开 Spawns 数组:

VRC Scene Descriptor
└─ Spawns
├─ Element 0 (None Transform)
├─ Element 1 ...
└─ ...
Spawn Order Random # Random / First / Sequential
Spawn Orientation AlignPlayerWithSpawnPoint
Object Behaviour at Respawn Respawn # 玩家重生时所有 Pickup 也归位
Player Object Behaviour at Respawn Respawn

接下来做几个 Spawn:

  1. Hierarchy 选中 Spawn,按 Ctrl+D 复制三份,命名 Spawn_ASpawn_BSpawn_C
  2. 三个点摆在出生区域附近,相距 1.5 米左右,方向一致(或略有变化,给玩家一点新鲜感)。
  3. 把三个 Transform 拖进 VRC Scene DescriptorSpawns 数组里,分别填到 Element 0/1/2。
  4. Spawn Order 设为 RandomSequentialRandom 就是每个新玩家随机选一个,Sequential 是按顺序轮流。

Spawn Order 的几个选项各有用法:

选项作用适合
First永远用第一个 Spawn单 Spawn 世界,跟原来行为一样
Random每次随机选一个休闲世界,避免堆叠
Sequential按顺序轮流想让玩家均匀分布的活动世界
Demo用第一个 Spawn,但把它当作玩家在现实房间中的中心;玩家会按自己头显在房间里的偏移相对 Spawn 出现演示场、按真实房间布展,要求落点跟物理空间一致

Spawn Orientation 字段控制玩家进出生点时的朝向:

  • AlignPlayerWithSpawnPoint:用 Spawn 的旋转对齐玩家朝向(默认值,前面那条「Z 轴指向决定面朝」的规则就是这个)。
  • AlignRoomWithSpawnPoint:保留玩家自己 VR 房间的朝向,Spawn 的旋转不强制对齐。多用于已经习惯自己 VR 房间正前方的 VR 玩家场景。

普通房间留 AlignPlayerWithSpawnPoint 就好。

第二步:让玩家一眼能看懂自己在哪

Section titled “第二步:让玩家一眼能看懂自己在哪”

出生点摆好了,下一件事是给第一帧加一个可读的视觉焦点

走进真实世界的酒店大堂,会看到一块写着「Reception」或「Welcome」的牌子。走进美术馆会看到入口的展览海报。出生点附近放一块这样的「门面物」是同一个意图:让玩家一眼知道自己在哪。

最朴素的做法用 World Space UI(在三维空间里的 Canvas,跟在屏幕上贴的二维 Canvas 不同)。

  1. Hierarchy 空白处右键 UICanvas。Inspector 里把 Render Mode 改成 World Space
  2. 选中这个 Canvas,Rect Transform 里把 Width / Height 改成 400 / 200Scale 改成 0.005, 0.005, 0.005(World Space Canvas 默认 Scale 是 1,1 单位的 UI 在世界里是巨大的)。
  3. 摆到出生点正前方 3 到 4 米的位置,正对玩家。
  4. Canvas 下右键 UIText - TextMeshPro,在 Inspector 里编辑文字(具体设置参数下一节再讲)。

文字内容简单到这种程度就够:

欢迎来到 月光小屋
可以坐下、可以拿起桌上的灯
出口在右边

三行,不超过 30 字。第一行告诉玩家这是什么地方,第二行告诉玩家可以做什么,第三行告诉玩家可以去哪。

字体问题第 34 章解决,本章先验证「字面意思能让玩家看懂」就行,必要时先用英文。

「动线」是建筑设计里的词,意思是人在空间里实际行走的路径。出生点之后玩家走第一步,多半是被画面里某个东西吸引才动的。

设计动线起点可以用三个朴素手段:

  1. 光线引导。第 9 章讲过冷暖对比:远处一抹暖光会自然把人吸过去。在出生点正前方 5 米左右放一盏低强度的 Point Light(颜色 #FFE0B0、Intensity 1.5 左右),玩家会自然走向它。
  2. 可见的目标物。一张沙发、一盏吊灯、一个能拿的东西放在画面深处,比一面光秃秃的白墙更能让人想走过去看看。
  3. 走廊或开口。如果世界由多个空间组成,让出生点直接看到第二个空间的入口(一扇半开的门、一段走廊、一道拱门)。玩家会想知道里面是什么。

反过来三个让玩家「不想动」的常见错误:

  • 出生点周围 360° 全是同样的空间,没有方向感。
  • 出生点紧贴一面有信息的墙,但身后是空的,玩家不知道还能转身。
  • 出生点上方有过低的天花板(VR 玩家会有压迫感)。

第 14 章用过 OnPlayerTriggerEnter。同一个组件可以做一个「玩家走出出生圈时触发」的区域:第一次跨过这条线时,背景音淡入、第二盏灯打开、面板上的提示文字换成下一段。

最薄的一版只做「打开第二盏灯」:

WelcomeStep.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
public class WelcomeStep : UdonSharpBehaviour
{
public GameObject toEnable;
private bool triggered;
public override void OnPlayerTriggerEnter(VRCPlayerApi player)
{
if (!player.isLocal) return;
if (triggered) return;
if (toEnable == null) return;
triggered = true;
toEnable.SetActive(true);
}
}

挂法跟第 14 章的 Trigger 区域一致:建一个空 GameObject 当区域,加一个 Box Collider 勾上 Is Trigger,把这段脚本挂上去,把要打开的物体(一盏灯、一段提示牌、一个传送门)拖到 To Enable 字段。

triggered 字段保证触发只发生一次。玩家在出生圈里反复进出时不会反复触发。

注意 if (!player.isLocal) return; 这一行:第 26 章会展开讲,这里只用结论:玩家事件在每个客户端都触发一次,没这行的话别人进世界也会让本机这边的灯亮。

「第一帧看到的画面」很大程度上是「第一帧的光是什么样」。

第 9 章铺过的冷暖对比规则在出生区特别有用。一组容易立得住的搭法:

Directional Light
Rotation 50, -30, 0
Color #9AB4C8 # 冷调天空光
Intensity 0.4
Point Light(出生点正前方 4 米)
Type Point
Color #FFE0B0 # 暖调焦点光
Intensity 2.0
Range 6
Shadows None # 出生点附近的小灯先关阴影,省性能

冷调全局光给世界一个干净的底,暖调焦点光在画面深处吸住视线。玩家第一帧看到的是一张有焦点的画,不是一张平均亮度的工程截图。

VRChat 烘焙光照下的出生区还有一个很实用的小技巧:在出生点附近多放几个 Light Probe。Light Probe 是预计算好「这一点上四周来的光是什么」的小球,玩家、Pickup、动态对象进入这块区域时会按周围 Probe 的值取光。Probe 太少,玩家头像在出生点会显得灰扑扑的;Probe 加密之后,玩家自己的头像会被附近的暖光「染」一点点温度。Light Probe 的具体放法第 36 章会展开。

挑一个或几个改:

  • 入夜版:把全局光降到 0.1,留两盏暖色 Point Light,看出生区在「半黑」状态下还认不认得路。
  • 晴天版:全局光升到 0.8 偏白,关掉所有 Point Light,看暖光被拿走之后画面是不是变得太冷。
  • 盲测:把欢迎 UI 暂时禁用,请没看过这个世界的人进来,问他「看到第一眼,第一反应想往哪走」。如果对方走的方向跟设计意图不一致,问题不在玩家。

第三个版本最有用,但也最难做。条件不够时,自己用一个第二号 VRChat 账号、用全新的 avatar 进去看一遍,能发现的不一致比想象中多。

写一份清单,每次发布前自己走一遍:

  • Spawn 的 Z 轴指向房间最有信息的一面,不指墙、不指角、不指关上的门
  • Spawn 上方至少 2 米空间,下方落点稳固
  • 至少有 3 个 Spawn(休闲 / 游戏 / Hub 类世界),避免多人堆叠
  • 第一帧画面里能看见可去的方向(开口、走廊、亮光)
  • 欢迎牌字号在 VR 里清晰,背景与文字对比足够
  • 出生点附近有足够 Light Probe,玩家头像不会发灰
  • 找一个没看过这个世界的人,让他描述第一帧看见了什么。如果他说不清,画面信息密度不够