Camera

显示已弃用

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

未复制

Camera 对象定义了 3D 世界的视图。在运行中的体验中,每个客户端都有自己的 Camera 对象,它位于该客户端的本地 Workspace 中,可通过 Workspace.CurrentCamera 属性访问。

最重要的相机属性是:

  • CFrame 代表相镜头的位置和方向。

  • CameraType 这是被体验的相机脚本阅读的,决定相机应如何在每帧更新。

  • CameraSubject 这是被体验的相机脚本阅读的,决定相机应该跟关注的对象。

  • FieldOfView 表示可观察世界的可见范围。

  • Focus 代表相机正在观察的点。设置此属性很重要,因为某些视觉效果会更详细,并且更频繁地更新,取决于它们与焦点的距离有多近。

请参阅自定义相机以获取更多关于如何调整和自定义相镜头行为的信息。

存储多个相机

请注意,当将 Workspace.CurrentCamera 更改为新的 Camera 时,所有其他 Cameras 都会直接从 Workspace 降级。如果您需要存储多个相机并在需要时间切换之间使用它们,建议将它们存储在 或 下的 中,在其更改时仍然保持不变。

概要

属性

继承自PVInstance属性

方法

继承自PVInstance方法
  • 写入并联

    获取 PVInstance 的枢轴。

  • PivotTo(targetCFrame : CFrame):()

    将 以及所有其子孙 转换为位于指定 的位置,使旋转点现在位于指定的 。

属性

CFrame

读取并联

该属性是 CFrameCamera ,定义其在 3D 世界中的位置和方向。请注意,一些变形,例如使用 VR 设备时头部的旋转,在此属性中不会反映,因此您应该使用 GetRenderCFrame() 来获得相镜头的 "真实" CFrame

您可以通过设置此属性来移动相机。然而,默认相机脚本也设置了它,因此您应该:

  • 将相机 CameraType 设置为 Enum.CameraType.Scriptable ,以便默认相机脚本不会更新相镜头的 CFrame 。这个方法是最简单的,在大多数情况下都被推荐。

  • 完全替换默认相机脚本以替换替代品。这种方法只有在您不需要任何默认摄像头功能的情况下才被推荐。

最直观的方法来位置和方向 Camera 是使用 CFrame.lookAt() 建造器。在以下示例中,Camera 位于 Vector3.new(0, 10, 0) 并面向 Vector3.new(10, 0, 0)


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
local pos = Vector3.new(0, 10, 0)
local lookAtPos = Vector3.new(10, 0, 0)
Workspace.CurrentCamera.CFrame = CFrame.lookAt(pos, lookAtPos)

虽然相机可以按上述方式放置,但你可能想将其动画到从一个 CFrame 移动到另一个顺畅移动。为此,您可以:

  • 使用 RunService:BindToRenderStep()CFrame:Lerp() 方法设置相镜头的位置/方向每帧。

  • 创建并播放一个 Tween 动画,动画相镜头的位置/方向:


    local Players = game:GetService("Players")
    local TweenService = game:GetService("TweenService")
    local Workspace = game:GetService("Workspace")
    local camera = Workspace.CurrentCamera
    camera.CameraType = Enum.CameraType.Scriptable
    local player = Players.LocalPlayer
    local character = player.Character
    if not character or character.Parent == nil then
    character = player.CharacterAdded:Wait()
    end
    local pos = camera.CFrame * Vector3.new(0, 20, 0)
    local lookAtPos = character.PrimaryPart.Position
    local targetCFrame = CFrame.lookAt(pos, lookAtPos)
    local tween = TweenService:Create(camera, TweenInfo.new(2), {CFrame = targetCFrame})
    tween:Play()

CameraSubject

读取并联

CameraSubject 接受各种 Instances 。默认相机脚本对可用设置的响应各不相同:

CameraSubject 无法设置为 nil 。尝试这样做将恢复到其以前的值。

要将 CameraSubject 恢复到默认值,将其设置为本地角色的 Humanoid


local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local localPlayer = Players.LocalPlayer
local camera = Workspace.CurrentCamera
local function resetCameraSubject()
if camera and localPlayer.Character then
local humanoid = localPlayer.Character:FindFirstChildWhichIsA("Humanoid")
if humanoid then
camera.CameraSubject = humanoid
end
end
end

CameraType

读取并联

默认 Roblox 相机脚本具有几个内置行为。设置此属性可以在各种 Enum.CameraType 行为之间切换。请注意,一些摄像头类型需要有效的 CameraSubject 才能正常工作。

默认相机脚本不会移动或更新相机,如果 CameraType 设置为 Enum.CameraType.Scriptable 。了解有关手动定位和校准相机的更多信息,请参阅CFrame

对于所有 设置 除了 ,属性 代表相镜头的位置设置为的对象。

DiagonalFieldOfView

未复制
读取并联

设置相机可以在斜角方向查看多少度(从视窗的一个角落到另一个角落)。请参阅FieldOfView获取更广泛的视查看解释。

请注意,DiagonalFieldOfView 表示可由 Camera 渲染到全屏区域的视野,可能由某些设备上的钮或屏幕截割而被遮蔽。请参阅ViewportSize获取更多信息。

FieldOfView

读取并联

FieldOfView 属性设置相机可以在垂直方向查看察多少度。该属性位于 1120 度之间,默认值为 70 。非常低或非常高的视野不建议使用,因为它们可能会让玩家感到困惑。

请注意,强制执行了统一缩放,这意味着垂直和水平视野总是由屏幕的比例关联。

FieldOfView 建议的使用包括:

  • 减少视野以获得放大的印象,例如使用望远镜时。
  • 当玩家在“奔跑”时增加FOV,以产生缺乏控制的印象。

请注意,FieldOfView 表示可由 Camera 渲染到全屏区域的视野,可能由某些设备上的钮或屏幕截割而被遮蔽。请参阅ViewportSize获取更多信息。

FieldOfViewMode

读取并联

相镜头的 FieldOfView (FOV) 必须更新以反映 ViewportSize 变化。FieldOfViewMode 的值决定哪个 FOV 值将保持不变。

例如,当该属性设置为 Enum.FieldOfViewMode.Vertical 时,视窗大小变更时更新横向FOV,但垂直FOV保持不变。如果此属性设置为 Enum.FieldOfViewMode.Diagonal , 水平和垂直 FOV 都可能被更改以保持斜角 FOV 不变

Focus

读取并联

引擎执行的某些图形操作,例如更新照明,可能需要时间或计算努力来完成。相镜头的 Focus 属性告诉引擎在执行此操作时优先考虑在 3D 空间的哪个区域。例如,动态灯光从对象如 PointLights 可能不会在远离焦点的距离渲染。

默认 Roblox 相机脚本会自动将 Focus 设置为跟随 CameraSubject (通常是 Humanoid )。然而, Focus 自动更新, 当 CameraType 设置为 Enum.CameraType.Scriptable 或默认摄像头脚本未使用时。在这些情况下,您应该在Focus中更新每个框架,使用RunService:BindToRenderStep()Enum.RenderPriority.Camera中。

Focus 没有对相镜头的位置或方向的影响;请参阅 CFrame 获取此内容。

HeadLocked

读取并联

切换是否使用 VR 设备的相机自动跟踪玩家的头部运动。当 true (默认) 时,引擎将 CFrame 与用户头部的 Enum.UserCFrame 结合,渲染带有头部跟踪的玩家视图。视图将在以下 CFrame 中渲染:


local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local headCFrame = UserInputService:GetUserCFrame(Enum.UserCFrame.Head)
headCFrame = headCFrame.Rotation + headCFrame.Position * camera.HeadScale
-- 这将等于相机:获取渲染框架()
local renderCFrame = camera.CFrame * headCFrame

建议不要 禁用 此属性,以下是原因:

  • 如果没有添加相等的头部追踪解决方案,玩家可能会出现运动恶心。
  • Roblox 引擎在 HeadLocked 真实时执行延迟优化。
还看到也看到

HeadScale

读取并联

HeadScale 是使用 VR 时用户对世界的视角缩放。

虚拟现实中 1 格的大小是 0.3 meters / HeadScale ,意味着更大的 HeadScale 值等于用户使用 VR 设备时看起来更小的世界。例如,高度为 1 格的零件似乎高度为 0.6 米给虚拟现实玩家,其 HeadScale0.5 为。

此属性由 VRService.AutomaticScaling 自动控制,以将玩家的视角与其虚拟形象的大小匹配。如果您打算控制 HeadScale 自己或使用自定义角色,切换 VRService.AutomaticScalingEnum.VRScaling.Off

该属性不应与 Humanoid.HeadScale 混淆,后者是一个 NumberValue 对一个 Humanoid 进行缩放控制的父级。

MaxAxisFieldOfView

未复制
读取并联

MaxAxisFieldOfView 属性设置相机可以查看最长视窗轴的多少度。

当最长轴为垂直轴时,该属性的行为方式与 FieldOfView 属性相似。这通常是设备处于横向布置时的情况。在景观布局中,最长轴将是横向轴;在这种情况下,属性描述了 Camera 的横向视野领域。

NearPlaneZ

只读
未复制
读取并联

NearPlaneZ 属性描述相机的近剪平面距离有多远,以学分为单位。靠近剪切平面是坐在镜头前面的几何平面CFrame。在这飞机和相机之间的任何东西都不会渲染,在观察物体在非常短的距离时创建截断视图。NearPlaneZ 的值在不同平台上会变化,目前总是在 -0.1-0.5 之间。

Diagram showing how the NearPlaneZ clips (does not render) 3D content between the plane and the camera.

VRTiltAndRollEnabled

读取并联

此属性切换是否在玩家使用 VR 设备时应用倾斜和滚动的 CFrame 属性。

为了防止运动恶心,地平线应保持平等级。使用 VR 设备时斜倾和滚动玩家的视图可能会导致玩家的物理空间与他们正在查看的虚拟空间之间的连接中断。改变显然的向下方向可能会导致玩家失去平衡或感到头晕。

因此,一般来说,除非您已经广泛测试了体验对这些效果的影响,否则建议禁用此属性。即使启用了倾斜和滚动,您也可能想确保玩家始终拥有稳定的参考框架,例如车辆内部或可以帮助玩家在物理空间中找到自己的地板。

ViewportSize

只读
未复制
读取并联

ViewportSize 返回当前屏幕上设备安全区域的尺寸。该区域是一个长方形,包括 Roblox 顶部栏区,但不包括任何装置槽或屏幕截图。ViewportSize 的单位是 Roblox 用户界面抵消单位,可能与原生显示像素不同。

Mobile device screen with cutout showing device safe area.

如上所述,ViewportSize 不等于带有切割或钮的显示器的全屏区域尺寸。要获得所有显示器的全屏区域大小,您可以查询 AbsoluteSize 属性的 ScreenGuiScreenInsets 设置为 None 。见 Enum.ScreenInsets 获取更多关于如何定义屏幕区域的信息。

最后,请注意,ViewportSize 不是相机在渲染时使用的实际视窗大小 (相机在全屏区域渲染)。此外,FieldOfViewDiagonalFieldOfView 属性基于全屏区,而不是ViewportSize

相机更新

目前由 Camera 引用的只有 Workspace.CurrentCamera 每个框架在 ViewportSize 步骤期间都更新了其 PreRender 。你体验中的所有其他相机的 ViewportSize 不会被更新,包括用于 ViewportFrames 的相机。

方法

GetPartsObscuringTarget

Instances

该方法返回一个 BaseParts 阵列,该阵列抵挡了相镜头的 CFrameVector3 位置在 castPoints 数组列中的视线。任何 Instances 包含在 ignoreList 阵列中的子孙将被忽略,以及它们的后代。

castPoints 参数被视为一个阵列的 Vector3 位置。请注意,返回的 BaseParts 阵列处于随机顺序,并且没有提供额外的射线投射数据。如果您需要数据,例如命中位置、命中材料或表面正常,您应该选择 WorldRoot:Raycast() 方法。


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local castPoints = {
Vector3.new(0, 10, 0),
Vector3.new(0, 15, 0)
}
local ignoreList = {}
local partsObscuringTarget = camera:GetPartsObscuringTarget(castPoints, ignoreList)

如果 遮蔽了投射点, 遮蔽投射点之间的投射点将不会返回。

参数

castPoints: Array

一个阵列的 Vector3 投射点位置。

默认值:""
ignoreList: Instances

一个忽略的 Instances 阵列,包括其子孙。

默认值:""

返回

Instances

一个由 BaseParts 组成的阵列,隐藏了相镜头的 CFramecastPoints 之间的视线。

GetRenderCFrame

该方法返回渲染时的实际 CFrameCamera ,包括 VR 的影响(VR 头部变形不适用于 CFrame 属性,因此最好使用 GetRenderCFrame() 获得玩家的查看图的“真实” CFrame)。

例如,当使用 VR 时,Camera 实际上在以下 CFrame 渲染:


local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local headCFrame = UserInputService:GetUserCFrame(Enum.UserCFrame.Head)
headCFrame = headCFrame.Rotation + headCFrame.Position * camera.HeadScale
renderCFrame = camera.CFrame * headCFrame

相镜头的渲染 CFrame 只会在 HeadLocked 属性为真时才更改,以便计算头部。


返回

正在渲染 CFrameCamera

GetRoll

该方法返回,以 ради安为单位,当前滚动应用于 Camera 使用 SetRoll() 。滚动被定义为围绕相镜头的 Z 轴进行旋转。

该方法仅返回使用 SetRoll() 方法应用的滚动。手动卷轴应用到相镜头的 CFrame 不被计算在内。要获得 Camera 的实际卷轴,包括手动应用的卷轴,您可以使用以下片段:


local Workspace = game:GetService("Workspace")
local function getActualRoll()
local camera = Workspace.CurrentCamera
local trueUp = Vector3.new(0, 1, 0)
local cameraUp = camera:GetRenderCFrame().upVector
return math.acos(trueUp:Dot(cameraUp))
end

返回

目前由 SetRoll() 应用的滚动,以径为单位。

代码示例

LocalScript 中使用此例子时,将检索相机的当前卷在度。然后,如果相机滚动角度不是 20 度,相机滚动角度设置为 20 度。

相机:获取滚动

local currentRoll = math.deg(workspace.CurrentCamera:GetRoll()) -- 获取相机的当前卷在度数。
if currentRoll ~= 20 then
workspace.CurrentCamera:SetRoll(math.rad(20)) -- 如果相机不在 20 度滚动角度,滚动将设置为 20 度。
end

ScreenPointToRay

写入并联

该方法从屏幕上的 2D 位置创建单位 Ray ,用于计算 GUI 插入。该 起源于世界给定深度 (在螺柱) 的 2D 位置的等值 (在螺柱) 。

由于该方法承认图形用户界面插入,因此应用到图形用户界面元素(例如来自顶部栏)的抵消量被计算。这意味着指定的屏幕位置将在顶部栏下的左上角开始。对于没有考虑到 GUI 偏移值的相同方法,请使用 ViewportPointToRay()

由于 Ray 创建的单位射线只有一根螺柱长度,要创建更长的射线,您可以采取以关注中/正在关注行动:


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local length = 500
local unitRay = camera:ScreenPointToRay(100, 100)
local extendedRay = Ray.new(unitRay.Origin, unitRay.Direction * length)

该方法仅适用于当前 Workspace 镜头。其他相机,例如你为 ViewportFrame 创建的相机,初始视区尺寸为 (1, 1) ,只有在你将它们设置为 Workspace.CurrentCamera 后才会进行更新。视窗大小不匹配导致相机返回一个带有错误 Ray.Direction 的射线。

参数

X 轴上,以像素计算屏幕点,用于生成 Ray 。这个位置占据了 GUI 插入。

默认值:""

Y 轴上,以像素计算,屏幕点的位置,用于生成 Ray 。这个位置占用了 GUI 插入。

默认值:""
depth: number

Camera 的深度,以学分计算,用于抵消 Ray 的起源。

默认值:0

返回

一个单位 , 起源于与给定屏幕坐标在给定深度相等的世界位置 。这个射线沿着 Camera 的方向进行了定向。

SetRoll

()

该方法已过时,不再被视为最佳实践。

这个方法设置了 Camera 的当前滚动,以径为单位。卷在 CFrame 之后应用,代表着相镜头的 Z 轴周围的旋转。

例如,以下将反转 Camera :


local Workspace = game:GetService("Workspace")
Workspace.CurrentCamera:SetRoll(math.pi) -- math.pi radians = 180 degrees

设置滚动对使用 CFrame 属性应用的任何滚动没有影响。使用 SetRoll 滚动应用的结果并不反映在 CFrame 属性中,但反映在 CFrameGetRenderCFrame() 返回的。

此方法只能在 CameraType 设置为 Scriptable 时使用,无论默认相机脚本是否被使用。如果与其他 CameraType 一起使用,在输出中将提供警告。

使用此方法应用的任何滚动将在 CameraTypeScriptable 更改时丢失。

使用此方法获得滚动集使用 GetRoll()

由于此方法已过时,建议您使用 Camera 属性来应用滚动到 CFrame 。例如:


local Workspace = game:GetService("Workspace")
local currentCFrame = Workspace.CurrentCamera.CFrame
local rollCFrame = CFrame.Angles(0, 0, roll)
Workspace.CurrentCamera.CFrame = currentCFrame * rollCFrame

参数

rollAngle: number

在 radians 中应用到 Camera 的滚动角度。

默认值:""

返回

()

ViewportPointToRay

写入并联

该方法创建一个单位 Ray 从设备安全视窗坐标系中的 2D 位置,定义为像素。射线起源于世界的 2D 位置在给定的深度 (以学分计) 远离 。

如下图所示,(0, 0) 对应 Roblox 顶部栏的左上角。这意味着输入 2D 位置不会 考虑插入 CoreUISafeInsets,但它会考虑任何 DeviceSafeInsets

Diagram showing the origin of the device safe area viewport coordinate system.

注意,用户界面实例使用不同的坐标系统(GuiObject.AbsolutePosition 使用的是 CoreUISafeInsets 视窗坐标系统,而这个方法使用的是 DeviceSafeInsets 视窗坐标系统)。如果您想在核心 UI 坐标系中指定位置,请使用 ScreenPointToRay()

请注意,此方法仅适用于 Workspace.CurrentCamera 镜头机。其他相机,例如你为 ViewportFrame 创建的相机,初始视区尺寸为 (1, 1) ,只有在你将它们设置为 CurrentCamera 后才会进行更新。视窗大小不匹配导致相机返回一个错误的射线Ray.Direction

这种方法可以与 ViewportSize 属性一起使用,以从屏幕中心创建射线,例如:


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local viewportPoint = camera.ViewportSize / 2
local unitRay = camera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y, 0)

由于 Ray 创建的单位射线只有一根螺柱长度,要创建更长的射线,您可以采取以关注中/正在关注行动:


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local length = 500
local unitRay = camera:ScreenPointToRay(100, 100)
local extendedRay = Ray.new(unitRay.Origin, unitRay.Direction * length)

参数

X 轴上,以像素计算,视窗点的位置,用于产生 Ray ,在设备安全区域坐标。

默认值:""

Y 轴上,以像素计算的视窗点的位置,用于产生 Ray ,在设备安全区域坐标。

默认值:""
depth: number

Camera 的深度,以学分计算,用于抵消 Ray 的起源。

默认值:0

返回

一个单位 , 起源于与给定视窗坐标在给定深度相等的世界位置 。这个射线沿着 Camera 的方向进行了定向。

WorldToScreenPoint

写入并联

该方法返回 Vector3 worldPoint 屏幕位置和深度以及该点是否在屏幕边界内。

该方法考虑了当前的图形用户界面插入,例如顶部栏占用的空间,因此返回的 2D 位置与图形用户界面位置相同,可用于放置图形用户界面元素。对于忽略 GUI 插入的相同方法,请参阅 WorldToViewportPoint()


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local worldPoint = Vector3.new(0, 10, 0)
local vector, onScreen = camera:WorldToScreenPoint(worldPoint)
local screenPoint = Vector2.new(vector.X, vector.Y)
local depth = vector.Z

请注意,该方法不进行任何射线投射,指示是否 worldPoint 是否在屏幕边界内的 boolean 将是 true 无论点是否被 BasePartsTerrain 遮蔽。

参数

worldPoint: Vector3

Vector3 世界位置。

默认值:""

返回

包含以下顺序的 tuple:

  • 一个 其 X 和 Y 组件代表屏幕左上角的偏移,以像素计算。 Z 组件代表屏幕深度(以学分表示)。

  • 一个 bool 指示如果 worldPoint 是否在屏幕边界内。

WorldToViewportPoint

写入并联

该方法返回 Vector3 worldPoint 屏幕位置和深度以及该点是否在屏幕边界内。

该方法不考虑当前的图形用户界面插入,例如顶部栏占用的空间,意味着返回的 2D 位置来自视图的左上角。除非你正在使用 ScreenGui.IgnoreGuiInset , 这个位置不适合放置图形用户界面元素。

对于其他与插入图形用户界面相同的方法,请参阅WorldToScreenPoint()


local Workspace = game:GetService("Workspace")
local camera = Workspace.CurrentCamera
local worldPoint = Vector3.new(0, 10, 0)
local vector, onScreen = camera:WorldToViewportPoint(worldPoint)
local viewportPoint = Vector2.new(vector.X, vector.Y)
local depth = vector.Z

请注意,该方法不进行任何射线投射,指示是否 worldPoint 是否在屏幕边界内的 boolean 将是 true 无论点是否被 BasePartsTerrain 遮蔽。

参数

worldPoint: Vector3

Vector3 世界位置。

默认值:""

返回

包含以下顺序的 tuple:

  • 一个 其 X 和 Y 组件代表从视图左上角的偏移,以像素计算。 Z 组件代表屏幕深度(以学分表示)。

  • 一个 bool 指示如果 worldPoint 是否在屏幕边界内。

ZoomToExtents

()

参数

boundingBoxCFrame: CFrame
默认值:""
boundingBoxSize: Vector3
默认值:""

返回

()

活动

InterpolationFinished

Camera 使用 Camera:Interpolate() 方法完成了插值时,此事件发生。如果因为 Camera:Interpolate() 再次调用而中断了青少年,它不会发射。

建议您使用 TweenService 来动画 Camera ,因为它更可靠且提供更多减轻风格的选项。