CFrames

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

一个 CFrame ,简称 坐标框架 ,是用于旋转和定位 3D 对象的数据类型。作为对象属性或独立单元,CFrame 包含全球 x-, y-, 和 z-坐标以及每个轴的旋转数据。此外,CFrames 包含有助于在 3D 空间处理对象的有用功能。

游戏中的一些 CFrame 应用示例可能是:

  • 找到一个项目的远离目标点,例如玩家激光发射器瞄准的敌人位置。
  • 移动相机以便它专注于特定的 NPC 作为玩家与之交互。
  • 直接将状态指示放在玩家的头顶上,显示他们是否被麻痹、强化、中毒等

CFRame 基础

放置一个 CFrame

您可以使用 CFrame.new() 在默认位置(0, 0, 0)创建一个空的 CFrame 。要在特定位置放置 CFrame ,请向 CFrame.new() 提供 x-, y-, 和 z-坐标作为参数。在以下示例中,redBlock部分的CFrame属性更改为newCFrame,重新定位为(-2,2,4)


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
-- 创建新的 CFrame
local newCFrame = CFrame.new(-2, 2, 4)
-- 用新的 CFrame 覆盖红块的当前 CFrame
redBlock.CFrame = newCFrame

之前
>

之后
>

或者,你可以提供一个新的 Vector3 位置给 CFrame.new() 并获得相同的结果:


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
-- 创建新的 CFrame
local newVector3 = Vector3.new(-2, 2, 4)
local newCFrame = CFrame.new(newVector3)
-- 用新的 CFrame 覆盖红块的当前 CFrame
redBlock.CFrame = newCFrame

旋转一个 CFrame

要创建旋转的 CFrame ,请使用 CFrame.Angles() 建造器,为所需的轴提供以径为单位的旋转角度。CFrame.Angles() 的参数是在 ради度,不是度。如果你喜欢度数,使用 math.rad() 将度数转换为 ради度。在以下示例中, redBlock 部分在其 y 轴上旋转 45 度逆时针。


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
-- 创建新的旋转 CFrame
local newCFrame = CFrame.Angles(0, math.rad(45), 0)
-- 用新的 CFrame 覆盖红块的当前 CFrame
redBlock.CFrame = newCFrame

之前
>

之后
>

面向一个点的 CFrame

您可以使用 CFrame.new() 来将 CFrame 的前表面指向世界上的特定位置。在以下示例中,redBlock部件位置在(0,3,0),指向白色圆圈标记的前表面,指向blueCube部件。


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
local blueCube = Workspace.BlueCube
-- 为起始位置和目标位置创建一个 Vector3
local startPosition = Vector3.new(0, 3, 0)
local targetPosition = blueCube.Position
-- 将红色块放在“startPosition”并将其前表面指向“targetPosition”
redBlock.CFrame = CFrame.new(startPosition, targetPosition)

之前
>

之后
>

抵消一个 CFrame

要将对象从其当前位置抵消特定数量的螺柱,在对象位置添加或减去 Vector3 到或从新的 CFrame 。要将对象的正确格式化 Vector3 位置用于 CFrame.new() ,如图中所示,其 Position 属性 ( redBlock.Position ) 是一个方便的快捷键。


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
redBlock.CFrame = CFrame.new(redBlock.Position) + Vector3.new(0, 1.25, 0)

之前
>

之后
>

您可以使用相同的技巧来抵消对象从另一个对象的位置。在以下示例中,一个 Vector3 添加到蓝色立方体位置的新 CFrame 块,而不是砖块的位置。


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
local blueCube = Workspace.BlueCube
redBlock.CFrame = CFrame.new(blueCube.Position) + Vector3.new(0, 2, 0)

之前
>

之后
>

动态 CFrame 方向

CFrame.new()CFrame.Angles() 建造者重新定位或旋转世界内的对象在特定方向,但你有时无法依靠固定的世界位置和旋转角度。例如:

  • 直接将漂浮的宝物放在世界上任何地方站立的玩家面前,面向任何方向。
  • 让一个魔法精灵直接出现在玩家的右肩上。

在这些情况下,使用 CFrame 方法而不是使用他们的生成器。

相对位置

CFrame:ToWorldSpace()将对象的CFrame转换为新的 世界 方向。这使得它对抵消零件相对于自身或其他对象非常理想,无论如何当前位置/旋转。

在以下示例中,redBlock部分相对于蓝色立方体的 y-轴(绿色箭头通过它指向)和 相对于全球 y-轴直接向上指向。


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
local blueCube = Workspace.BlueCube
local 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.RedBlock
local rotatedCFrame = CFrame.Angles(0, math.rad(70), math.rad(20))
redBlock.CFrame = redBlock.CFrame:ToWorldSpace(rotatedCFrame)

之前
>

之后
>

面向某个点的特定表面

您可以通过提供 Vector3 点作为 CFrame.new() 的第二个参数来让对象的前面对另一个对象。您还可以使用相对旋转将对象的任何面向一个 Vector3 点。以下示例执行了两个连续的 CFrame 操作:

  1. 将标有白色圆圈的 表面指向目标。
  2. 旋转 CFrame 以使黑色圆圈标记的 顶部 面向目标。

local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
local blueCube = Workspace.BlueCube
-- 为目标位置创建一个 Vector3
local targetPosition = blueCube.Position
-- 将红块的前表面指向“目标位置”
redBlock.CFrame = CFrame.new(redBlock.Position, targetPosition)
-- 现在红块的前表面(白色圆圈)正指向蓝立方
-- 将红块的 CFrame相对于自身旋转,使其顶部表面(不是前部)指向目标
local rotatedCFrame = CFrame.Angles(math.rad(-90), 0, 0)
redBlock.CFrame = redBlock.CFrame:ToWorldSpace(rotatedCFrame)
-- Now the redBlock's top surface (black circle) is pointing towards the blueCube (as seen in After below)

之前
>

之后
>

找到点之间的点

您可以使用 线性插值lerp 来在两个点之间放置 CFrame。在以下示例中,redBlock部分重新位置在greenCubecyanCube部分之间。值 0.7 将其放置在绿色立方体的距离的 70% 处


local Workspace = game:GetService("Workspace")
local redBlock = Workspace.RedBlock
local greenCube = Workspace.GreenCube
local cyanCube = Workspace.CyanCube
redBlock.CFrame = greenCube.CFrame:Lerp(cyanCube.CFrame, 0.7)

之前
>

之后
>