示例 · Cinemachine 双屏
两个可运行场景,都不依赖任何外部美术:全部用 Unity 内置 Cube / Sphere / Plane 在 Awake 里搭出来,层用无名层 28 / 29,不需要改 Tags and Layers。
文件:DemoFactory.cs / SameWorldSplitDemo.cs / DualStyleSplitDemo.cs / Scenes/*.unity
◈
打开场景时 Hierarchy 里只有一个空物体、Game 视图写着 "No cameras rendering" —— 这是正常的。场景文件只是「一个挂着 demo 脚本的空壳」,相机 / 机位 / Brain / 台子 / 柱子 / 方块 / 灯光全在
Awake 里现搭,点 Play 之后那棵树立刻长出来。两个例子的分界线
| ① 同一场景双人分屏 | ② 同场景视觉分叉 | |
|---|---|---|
| 需求 | 一个大场景、两个角色,一人一半屏 | 场景一份、位置固定,两侧看到的东西不一样 |
| 两半为什么不同 | 相机跟着不同角色 ⇒ 视角不同 | 相机位姿相同 ⇒ 内容层不同 |
| 组件 | CinemachineDualView(Composite) | CinemachineDualView(Composite) |
| 像素 | 2× | 2× |
| 相机 | 两台各自跟随,位姿不同 | 必须同一张图,位姿由 CinemachineDualMirror 保证 |
例 ① SameWorldSplitDemo
一个大场景(地面 / 中央高塔 / 两排拱门 / 散落箱子)+ 红蓝两个角色,两台相机各跟一个。
- 走接缝合成路径(
ViewRenderMode.Composite):两台相机各自渲整屏到 RT,再由 shader 按接缝逐像素择一 ⇒ 接缝可以任意角度 / 任意占比,还能在 Game 视图里直接拖。 - 两台相机都看整个世界(
~(1 << 5),只排除内置 UI 层)——「两半是同一张地图」不靠 cullingMask 实现。 - 面板:
分屏 Split → Separate(Style)/合屏 Merge → CombineAroundPlayers()(两台相机慢慢并拢到两人中点并拉远,两侧画面真的并成一张)/ 竖切 / 横切 / 斜切 / 接缝光带开关 / 角色回原位 / 两侧视角复位。 - 右键按住拖动 = 转鼠标那一侧的视角(左右转圈、上下抬压,
SetOrbit)。两侧可以转成不同角度;点「合屏」时框架会把两侧偏移混成同一个方向与长度,所以视角不同也能并拢成一景。
例 ② DualStyleSplitDemo
一份共享场景 + 5 组「同位置 A 是 Cube、B 是 Sphere」的变体。
- 拖动方块让它跨过切线,切到哪边就显示哪边的外形——逐像素切换,没有一行交叉检测代码。
- 视角是
Rig A下的一台固定机位(vcam_Fixed Cam,不挂 Body/Aim)。Rig B没有 Brain、也没有机位:它的相机位姿由CinemachineDualMirror每帧从 A 侧复制。 - 固定机位下
AutoFraming = false(取景偏移是给「各跟各的角色」用的,会把固定机位推开)。
机位怎么摆(两个样例都是这套)
Rig A/ ← CinemachineRigBinder(分屏调度器认它)
├─ Camera ← Camera + CinemachineBrain(+ AudioListener,只留一个)
└─ vcam_Follow Cam ← CinemachineCamera + CinemachineFollow + CinemachineRotationComposer
- 机位与
Camera必须平级。机位是位姿来源、Camera 是出图设备;把机位挂成 Camera 的子物体,Brain 每帧写回 Camera 的位姿会经父子关系反喂给机位——跟随机位收敛发飘、固定机位直接原地不动。 - 跟随机位 =
CinemachineFollow(Body)+CinemachineRotationComposer(Aim)。 - 固定机位 =
CinemachineCamera什么都不挂。 vcam.Priority = 20要显式写:PrioritySettings的Enabled默认 false,只写Value的机位会被当成优先级 0。- 一个 rig 一个 Brain:合成路径下 B 侧是镜像相机,那一侧不能再挂 Brain。
雷区
Viewport(Camera.rect)和Composite不能混着切。CinemachineDualView的装配引导会调SetSeam,而SetSeam把RenderMode单向切成Composite(DowngradeToViewport回不来,切的时候画面还会跳)。Camera.cullingMask是「掩码」不是「层号」。直接传层号28,得到的是0b11100= 层 2/3/4 ⇒ 相机什么都看不到:只有清屏色、一点几何都不渲染,而且不报任何错。必须写1 << 28。样例现在用~(1 << 5)。- ② 必须关自动取景(
AutoFraming = false)。 - 层号 vs 层名:
CinemachineDualVariant默认按层名解析,无名层解析不出来,样例用SetLayers(28, 29)直接给层号。 - 机位要建在
CinemachineRigBinder之前(或建完调binder.Rescan()):binder 在Awake里一次性扫描机位并缓存。 - 多份 rig 各带 Brain 必须分流输出通道:CM 3 的 Brain 是从全局机位表里挑优先级最高的,
IsValidChannel只看OutputChannel/ChannelMask,不看层级。CinemachineViewSplitter.Register已自动分配(第 1 份Default、第 2 份起Channel01…)。 - 样例不做物理:
DemoFactory用DestroyImmediate移除 primitive 自带的 Collider。