LOADING
加载中,请稍候…
ZC 程之睿 CZR's SPACE
UnityC#GraphicsGameplay

从零实现传送门(Portal)系统:视图渲染与物理穿越Building a Portal System From Scratch: View Rendering and Physical Traversal

2024年12月19日December 19, 2024 9 分钟阅读9 min read 程之睿

传送门看起来「魔法」,但拆开来是两个相对独立的问题:看起来能穿过去(渲染)和 真的能穿过去(物理)。

一、视图渲染

每个传送门是一块 quad,上面贴一张 RenderTexture。渲染这张贴图的虚拟相机由「主相机相对本门的变换」映射到「另一扇门」得到:

Matrix4x4 m = portalB.TransformMatrix
            * flip180
            * portalA.InverseTransformMatrix
            * mainCamera.localToWorldMatrix;
virtualCam.transform.SetPositionAndRotation(m.GetPosition(), m.rotation);

关键:斜裁剪面 (oblique near-plane clipping) 要对齐目标门平面,否则会把门后的墙渲染进来穿帮。两扇门互相可见时会无限递归,需限制深度。

二、物理穿越

  • 克隆体:物体开始进门时在另一扇门生成镜像;
  • 过中点瞬移:质心越过门平面瞬间传送本体并交换速度方向;
  • 速度重定向:出门速度按两门相对旋转重新投影。

设计收获

真正让项目拿奖的是用一个核心机制撑起整套关卡的克制 —— 每关只教一个新用法。

Portals split into two independent problems: looking like you can pass through (rendering) and actually passing through (physics).

1. View rendering

Each portal is a quad textured with a RenderTexture. The virtual camera is positioned by mapping "the main camera relative to this portal" onto "the other portal":

Matrix4x4 m = portalB.TransformMatrix
            * flip180
            * portalA.InverseTransformMatrix
            * mainCamera.localToWorldMatrix;
virtualCam.transform.SetPositionAndRotation(m.GetPosition(), m.rotation);

Key: oblique near-plane clipping must align to the destination portal's plane, or you render the wall behind it. When two portals see each other you get infinite recursion — cap the depth.

2. Physical traversal

  • Clone: spawn a mirror at the other portal as the object enters;
  • Teleport at the midpoint: the instant the center of mass crosses the plane, teleport the body and swap velocity direction;
  • Velocity redirection: re-project exit velocity by the portals' relative rotation.

The design lesson

What won the award was the restraint of building whole levels on one core mechanic — each level teaches exactly one new use.