VRCCameraSettings
通过以下列出的 API 暴露关于用户屏幕相机、手持相机和 Unity 全局质量设置的信息和有限控制。
你可以通过以下静态访问器访问此类的 2 个实例:
VRCCameraSettings.ScreenCamera:用户的屏幕相机,即渲染当前视图的相机(如果用户使用 VR,则将是立体相机)VRCCameraSettings.PhotoCamera:用户的手持拍照相机。请注意,此实例上的属性仅在用户启用相机时更新,你可以使用Active属性来检查。另请注意,此属性始终指向渲染预览图像的相机,而不是用于拍照本身或渲染流媒体相机视图的相机(尽管大多数属性在按下快门时会从这些相机同步或同步到这些相机)。- ⚠️ 在 ClientSim 中,此属性将为
null,因为没有可用的拍照相机。在实际的 VRChat 客户端中,它永远不会为null。
- ⚠️ 在 ClientSim 中,此属性将为
note
这两个属性在底层可能并不总是指向单个真实的 Camera 组件。VRChat 为你抽象了一些复杂性,你永远不需要担心这一点。但为完整起见,请注意以下几点:
- 在
VRCCameraSettings.ScreenCamera上更改属性时,聚焦视图相机将受到影响。 - 同样,在"流媒体相机"模式下打开手持相机时使用的组件在访问
VRCCameraSettings.PhotoCamera时会受到影响。 VRCCameraSettings.PhotoCamera也链接到 Dolly Multi Cam 设置中使用的所有相机,尽管某些属性(如FieldOfView)可能不同。在这种情况下,将返回第一个相机的设置。
对于高级用例,可以通过 CameraMode 属性读取此状态。
公开属性
这些实例将暴露 Unity 的 Camera 类的某些属性(你可以参考 Unity 文档了解这些属性的详细信息)。请注意,出于安全原因,你将无法访问原始的 Camera 组件。但是,对于手动放置在世界中的组件,Camera 类是暴露的。
目前以只读方式公开:
Vector3 Position:世界空间位置Quaternion Rotation:世界空间旋转Vector3 Forward:世界空间前向向量,方便使用Vector3 Up:世界空间上向向量,方便使用Vector3 Right:世界空间右向向量,方便使用int PixelWidth和int PixelHeight:当前渲染目标的大小(像素)(可能受 VR 超级采样设置 影响)float Aspect:渲染目标的当前宽高比float FieldOfView:相机的当前_垂直_视野(对于 VR 用户可能不准确)bool Active:相机是否正在渲染。对于ScreenCamera始终为 true,对于通过PhotoCamera检测手持相机很有用。在启用 Spout 流式传输时,PhotoCamera也为此返回true。bool StereoEnabled:如果用户处于 VR 中,则ScreenCamera返回true。建议使用 Player API 检测 VR 用户。
note
如果 Active 为 false,则 Position 和 Rotation 等变换数据将全部为 0。Forward/Up/Right 在这种情况下将分别返回 Vector3.forward/up/right。
目前以读写方式公开:
float NearClipPlane和float FarClipPlane:你可以在运行时调整相机的裁剪面。这与通过场景描述符中的参考相机设置它们有 类似的限制:NearClipPlane可能会受到用户"强制相机近裁面距离"设置的影响。你可以在设置后通过回读值来检测是否发生了这种情况。NearClipPlane将在0.001和0.05之间被钳制FarClipPlane最低只能设置为比NearClipPlane高0.1,这将被钳制- 如果用户将"强制相机近裁面距离"设置为"动态",调整
FarClipPlane也可能调整NearClipPlane
bool AllowHDR:相机是否将向渲染目标提交 HDR 值DepthTextureMode DepthTextureMode:可用于启用相机深度纹理渲染,这对某些着色器效果很有用。此属性可以替代启用了阴影的实时灯光来强制生成相机深度纹理。但请注意,场景中存在这样的灯光不会改变DepthTextureMode属性,这意味着从此属性读取None值并_不_意味着场景中没有强制进行深度渲染的深度灯光。PhotoCamera始终启用DepthTextureMode.Depth,你不能禁用它,但可以附加添加其他选项。bool UseOcclusionCulling:相机在渲染期间是否使用遮挡剔除。默认为true,但仅当你的世界已烘焙遮挡数据时才有效果。bool AllowMSAA:如果设置为false,则禁用此相机上的所有 MSAA(抗锯齿),无论用户设置如何。默认为true,此时将使用用户的图形设置。LayerMask CullingMask:设置主相机要渲染的层。此属性的 setter 将对除ScreenCamera之外的任何对象抛出异常。任何"保留"的层、MirrorReflection和InternalUI都无法更改。请注意,在某些平台上,由于相机堆叠,InternalUI即使可见也可能读取为 0。CameraClearFlags ClearFlags:设置渲染此相机时使用的背景清除模式。Color BackgroundColor:当ClearFlags设置为SolidColor时使用的颜色。
bool LayerCullSpherical:参见 Unity 文档。此 API 目前在 Udon 中已禁用,因为它会导致 UI 剔除问题。设置它无任何效果。float[] LayerCullDistances:参见 Unity 文档。数组必须有 32 个条目,对应 GameObject 层。某个层的值为0表示它将使用FarClipPlane的值。将此属性设置为null等同于为每一层传递0。- 与
FarClipPlane一样,这将被钳制到最小值NearClipPlane + 0.1。任何"保留"的层和InternalUI都无法更改,并将始终读取为0。
- 与
相机模式
CameraMode 属性在 ScreenCamera 和 PhotoCamera 上可用。
ScreenCamera 有以下相机模式:
| 模式 | 描述 |
|---|---|
| Screen | 渲染用户当前视图的默认模 式。 |
| FocusView | 用户在移动设备上处于焦点视图时激活。 |
PhotoCamera 有以下相机模式:
| 模式 | 描述 |
|---|---|
| PhotoOrVideo | 相机处于照片或流模式。包括表情和贴纸等模式。 |
| 相机启用了"打印"皮肤。 | |
| DroneHandheld | 相机处于无人机模式。 |
| DroneFPV | 用户正在以 FPV 模式飞行无人机。 |
| Unknown | 当 Active 为 false 时设置。 |
静态函数
对于 VR 用户最有用,VRCCameraSettings 暴露了 2 个静态函数:
Vector3 GetEyePosition(Camera.StereoscopicEye eye):返回指定眼睛的世界空间位置。对于非 VR 用户,等同于ScreenCamera.Position。Quaternion GetEyeRotation(Camera.StereoscopicEye eye):返回指定眼睛的世界空间旋转。对于非 VR 用户,等同于ScreenCamera.Rotation。
此外,还有一个通用函数:
void GetCurrentCamera(out VRCCameraSettings internalComponent, out Camera externalComponent):这是 Camera.current 的替代方法,该方法仅在渲染事件期间填充。- 当已知的内部相机正在渲染时,
internalComponent将包含VRCCameraSettings.ScreenCamera或VRCCameraSettings.PhotoCamera,而externalComponent将为null。 - 当世界中的自定义相机正在渲染时,
internalComponent将为null,而externalComponent将包含UnityEngine.Camera组件。 - 当
Camera.current为null时,两个结果都将为null,_或者_当 Udon 无法访问的相机正在渲染时(例如 Avatar 上的UnityEngine.Camera)。⚠️ 即使没有 Avatar 相机,此函数也可能在任何时候为两个结果返回null,即使在渲染事件期间也是如此。这是因为 VRChat 使用了一些内部渲染步骤,例如内置菜单。请确保在 Udon 脚本中处理这种情况!
- 当已知的内部相机正在渲染时,
更改事件
当用户更改某些图形设置(例如"近裁剪面覆盖")时,会触发 OnVRCCameraSettingsChanged 事件。
此事件可能会每帧触发,甚至每帧多次触发。建议进行最少的处理以避免影响性能。
示例
- Udon Graph
- UdonSharp

using TMPro;
using UdonSharp;
using UnityEngine;
using UnityEngine.UI;
using VRC.SDK3.Rendering;
public class CameraInfoDisplay : UdonSharpBehaviour
{
[SerializeField] private TextMeshProUGUI info;
void Start()
{
// call it once to initialize
OnVRCCameraSettingsChanged(VRCCameraSettings.ScreenCamera);
Debug.Log($"Started CameraInfoDisplay at resolution of {VRCCameraSettings.ScreenCamera.PixelWidth}x{VRCCameraSettings.ScreenCamera.PixelHeight}");
Debug.Log($"The handheld photo camera is {(VRCCameraSettings.PhotoCamera.Active ? "enabled" : "disabled")}");
}
// will be called if resolution or a couple other properties change
public override void OnVRCCameraSettingsChanged(VRCCameraSettings camera)
{
// ignore handheld photo camera
if (camera != VRCCameraSettings.ScreenCamera)
return;
info.text = $"{camera.PixelWidth}x{camera.PixelHeight} fov={camera.FieldOfView} frame={Time.frameCount}°";
}
}