Manuals
Manuals




This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English

摄像机

Defold中的摄像机是一种改变游戏世界视口和投影的组件。摄像机组件定义了一个基本的透视或正交摄像机,它为渲染脚本提供视图和投影矩阵。

透视摄像机通常用于3D游戏,其中摄像机的视图以及物体的大小和透视基于视锥体以及从摄像机到游戏中物体的距离和视角。

对于2D游戏,通常希望使用正交投影来渲染场景。这意味着摄像机的视图不再由视锥体决定,而是由一个立方体决定。正交投影是不现实的,因为它不会根据物体的距离改变物体的大小。一个1000单位远的物体将与摄像机正前方的物体以相同的大小渲染。

projections

创建摄像机

要创建摄像机,右键点击一个游戏对象并选择Add Component ▸ Camera。您也可以在项目层次结构中创建一个组件文件,并将该组件文件添加到游戏对象中。

create camera component

摄像机组件具有以下定义摄像机视锥体的属性:

camera settings

Id
组件的ID
Aspect Ratio
(仅透视摄像机) - 视锥体宽度和高度之间的比率。1.0表示您假设的是方形视图。1.33适用于4:3视图,如1024x768。1.78适用于16:9视图。如果设置了自动宽高比,则此设置将被忽略。
Fov
(仅透视摄像机) - 以_弧度_表示的摄像机垂直视野。视野越宽,摄像机将看到的内容越多。
Near Z
近裁剪平面的Z值。
Far Z
远裁剪平面的Z值。
Auto Aspect Ratio
(仅透视摄像机) - 设置此项以让摄像机自动计算宽高比。
Orthographic Projection
设置此项以将摄像机切换到正交投影(见下文)。
Orthographic Zoom
(仅正交摄像机) - 用户控制的缩放倍数(> 1 = 放大,< 1 = 缩小)。在 Fixed 模式下,它就是有效缩放。在 Auto FitAuto Cover 模式下,它会与自动计算的缩放相乘,因此无需禁用自动调整即可应用额外缩放。
Orthographic Mode
(仅正交摄像机) - 控制正交摄像机如何根据窗口大小和设计分辨率(game.project 中的 display.width/height 值)确定缩放。
  • Fixed(使用固定缩放):直接使用当前 Orthographic Zoom 值。
  • Auto Fit(包含):自动计算缩放,使完整设计区域适配窗口,然后与 Orthographic Zoom 相乘。侧边或上下可能显示额外内容。
  • Auto Cover(覆盖):自动计算缩放,使设计区域覆盖整个窗口,然后与 Orthographic Zoom 相乘。侧边或上下可能被裁剪。 仅在启用 Orthographic Projection 时可用。

使用摄像机

所有摄像机都会在帧期间自动启用和更新,并且lua camera模块在所有脚本上下文中都可用。自Defold 1.8.1起,不再需要通过向摄像机组件发送acquire_camera_focus消息来显式启用摄像机。旧的获取和释放消息仍然可用,但建议改为使用enabledisable消息,就像您希望启用或禁用的任何其他组件一样:

msg.post("#camera", "disable")
msg.post("#camera", "enable")

要列出所有当前可用的摄像机,您可以使用camera.get_cameras()

-- 注意:渲染调用仅在渲染脚本中可用。
--       camera.get_cameras()函数可以在任何地方使用,
--       但render.set_camera只能在渲染脚本中使用。

for k,v in pairs(camera.get_cameras()) do
    -- 摄像机表包含所有摄像机的URL
    render.set_camera(v)
    -- 在这里进行渲染 - 这里渲染的任何使用指定了
    -- 视图和投影矩阵的材质的内容,都将使用来自摄像机的矩阵。
end
-- 要禁用摄像机,将nil(或根本不传递参数)传递给render.set_camera。
-- 此调用后,所有渲染调用将使用在渲染上下文中指定的
-- 视图和投影矩阵(render.set_view和render.set_projection)
render.set_camera()

脚本camera模块有多个可用于操作摄像机的函数。这里只是几个可以使用的函数,要查看所有可用函数,请查阅API文档中的手册。

camera.get_aspect_ratio(camera) -- 获取宽高比
camera.get_far_z(camera) -- 获取远z值
camera.get_fov(camera) -- 获取视野
camera.get_orthographic_zoom(camera) -- 获取用户控制的缩放倍数
camera.get_orthographic_auto_zoom(camera) -- 获取自动计算的缩放
camera.set_aspect_ratio(camera, ratio) -- 设置宽高比
camera.set_far_z(camera, far_z) -- 设置远z值
camera.set_near_z(camera, near_z) -- 设置近z值
... 等等

摄像机通过URL标识,它是组件的完整场景路径,包括集合、它所属的游戏对象和组件ID。在这个例子中,您将使用URL /go#camera 来从同一集合中标识摄像机组件,而在从不同集合或渲染脚本访问摄像机时使用 main:/go#camera

create camera component

-- 从同一集合中的脚本访问摄像机:
camera.get_fov("/go#camera")

-- 从不同集合中的脚本访问摄像机:
camera.get_fov("main:/go#camera")

-- 从渲染脚本访问摄像机:
render.set_camera("main:/go#camera")

每帧,当前具有摄像机焦点的摄像机组件将向@render套接字发送set_view_projection消息:

-- builtins/render/default.render_script
--
function on_message(self, message_id, message)
    if message_id == hash("set_view_projection") then
        self.view = message.view                    -- [1]
        self.projection = message.projection
    end
end
  1. 从摄像机组件发布的消息包括一个视图矩阵和一个投影矩阵。

摄像机组件根据摄像机的正交投影属性为渲染脚本提供透视或正交投影矩阵。投影矩阵还考虑了定义的近和远裁剪平面、摄像机的视野和宽高比设置。

摄像机提供的视图矩阵定义了摄像机的位置和方向。具有正交投影的摄像机将视图居中在它所附加的游戏对象的位置上,而具有透视投影的摄像机将视图的左下角定位在它所附加的游戏对象上。

渲染脚本

从Defold 1.9.6开始,当使用默认渲染脚本时,Defold将自动设置应使用的最后启用的摄像机。在此更改之前,项目中的某个脚本需要显式地向渲染器发送use_camera_projection消息,以通知它应使用摄像机组件的视图和投影。这不再必要,但为了向后兼容性,仍然可以这样做。

或者,您可以在渲染脚本中设置应使用的特定摄像机。这在需要更具体控制应使用哪个摄像机进行渲染的情况下可能很有用,例如在多人游戏中。

-- render.set_camera将自动使用视图和投影矩阵
-- 用于任何渲染,直到调用render.set_camera()。
render.set_camera("main:/my_go#camera")

要检查摄像机是否处于活动状态,您可以使用摄像机API中的get_enabled函数:

if camera.get_enabled("main:/my_go#camera") then
    -- 摄像机已启用,使用它进行渲染!
    render.set_camera("main:/my_go#camera")
end

要将set_camera函数与视锥体剔除一起使用,您需要将此作为选项传递给函数: render.set_camera("main:/my_go#camera", {use_frustum = true})

平移摄像机

您通过移动摄像机组件所附加到的游戏对象来在世界中平移/移动摄像机。摄像机组件将根据摄像机的当前x和y轴位置自动发送更新的视图矩阵。

缩放摄像机

使用透视摄像机时,您可以通过沿z轴移动摄像机所附加到的游戏对象来放大和缩小。摄像机组件将根据摄像机的当前z位置自动发送更新的视图矩阵。

使用正交摄像机时,您可以在编辑器或运行时通过更改摄像机的 Orthographic Zoom 属性来放大和缩小:

-- 在 Fixed 模式下,这就是有效缩放。
go.set("#camera", "orthographic_zoom", 2)

Auto FitAuto Cover 模式下,Orthographic Zoom 会应用在自动计算的缩放之上,而不会被忽略。例如,在编辑器中将 Orthographic Mode 设为 Auto Fit,将 Orthographic Zoom 设为 1.25,可先让设计区域适配窗口,再额外放大 25%。等效的运行时设置为:

camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_FIT)
go.set("#camera", "orthographic_zoom", 1.25)

local auto_zoom = camera.get_orthographic_auto_zoom("#camera")
local zoom_multiplier = camera.get_orthographic_zoom("#camera")
local effective_zoom = auto_zoom * zoom_multiplier

camera.get_orthographic_auto_zoom()Auto FitAuto Cover 模式下返回根据当前窗口和项目尺寸计算的缩放,在 Fixed 模式下返回 1.0。同一数值也可通过只读组件属性 orthographic_auto_zoom 获取:

local auto_zoom = go.get("#camera", "orthographic_auto_zoom")

使用正交摄像机时,您还可以通过 Orthographic Mode 设置或脚本切换缩放的确定方式:

-- 获取当前模式(camera.ORTHO_MODE_FIXED、_AUTO_FIT、_AUTO_COVER 之一)
local mode = camera.get_orthographic_mode("#camera")

-- 切换到 auto-fit(包含),始终保持完整设计区域可见
camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_FIT)

-- 切换到 auto-cover,确保设计区域覆盖窗口
camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_COVER)

-- 切换到 fixed 模式,不使用自动调整而直接使用 orthographic_zoom
camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_FIXED)

自适应缩放

自适应缩放背后的概念是当显示分辨率从game.project中设置的初始分辨率改变时调整摄像机缩放值。

自适应缩放的两种常见方法是:

  1. 最大缩放 - 计算一个缩放值,使得game.project中初始分辨率所覆盖的内容将填充并扩展到屏幕边界之外,可能会隐藏侧面或上方和下方的一些内容。
  2. 最小缩放 - 计算一个缩放值,使得game.project中初始分辨率所覆盖的内容将完全包含在屏幕边界内,可能会在侧面或上方和下方显示额外内容。

示例:

local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")

function init(self)
    local initial_zoom = go.get("#camera", "orthographic_zoom")
    local display_scale = window.get_display_scale()
    window.set_listener(function(self, event, data)
        if event == window.WINDOW_EVENT_RESIZED then
            local window_width = data.width
            local window_height = data.height
            local design_width = DISPLAY_WIDTH / initial_zoom
            local design_height = DISPLAY_HEIGHT / initial_zoom

            -- 最大缩放:确保初始设计尺寸将填充并扩展到屏幕边界之外
            local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale

            -- 最小缩放:确保初始设计尺寸将缩小并包含在屏幕边界内
            --local zoom = math.min(window_width / design_width, window_height / design_height) / display_scale
            
            go.set("#camera", "orthographic_zoom", zoom)
        end
    end)
end

自适应缩放的完整示例可以在此示例项目中看到。

注意:使用正交摄像机时,现在可以通过将 Orthographic Mode 设置为 Auto Fit(包含)或 Auto Cover(覆盖)来实现包含/覆盖行为,而无需自定义代码。在这些模式下,根据窗口大小和设计分辨率计算的缩放会与 Orthographic Zoom 相乘。

跟随游戏对象

您可以通过将摄像机组件所附加到的游戏对象设置为要跟随的游戏对象的子对象来使摄像机跟随游戏对象:

follow game object

另一种方法是每帧更新摄像机组件所附加到的游戏对象的位置,随着要跟随的游戏对象移动。

在屏幕坐标与世界坐标之间转换

当摄像机发生平移、缩放或更改投影后,输入坐标便不再直接对应世界坐标。请将摄像机转换函数与 action.screen_xaction.screen_y 一起使用。如果省略可选的摄像机 URL,则使用最后启用的摄像机。

对于正交摄像机,camera.screen_xy_to_world() 返回摄像机近平面上与屏幕像素对应的世界空间点:

function on_input(self, action_id, action)
    if action_id == hash("touch") and action.pressed then
        local world_position = camera.screen_xy_to_world(
            action.screen_x, action.screen_y, "#camera")
        go.set_position(world_position, "/marker")
    end
end

对于透视摄像机,camera.screen_to_world() 接受一个 vector3,其 Z 分量是从摄像机平面测量的世界单位视图深度:

local depth = 10
local world_position = camera.screen_to_world(
    vmath.vector3(action.screen_x, action.screen_y, depth), "#camera")

camera.world_to_screen() 执行反向转换。它返回屏幕像素 X 和 Y,并在 Z 中使用相同的视图深度约定,因此其结果可以传回 camera.screen_to_world()

-- Update the cached world transform first if the object moved this frame.
go.update_world_transform("/marker")
local world_position = go.get_world_position("/marker")
local screen_position = camera.world_to_screen(world_position, "#camera")

请访问示例页面查看坐标转换的实际用法。另有一个示例项目展示相同的 API。

本手册中提到的第三方摄像机解决方案提供了用于屏幕坐标之间转换的函数。

运行时操作

您可以通过多种不同的消息和属性在运行时操作摄像机(请参阅API文档以了解用法)。

摄像机有许多不同的属性可以使用go.get()go.set()进行操作:

fov
摄像机视野(number)。
near_z
摄像机近Z值(number)。
far_z
摄像机远Z值(number)。
orthographic_zoom
用户控制的正交摄像机缩放倍数。在 Auto FitAuto Cover 模式下,它会与 orthographic_auto_zoom 相乘。(number)。
orthographic_auto_zoom
Auto FitAuto Cover 模式下计算出的正交缩放;在 Fixed 模式下为 1.0。只读。(number)。
aspect_ratio
Defold 1.4.8中添加。视锥体宽度和高度之间的比率。用于计算透视摄像机的投影。(number)。
view
Defold 1.4.8中添加。摄像机的计算视图矩阵。只读。(matrix4)。
projection
Defold 1.4.8中添加。摄像机的计算投影矩阵。只读。(matrix4)。

第三方摄像机解决方案

有社区制作的摄像机解决方案实现了常见功能,如屏幕抖动、跟随游戏对象、屏幕到世界坐标转换等等。它们可以从Defold资产门户下载: