一个 CFrame,即 坐标帧 的缩写,是一种用于旋转和定位 3D 对象的数据类型。作为对象属性或独立单元,CFrame 包含全局的 X、Y 和 Z 坐标以及每个轴的旋转数据。此外,CFrames 包含一些有助于处理 3D 空间中对象的实用函数。
定位 CFrame
您可以通过使用 CFrame.new() 在默认位置 (0, 0, 0) 创建一个空的 CFrame。要将 CFrame 置于特定点,请将 X、Y 和 Z 坐标作为参数提供给 CFrame.new()。在以下示例中,redBlock 部件的 CFrame 属性更改为 newCFrame,将其重新定位到 (-2, 2, 4)。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlock-- 创建新的 CFramelocal newCFrame = CFrame.new(-2, 2, 4)-- 用新的 CFrame 覆盖红色方块的当前 CFrameredBlock.CFrame = newCFrame


或者,您可以将新的 Vector3 位置提供给 CFrame.new(),并实现相同的结果:
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlock-- 创建新的 CFramelocal newVector3 = Vector3.new(-2, 2, 4)local newCFrame = CFrame.new(newVector3)-- 用新的 CFrame 覆盖红色方块的当前 CFrameredBlock.CFrame = newCFrame
旋转 CFrame
要创建一个旋转的 CFrame,使用 CFrame.fromEulerAnglesXYZ() 构造函数,并提供所需轴的旋转角度(单位为弧度)。CFrame.fromEulerAnglesXYZ() 的参数是弧度而不是度数;如果您更喜欢度数,请使用 math.rad() 将度数转换为弧度。在以下示例中,redBlock 部件在其 Y 轴上逆时针旋转 45 度。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlock-- 创建新的旋转 CFramelocal newCFrame = CFrame.fromEulerAnglesXYZ(0, math.rad(45), 0)-- 用新的 CFrame 覆盖红色方块的当前 CFrameredBlock.CFrame = newCFrame


使 CFrame 面向某一点
您可以使用 CFrame.lookAt() 将 CFrame 的前表面指向世界中的特定点。以下示例将 redBlock 定位在 (0, 3, 0),并将其前表面(以白色圆圈标记)指向 blueCube 部件。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlocklocal blueCube = Workspace.BlueCuberedBlock.Position = Vector3.new(0, 3, 0)-- 将红方块的前表面指向蓝方块redBlock.CFrame = CFrame.lookAt(redBlock.Position, blueCube.Position)


偏移 CFrame
要将对象偏移特定数量的单位(studs)从其当前位置信息,可以在对象的位置上加或减一个 Vector3,创建一个新的 CFrame。要获取对象适合格式化的 Vector3 位置以供使用 CFrame.new(),如这里所示,可以使用其 Position 属性(redBlock.Position)作为便捷的捷径。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlockredBlock.CFrame = CFrame.new(redBlock.Position) + Vector3.new(0, 1.25, 0)


您可以使用相同的技术从另一个对象的位置偏移对象。在以下示例中,一个 Vector3 添加到在蓝色方块位置创建的新 CFrame 中,而不是方块自身的位置。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlocklocal blueCube = Workspace.BlueCuberedBlock.CFrame = CFrame.new(blueCube.Position) + Vector3.new(0, 2, 0)


动态 CFrame 定向
CFrame.new() 和 CFrame.fromEulerAnglesXYZ() 构造函数在世界中以特定方向重新定位或旋转对象,但有时您无法依赖固定的世界位置和旋转角度。例如:
- 将漂浮的宝藏放置在某个玩家面前,而玩家可能在任何方向上站立。
- 使魔法精灵出现在玩家的右肩上方。
在这些情况下,使用 CFrame 方法而不是它们的构造函数。
相对位置
CFrame:ToWorldSpace() 函数将对象的 CFrame 转换为新的 世界 定向,同时尊重其自身的本地定向。这使其在相对于自身或其他对象进行偏移时非常理想,而不管其当前如何定位/旋转。
在以下示例中,redBlock 部件在蓝色方块的 Y 轴相对偏移 2 个单位(绿色箭头穿过它),而不是相对于全局 Y 轴直向上方。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlocklocal blueCube = Workspace.BlueCubelocal offsetCFrame = CFrame.new(0, 2, 0)redBlock.CFrame = blueCube.CFrame:ToWorldSpace(offsetCFrame)


相对旋转
您还可以使用 CFrame:ToWorldSpace() 为对象进行相对旋转。在以下示例中,redBlock 部件在其 Y 轴上逆时针旋转 70 度,并在其 Z 轴上顺时针旋转 20 度。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlocklocal rotatedCFrame = CFrame.fromEulerAnglesXYZ(0, math.rad(70), math.rad(20))redBlock.CFrame = redBlock.CFrame:ToWorldSpace(rotatedCFrame)


使特定表面面向某一点
您可以通过将 Vector3 点作为第二个参数传递给 CFrame.new(),使对象的前面朝向另一个对象。您还可以使用相对旋转,使对象的任何面指向 Vector3 点。以下示例执行两个连续的 CFrame 操作:
- 将 前 表面(以白色圆圈标记)指向目标。
- 相对旋转 CFrame,使 顶部 表面(以黑色圆圈标记)指向目标。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlocklocal blueCube = Workspace.BlueCube-- 将红色方块的前表面指向蓝色方块redBlock.CFrame = CFrame.lookAt(redBlock.Position, blueCube.Position)-- 相对旋转 CFrame,使顶部表面(而不是前面)指向蓝色方块local rotatedCFrame = CFrame.fromEulerAnglesXYZ(math.rad(-90), 0, 0)redBlock.CFrame = redBlock.CFrame:ToWorldSpace(rotatedCFrame)


在两点之间查找点
您可以使用 线性插值,或称 lerp,在两个点之间定位 CFrame。在以下示例中,redBlock 部件在 greenCube 和 cyanCube 部件之间重新定位。值 0.7 使其位于距离绿色方块 70% 的位置。
local Workspace = game:GetService("Workspace")local redBlock = Workspace.RedBlocklocal greenCube = Workspace.GreenCubelocal cyanCube = Workspace.CyanCuberedBlock.CFrame = greenCube.CFrame:Lerp(cyanCube.CFrame, 0.7)

