关于向量的这篇文章
Blueprints 是 Unreal Engine 4 中的可视化脚本系统,是开始制作游戏原型的快速方法。无需逐行编写代码,您可以直观地完成所有操作:拖放节点,在 UI 中设置它们的属性,然后拖动电线进行连接。
除了作为一种快速的原型制作工具之外,蓝图还使非程序员可以很容易地潜入并开始编写脚本。
下载启动项目并解压缩。要打开项目,请转到项目文件夹并打开BananaCollector.uproject。
注意:如果您收到一条消息说项目是使用早期版本的虚幻编辑器创建的,那没关系(引擎经常更新)。您可以选择打开副本的选项,也可以选择就地转换的选项。
你会看到下面的场景。这是玩家将四处走动并收集物品的地方。
我已将项目文件分类到文件夹中以便于导航,如下所示:
如果您愿意,可以使用上面以红色突出显示的按钮来显示或隐藏源面板。
在内容浏览器中,导航到Blueprints文件夹。单击Add New按钮并选择Blueprint Class。
由于您希望演员能够接收来自玩家的输入,因此Pawn类很合适。从弹出窗口中选择Pawn并将其命名为BP_Player。
注意: Character类也可以工作。它甚至默认包含一个运动组件。但是,您将实现自己的移动系统,因此Pawn类就足够了。
相机是玩家观察世界的方法。您将创建一个俯视玩家的摄像机。
在内容浏览器中,双击BP_Player以在蓝图编辑器中打开它。
要创建相机,请转到“组件”面板。单击添加组件并选择相机。
要使相机处于自上而下的视图中,您需要将其放置在Player上方。选择相机组件后,转到“视口”选项卡。
按W键激活移动操纵器,然后将其移动到(-1100, 0, 2000)。或者,您可以在位置字段中输入坐标。它位于Details 面板中的Transform部分下。
如果您看不到相机,请按F键对焦。
接下来,按E键激活旋转操纵器。在Y 轴上将相机向下旋转到-60度。
一个红色立方体将代表玩家,因此您需要使用静态网格组件来显示它。
首先,通过左键单击“组件”面板中的空白区域来取消选择“相机”组件。如果不这样做,下一个添加的组件将是 Camera 的子组件。
单击添加组件并选择静态网格体。
要显示红色立方体,请选择静态网格组件,然后转到详细信息选项卡。单击位于静态网格体右侧的下拉菜单并选择SM_Cube。
这是你应该看到的(如果你没有看到它,你可以在视口中点击F来关注它):
现在,是时候生成玩家 Pawn 了。单击编译并返回主编辑器。
在玩家可以控制 Pawn 之前,您需要指定两件事:
您通过创建一个新的Game Mode类来完成第一个。
Game Mode是一个控制玩家如何进入游戏的类。例如,在多人游戏中,您将使用游戏模式来确定每个玩家的生成位置。更重要的是,Game Mode决定了玩家将使用哪个 Pawn。
转到 Content Browser 并确保您位于Blueprints文件夹中。单击Add New按钮并选择Blueprint Class。
从弹出窗口中,选择Game Mode Base并将其命名为GM_Tutorial。
现在,您需要指定默认的 Pawn 类。双击GM_Tutorial打开它。
转到 Details 面板并查看Classes部分。单击Default Pawn Class的下拉菜单并选择BP_Player。
在您可以使用新的游戏模式之前,关卡需要知道要使用哪种游戏模式。您可以在World Settings中指定。单击编译并关闭蓝图编辑器。
每个级别都有自己的设置。您可以通过选择Window\World Settings来访问设置。或者,您可以转到工具栏并选择Settings\World Settings。
一个新的世界设置选项卡将在详细信息选项卡旁边打开。在此处,单击GameMode Override的下拉菜单并选择GM_Tutorial。
您现在将看到这些类已更改为在GM_Tutorial中选择的类。
最后,您需要指定Player的生成位置。您可以通过将Player Start actor 放置到关卡中来做到这一点。
在生成玩家的过程中,游戏模式会寻找Player Start actor。如果游戏模式找到一个,它将尝试在那里生成玩家。
要放置 Player Start,请转到 Modes 面板并搜索Player Start。左键单击并将Player Start从 Modes 面板拖到 Viewport 中。释放左键将放置它。
你可以把它放在任何你喜欢的地方。完成后,转到工具栏并单击播放。您将在放置 Player Start 的位置生成。
要退出游戏,请单击工具栏中的停止按钮或按Esc键。如果看不到光标,请按Shift+F1。
如果你不能四处走动,这不是一场游戏,对吧?您的下一个任务是设置输入设置。
将键分配给操作称为键绑定。
在 Unreal 中,您可以设置按键绑定,当您按下它们时将触发一个事件。事件是在某些操作发生时执行的节点(在这种情况下,当您按下绑定键时)。当事件被触发时,任何连接到该事件的节点都会执行。
这种绑定键的方法很有用,因为它意味着您不必对键进行硬编码。
例如,您绑定左键单击并将其命名为 Shoot。任何可以射击的Actor都可以使用 Shoot 事件来了解玩家何时按下了左键。如果要更改密钥,请在输入设置中进行更改。
如果您对其进行了硬编码,则必须检查每个参与者并单独更改键。
要查看输入设置,请转到Edit\Project Settings。在左侧,选择引擎部分下的输入。
绑定部分是您设置输入的地方。
Unreal 提供了两种创建键绑定的方法:
对于本教程,您将使用轴映射。
首先,您将创建两个轴映射组。组允许您将多个键绑定到一个事件。
要创建新的轴映射组,请单击Axis Mappings右侧的+号。创建两个组并将它们命名为MoveForward和MoveRight。
MoveForward将处理向前和向后移动。MoveRight将处理左右移动。
您将移动映射到四个键:W、A、S和D。目前,只有两个插槽来映射键。通过单击组名称字段旁边的+号,向每个组添加另一个轴映射。
要映射键,请单击下拉菜单以显示键列表。将W和S键映射到MoveForward。将A和D键映射到MoveRight。
接下来,您将设置比例字段。
在设置 Scale 字段之前,您需要了解它们如何使用轴值。
轴值是由输入类型和使用方式确定的数值。按钮和按键在按下时输出 1。Thumbsticks 输出一个介于 -1 和 1 之间的值,具体取决于方向和推它的距离。
您可以使用轴值来控制 Pawn 的速度。例如,如果将摇杆推到边缘,则轴值为 1。如果将其推到一半,则值为 0.5。
通过将轴值与速度变量相乘,您可以使用摇杆调整速度。
您还可以使用轴值来指定沿轴的方向。如果将 Pawn 的速度乘以正轴值,则会得到正偏移。使用负轴值将导致负偏移。将此偏移量添加到 Pawn 的位置将确定它移动的方向。
由于键盘按键只能输出轴值 1 或 0,因此您可以使用scale将其转换为负数。它通过取轴值并将其乘以比例来工作。
如果将正数(轴值)与负数(刻度)相乘,您将得到负数。
通过单击Scale字段并输入-1来设置S和A键的比例。
接下来是有趣的部分:让 Pawn 移动!关闭项目设置,然后在蓝图编辑器中双击打开BP_Player 。
首先,您需要获取运动映射的事件。右键单击事件图表中的空白区域以获取节点列表。从菜单中搜索MoveForward。添加列在Axis Events下的MoveForward节点。请注意,您正在寻找 Axis Events 下的红色节点,而不是 Axis Values 下的绿色节点。
对MoveRight重复该过程。
现在,您将为MoveForward设置节点。
要移动,您需要指定 Pawn 移动的速度。指定速度的一种简单方法是将其存储在变量中。
要创建一个,请转到我的蓝图选项卡,然后单击变量部分右侧的+号。
选择新变量后,转到详细信息选项卡。将变量重命名为MaxSpeed。之后,将变量类型更改为Float。通过单击变量类型旁边的下拉菜单并选择浮点数来执行此操作。
接下来,您需要设置默认值。不过,在设置它之前,您需要单击工具栏中的编译。
在您的变量仍处于选中状态的情况下,返回“详细信息”选项卡。转到Default Value部分并将MaxSpeed的默认值更改为10。
接下来,将MaxSpeed变量从 My Blueprint 选项卡拖放到 Event Graph 中。从菜单中选择获取。
您现在将MaxSpeed和轴值相乘以确定最终速度和方向。添加一个float * float节点并将Axis Value和MaxSpeed连接到它。
要继续前进,您需要知道 Pawn 面向的位置。幸运的是,虚幻引擎有一个用于此目的的节点。添加一个Get Actor Forward Vector节点。
接下来,添加一个Add Movement Input节点。该节点将采用方向和值并将其转换为存储的偏移量。像这样连接节点:
白线代表一个执行链。换句话说,当玩家移动输入轴时,将生成一个事件,该事件将执行InputAxis MoveForward节点。白线表示一旦发生这种情况,您将执行Add Movement Input节点。
Add Movement Input节点接受以下输入:
对MoveRight重复该过程,但将Get Actor Forward Vector替换为Get Actor Right Vector。看看你自己可以做多少而不查看上面的说明!
要实际移动 Pawn,您需要获取通过 Add Movement Input 计算的偏移量并将其添加到 Pawn 的位置。
基本上,您的策略是在游戏的每一帧中移动玩家少量,因此您需要将移动添加到每帧生成的Event Tick事件中。
导航到事件图表中的Event Tick节点。它应该在左侧变灰,但如果您没有它,请创建一个。
要获取偏移量,请创建一个Consume Movement Input Vector节点。要添加偏移量,请创建一个AddActorLocalOffset节点。然后,像这样链接它们:
基本上,这意味着游戏的每一帧,您都会获得任何存储的运动输入,并将其添加到演员的当前位置。
单击Compile,然后返回主编辑器并单击Play。您现在可以四处走动了!
不过有一个小问题。高端机器能够以更快的速度渲染帧。由于每帧都会调用 Event Tick,因此移动节点将更频繁地执行。这导致 Pawn 在高端机器上以更快的速度移动,反之亦然。
要解决此问题,您的运动需要与帧速率无关。
注意:我已经设置了一些键绑定,将向您展示帧速率依赖的效果。按0将帧速率上限设置为 60,然后按1重置上限。以两种帧速率移动以查看速度差异。
帧率独立意味着无论帧率如何,一切都会有相同的结果。值得庆幸的是,在 Unreal 中实现帧速率独立很容易。
退出游戏,然后打开BP_Player。接下来,导航到您的Event Tick节点并查看Delta Seconds。
Delta Seconds 是自最后一个 Event Tick 以来经过的时间量。通过将您的偏移量与 Delta Seconds 相乘,您的移动将与帧速率无关。
例如,您的 Pawn 的最大速度为 100。如果自上一次 Event Tick 后经过一秒,您的 Pawn 将移动全部 100 个单位。如果过了半秒,它将移动 50 个单位。
如果移动取决于帧速率,则 Pawn 将每帧移动 100 个单位,而不管帧之间的时间。
要将您的偏移量与 Delta Seconds 相乘,请添加一个vector * float节点。之后,像这样连接你的节点:
因为帧之间的时间(增量秒)非常小,所以您的 Pawn 移动速度会慢很多。通过将MaxSpeed的默认值更改为600来解决此问题。
恭喜你,你成功实现了帧率独立!
您可能已经注意到立方体直接穿过所有物体。要解决这个问题,您需要了解碰撞。
带上你的安全头盔,因为你即将与一些理论发生正面碰撞!
当您想到碰撞时,您可能会想到汽车相撞。幸运的是,虚幻引擎中的碰撞更加安全。
为了能够碰撞,actor 需要其可碰撞空间的表示(通常称为碰撞)。您可以使用以下方法之一:
下面是一个角色及其碰撞的示例。
当一个actor的碰撞触及另一个actor的碰撞时,就会发生碰撞。
现在,是时候启用碰撞了。
你可能想知道为什么盒子没有碰撞,即使它有一个碰撞网格。当你移动一个actor时,虚幻引擎只考虑碰撞的根组件。由于 Pawn 的根组件没有任何碰撞,因此它会通过所有内容。
注意:没有碰撞作为根的actor仍然可以阻止其他actor。但是,如果你移动演员,它不会与任何东西发生碰撞。
因此,要使用碰撞网格,StaticMesh需要是root。为此,请转到“组件”面板。接下来,左键单击并拖动 StaticMesh到DefaultSceneRoot。释放左键单击以使StaticMesh成为新的根。
在碰撞起作用之前还有一件事要做。切换到 Event Graph 并转到AddActorLocalOffset节点。找到Sweep输入并通过左键单击复选框将其设置为true。
基本上,AddActorLocalOffset将演员传送到新位置。Sweep确保演员与新旧位置之间的任何东西发生碰撞。
返回主编辑器并单击Play。立方体现在将与关卡发生碰撞!
你要做的最后一件事是创建一个在玩家触摸它时消失的项目。
一般来说,物品是玩家可以收集的任何东西。您将使用BP_Banana作为项目。
要检测立方体何时接触项目,您需要一个在发生碰撞时触发的事件节点。您可以使用碰撞响应来生成此类事件。
碰撞响应还决定了一个actor在与另一个actor碰撞时的反应。有三种类型的碰撞响应:Ignore忽略碰撞,Block就是阻挡,而Overlap与Ignore类似,不会产生阻挡,但会产生重合的事件通知。以下是它们之间的交互方式:
(1)只有两个对象互相Block时,才会真正的被阻挡,其他情况都不会;
(2)只要有一方Ignore,就不会产生Overlap的重合事件
在编辑器里,选中这个白盒子,在这里配置碰撞信息(Collison Preset,碰撞预设):
默认是Default,切换成其他的碰撞预设都能看到具体的碰撞响应,但大多都不可编辑(只读),如下图:
只有切成Custom...才可编辑:
我们来分别说下这些配置:
CollisionEnabled决定了碰撞的用途,如下:
NoCollision:如果是这个,那么其他碰撞设置都会被忽略不计,因为不再考虑碰撞了;
Query Only:仅用于查询,不会考虑物理仿真;
Physics Only:仅用于物理仿真,不考虑查询;
Collision Enabled(Query and Physics):同时用于查询与仿真;
人物的移动物理属于查询,我们选择Query Only就行。
ObjectType决定了物体本身是什么碰撞类型,可选类型如下(也可以在ProjectSettings里面添加,后面会谈到):
WorldStatic:静态几何物件,如山石,树干等;
WorldDynamic:动态几何物件,如房门,地面可拾取物等;
Pawn:人物或类人的东西,如玩家,野怪;
PhysicsBody:物理体;
Vehicle:载具,如摩托车,飞机等;
Destructible:可破坏物件,如栅栏,窗户等;
ObjectType配置的自由度很高,你也可以把石头配置成载具的ObjectType,只是这样在处理其他物件对它的响应时要绕得过来,一般不会做这种坑人坑己的事情。
碰撞响应决定了该对象对其他碰撞类型的响应,如下图:
仔细看可以发现碰撞响应还会细分成Trace Response与Object Response,个人理解其实差别不大,主要是通道过滤比较方便,直观理解射线检测类的配置成Trace Response,对象移动类的配置成Object Response就可以了。ObjectResponses列举出来的情况正是之前我们谈到的ObjectType的枚举,上图应解释成:白盒子对这几种碰撞类型的对象都是阻挡响应。
尽管您可以使用 Overlap 或 Block,但本教程将仅向您展示如何使用 Overlap。
退出游戏,然后打开BP_Banana。选择StaticMesh组件,然后转到 Details 面板。Collision部分是您设置碰撞响应的地方。
如您所见,大多数设置都是灰色的。要使它们可编辑,请左键单击Collision Presets旁边的下拉菜单。从列表中选择自定义。
现在,您需要指定项目和立方体之间的碰撞响应。
组件有一个名为object type的属性。对象类型只是将相似参与者组合在一起的一种便捷方式。您可以在此处阅读有关对象类型的更多信息。
由于立方体的类型是WorldDynamic,因此您希望将碰撞响应更改为该类型。在Collision Responses部分下,将WorldDynamic的碰撞响应更改为Overlap。通过左键单击WorldDynamic右侧的中间复选框来执行此操作。
要处理碰撞,您需要使用重叠事件。转到 Components 面板并右键单击StaticMesh。从上下文菜单中,选择Add Event\Add OnComponentBeginOverlap。
这会将OnComponentBeginOverlap (StaticMesh)节点添加到您的事件图表中。
最后,创建一个DestroyActor节点并将其链接到OnComponentBeginOverlap (StaticMesh)节点。顾名思义,它将从游戏中移除目标演员。但是,由于没有目标,它会破坏调用它的actor。
关闭蓝图编辑器,然后确保您位于蓝图文件夹中。
通过左键单击并将BP_Banana拖动 到视口中,开始将香蕉放入关卡中。
单击播放并开始收集香蕉!