Unreal Engine开发:Unreal Engine基础入门_(5).蓝图视觉脚本基础

蓝图视觉脚本基础

蓝图概述

蓝图(Blueprints)是Unreal Engine中的一种可视化脚本系统,允许开发者通过拖拽节点和连接线来创建游戏逻辑、行为和交互。蓝图简化了游戏开发过程,使得没有编程背景的开发者也能轻松上手。蓝图可以用于创建游戏对象的行为、关卡逻辑、UI界面、动画逻辑等。

蓝图的类型

Unreal Engine中的蓝图主要分为以下几种类型:

  1. 蓝图类(Blueprint Class):这是最常见的蓝图类型,用于创建游戏中的可实例化对象,如角色、道具、敌人等。

  2. 蓝图宏库(Blueprint Macro Library):用于创建可重用的逻辑块,可以在多个蓝图中调用。

  3. 关卡蓝图(Level Blueprint):用于控制关卡中的全局逻辑,如玩家的初始位置、游戏事件等。

  4. 数据表蓝图(Data Table Blueprint):用于管理游戏中的数据表格,如角色属性、物品数据等。

  5. 动画蓝图(Animation Blueprint):用于创建和管理角色的动画逻辑。

创建蓝图类

创建蓝图类的步骤

  1. 打开Unreal Engine编辑器:启动Unreal Engine编辑器并打开您的项目。

  2. 创建蓝图类

    • 在内容浏览器(Content Browser)中,右键点击空白处,选择“新建”(New) > “蓝图类”(Blueprint Class)。

    • 选择一个父类(Parent Class),例如“Actor”(用于创建一般的游戏对象)、“Character”(用于创建角色)等。

    • 为蓝图类命名并点击“创建”(Create)按钮。

蓝图类的基本结构

创建蓝图类后,您将看到一个蓝图编辑器窗口,其中包含以下几个主要部分:

  • 事件图表(Event Graph):用于编辑蓝图的逻辑。

  • 组件(Components):用于添加和编辑蓝图的组件,如静态网格体(Static Mesh)、碰撞组件(Collision Component)等。

  • 变量(Variables):用于定义蓝图的属性和数据。

  • 函数(Functions):用于创建可重用的逻辑块。

示例:创建一个简单的Actor蓝图

假设我们要创建一个简单的游戏对象,该对象在被玩家碰撞时播放一个音效。

  1. 创建蓝图类

    • 在内容浏览器中右键点击空白处,选择“新建” > “蓝图类”。

    • 选择“Actor”作为父类。

    • 命名为“SimpleActor”。

  2. 添加组件

    • 打开蓝图编辑器。

    • 在“组件”部分,点击“添加组件”(Add Component)按钮。

    • 选择“Static Mesh”组件,用于显示物体的模型。

    • 选择“Sphere Collision”组件,用于检测碰撞。

  3. 配置组件

    • 选择“Static Mesh”组件,在细节(Details)面板中选择一个静态网格体(例如一个立方体)。

    • 选择“Sphere Collision”组件,在细节面板中调整碰撞半径(例如设置为100)。

  4. 创建变量

    • 在蓝图编辑器中,点击“变量”(Variables)标签。

    • 点击“+添加变量”(+Add Variable)按钮。

    • 命名为“SoundEffect”,类型选择“Sound Base”。

    • 点击“编译”(Compile)按钮。

  5. 编写逻辑

    • 点击“事件图表”(Event Graph)标签。

    • 右键点击空白处,选择“添加事件”(Add Event) > “碰撞”(Collision) > “Begin Overlap”。

    • 从“Begin Overlap”事件中拖出一条线,选择“播放声音”(Play Sound)节点。

    • 将“SoundEffect”变量连接到“播放声音”节点的“Sound”引脚。


// 事件图表逻辑

Event BeginOverlap(OtherActor, OtherComp)

  Play Sound (SoundEffect)

蓝图类的实例化

  1. 将蓝图类放入关卡

    • 在关卡编辑器(Level Editor)中,点击“添加演员”(Add Actor)按钮。

    • 选择您刚刚创建的“SimpleActor”蓝图类。

    • 将其放置在关卡中。

  2. 设置变量

    • 选中关卡中的“SimpleActor”实例。

    • 在细节面板中,找到“SoundEffect”变量。

    • 选择一个音效资源(例如“WAV”文件)并拖放到变量中。

事件图表(Event Graph)

事件概述

事件图表是蓝图中用于编辑逻辑的主要区域。事件(Event)是蓝图中的一种特殊节点,用于触发一系列逻辑操作。常见的事件包括:

  • BeginPlay:当游戏开始时触发。

  • Tick:每帧触发一次,用于更新游戏逻辑。

  • Input Events:当玩家输入时触发,例如按键、触摸等。

  • Collision Events:当对象发生碰撞时触发,例如BeginOverlap、EndOverlap等。

事件的使用

  1. BeginPlay事件

    • 在事件图表中右键点击空白处,选择“添加事件” > “BeginPlay”。

    • 从“BeginPlay”事件中拖出一条线,选择“打印字符串”(Print String)节点。

    • 在“Print String”节点中输入“Game Started!”。


// BeginPlay事件

Event BeginPlay

  Print String ("Game Started!")

  1. Tick事件

    • 在事件图表中右键点击空白处,选择“添加事件” > “Tick”。

    • 从“Tick”事件中拖出一条线,选择“设置演员位置”(Set Actor Location)节点。

    • 在“Set Actor Location”节点中,设置一个新的位置,例如将对象沿着X轴移动100个单位。


// Tick事件

Event Tick (DeltaSeconds)

  Set Actor Location (NewLocation = Get Actor Location + (X = 100, Y = 0, Z = 0) * DeltaSeconds)

  1. 输入事件

    • 在事件图表中右键点击空白处,选择“添加事件” > “输入” > “跳跃”(Jump)。

    • 从“Jump”事件中拖出一条线,选择“播放动画”(Play Animation)节点。

    • 在“Play Animation”节点中,选择一个跳跃动画。


// 跳跃输入事件

Event Jump

  Play Animation (JumpAnimation)

  1. 碰撞事件

    • 在事件图表中右键点击空白处,选择“添加事件” > “碰撞” > “BeginOverlap”。

    • 从“BeginOverlap”事件中拖出一条线,选择“播放声音”(Play Sound)节点。

    • 将“SoundEffect”变量连接到“播放声音”节点的“Sound”引脚。


// BeginOverlap碰撞事件

Event BeginOverlap (OtherActor, OtherComp)

  Play Sound (SoundEffect)

变量(Variables)

变量概述

变量是蓝图中用于存储数据的容器。变量可以是各种类型,如整数、浮点数、字符串、布尔值、对象引用等。变量可以在事件图表中使用,也可以在组件中配置。

变量的创建和使用

  1. 创建变量

    • 在蓝图编辑器中,点击“变量”(Variables)标签。

    • 点击“+添加变量”(+Add Variable)按钮。

    • 命名为“Health”,类型选择“整数”(Integer)。

    • 点击“编译”(Compile)按钮。

  2. 在事件图表中使用变量

    • 在事件图表中右键点击空白处,选择“添加事件” > “BeginPlay”。

    • 从“BeginPlay”事件中拖出一条线,选择“设置变量”(Set Variable)节点。

    • 选择“Health”变量。

    • 在“Set Variable”节点中,设置“Health”的初始值为100。


// BeginPlay事件设置Health变量

Event BeginPlay

  Set Health (100)

  1. 更新和读取变量

    • 在事件图表中右键点击空白处,选择“添加事件” > “输入” > “攻击”(Attack)。

    • 从“Attack”事件中拖出一条线,选择“获取变量”(Get Variable)节点。

    • 选择“Health”变量。

    • 从“Get Variable”节点拖出一条线,选择“整数操作”(Integer Operation)节点。

    • 选择“减法”(Subtract)操作。

    • 从“Subtract”节点拖出一条线,选择“设置变量”(Set Variable)节点。

    • 选择“Health”变量。

    • 在“Subtract”节点中,设置减去的值为10。


// Attack输入事件减少Health变量

Event Attack

  Get Health

  Subtract (Health, 10)

  Set Health (Result)

函数(Functions)

函数概述

函数是蓝图中用于封装可重用逻辑的节点。通过创建函数,您可以将复杂的逻辑拆分为多个独立的模块,提高代码的可读性和可维护性。

函数的创建和使用

  1. 创建函数

    • 在蓝图编辑器中,点击“函数”(Functions)标签。

    • 点击“+添加函数”(+Add Function)按钮。

    • 命名为“TakeDamage”,点击“创建”(Create)按钮。

  2. 编写函数逻辑

    • 在事件图表中右键点击空白处,选择“添加事件” > “自定义事件”(Custom Event)。

    • 命名为“TakeDamage”。

    • 从“TakeDamage”事件中拖出一条线,选择“获取变量”(Get Variable)节点。

    • 选择“Health”变量。

    • 从“Get Variable”节点拖出一条线,选择“整数操作”(Integer Operation)节点。

    • 选择“减法”(Subtract)操作。

    • 从“Subtract”节点拖出一条线,选择“设置变量”(Set Variable)节点。

    • 选择“Health”变量。

    • 在“Subtract”节点中,设置减去的值为10。


// TakeDamage函数逻辑

Event TakeDamage

  Get Health

  Subtract (Health, 10)

  Set Health (Result)

  1. 调用函数

    • 在事件图表中右键点击空白处,选择“添加事件” > “输入” > “攻击”(Attack)。

    • 从“Attack”事件中拖出一条线,选择“调用函数”(Call Function)节点。

    • 选择“TakeDamage”函数。


// Attack输入事件调用TakeDamage函数

Event Attack

  Call Function TakeDamage

蓝图的继承和多态

继承概述

蓝图支持继承,您可以创建一个父蓝图,并在其基础上创建多个子蓝图。子蓝图可以重写或扩展父蓝图的属性和逻辑。

继承的步骤

  1. 创建父蓝图

    • 在内容浏览器中右键点击空白处,选择“新建” > “蓝图类”。

    • 选择“Actor”作为父类。

    • 命名为“BaseActor”。

  2. 添加父蓝图的变量和逻辑

    • 在“BaseActor”蓝图中,创建一个变量“Health”。

    • 在事件图表中添加“TakeDamage”函数。

  3. 创建子蓝图

    • 在内容浏览器中右键点击空白处,选择“新建” > “蓝图类”。

    • 选择“BaseActor”作为父类。

    • 命名为“ChildActor”。

  4. 重写或扩展父蓝图的逻辑

    • 在“ChildActor”蓝图中,打开事件图表。

    • 右键点击空白处,选择“添加事件” > “调用父类函数”(Call Parent Function)。

    • 选择“TakeDamage”函数。

    • 从“Call Parent Function”节点拖出一条线,选择“打印字符串”(Print String)节点。

    • 在“Print String”节点中输入“Health decreased!”。


// ChildActor蓝图中重写TakeDamage函数

Event TakeDamage

  Call Parent Function TakeDamage

  Print String ("Health decreased!")

蓝图的通信

通信概述

蓝图之间的通信可以通过事件派遣(Event Dispatchers)和接口(Interfaces)来实现。事件派遣可以用于在蓝图之间发送事件,而接口可以用于定义蓝图之间的方法调用。

事件派遣的使用

  1. 创建事件派遣

    • 在“BaseActor”蓝图中,点击“变量”(Variables)标签。

    • 点击“+添加变量”(+Add Variable)按钮。

    • 命名为“OnHealthChanged”,类型选择“事件派遣”(Event Dispatcher)。

    • 点击“编译”(Compile)按钮。

  2. 在函数中使用事件派遣

    • 在“BaseActor”蓝图的“TakeDamage”函数中,从“Set Health”节点拖出一条线,选择“触发事件派遣”(Trigger Event Dispatcher)节点。

    • 选择“OnHealthChanged”事件派遣。


// TakeDamage函数中触发OnHealthChanged事件派遣

Event TakeDamage

  Get Health

  Subtract (Health, 10)

  Set Health (Result)

  Trigger Event Dispatcher OnHealthChanged

  1. 在子蓝图中监听事件派遣

    • 在“ChildActor”蓝图中,打开事件图表。

    • 右键点击空白处,选择“添加事件” > “事件派遣” > “OnHealthChanged”。

    • 从“OnHealthChanged”事件中拖出一条线,选择“打印字符串”(Print String)节点。

    • 在“Print String”节点中输入“Health changed to: ”。

    • 使用“获取变量”(Get Variable)节点获取“Health”变量,并将其连接到“Print String”节点的“Text”引脚。


// ChildActor蓝图中监听OnHealthChanged事件

Event OnHealthChanged

  Get Health

  Print String ("Health changed to: " + Health.ToString())

接口的使用

  1. 创建接口

    • 在内容浏览器中右键点击空白处,选择“新建” > “蓝图接口”(Blueprint Interface)。

    • 命名为“HealthInterface”。

    • 打开“HealthInterface”蓝图,点击“+添加函数”(+Add Function)按钮。

    • 命名为“TakeDamage”,点击“创建”(Create)按钮。

    • 点击“编译”(Compile)按钮。

  2. 实现接口

    • 在“BaseActor”蓝图中,点击“类设置”(Class Settings)标签。

    • 在“接口”(Interfaces)部分,点击“+添加接口”(+Add Interface)按钮。

    • 选择“HealthInterface”接口。

    • 点击“编译”(Compile)按钮。

    • 在事件图表中右键点击空白处,选择“添加事件” > “接口” > “HealthInterface” > “TakeDamage”。

    • 编写“TakeDamage”函数的逻辑。


// BaseActor蓝图中实现TakeDamage接口

Event TakeDamage

  Get Health

  Subtract (Health, 10)

  Set Health (Result)

  Trigger Event Dispatcher OnHealthChanged

  1. 在其他蓝图中调用接口函数

    • 在内容浏览器中创建一个新的蓝图类,例如“HealthManager”。

    • 在“HealthManager”蓝图中,添加一个变量“TargetActor”,类型选择“Actor”。

    • 在事件图表中右键点击空白处,选择“添加事件” > “输入” > “减少目标血量”(ReduceTargetHealth)。

    • 从“ReduceTargetHealth”事件中拖出一条线,选择“调用接口函数”(Call Interface Function)节点。

    • 选择“TargetActor”变量和“HealthInterface”接口。

    • 选择“TakeDamage”函数。


// HealthManager蓝图中调用TargetActor的TakeDamage接口函数

Event ReduceTargetHealth

  Call Interface Function (TargetActor, HealthInterface, TakeDamage)

蓝图的调试

调试概述

蓝图提供了一些调试工具,帮助您在开发过程中查找和修复问题。常见的调试工具包括:

  • 打印字符串(Print String):在事件图表中添加“Print String”节点,可以在游戏运行时在屏幕上显示调试信息。

  • 断点(Breakpoints):在事件图表中右键点击节点,选择“添加断点”(Add Breakpoint),可以在节点处暂停游戏运行,以便检查变量和逻辑。

  • 蓝图调试器(Blueprint Debugger):通过蓝图调试器可以查看蓝图的执行过程和变量值。

调试示例

假设我们在“BaseActor”蓝图中有一个“TakeDamage”函数,我们希望在调用该函数时打印调试信息。

  1. 添加打印字符串节点

    • 在“BaseActor”蓝图的“TakeDamage”函数中,从“Set Health”节点拖出一条线,选择“打印字符串”(Print String)节点。

    • 在“Print String”节点中输入“Health decreased to: ”。

    • 使用“获取变量”(Get Variable)节点获取“Health”变量,并将其连接到“Print String”节点的“Text”引脚。


// TakeDamage函数中添加打印字符串节点

Event TakeDamage

  Get Health

  Subtract (Health, 10)

  Set Health (Result)

  Get Health

  Print String ("Health decreased to: " + Health.ToString())

  1. 添加断点

    • 在“TakeDamage”函数的“Set Health”节点上右键点击,选择“添加断点”(Add Breakpoint)。

    • 在游戏运行时,当“TakeDamage”函数被调用时,游戏将在断点处暂停。

    • 使用蓝图调试器查看变量值和执行过程。

蓝图的性能优化

性能优化概述

虽然蓝图提供了强大的可视化脚本功能,但在大型项目中,不当的使用方式可能会导致性能问题。性能优化是确保游戏运行流畅、响应迅速的关键步骤。以下是一些常见的蓝图性能优化技巧:

优化技巧

  1. 减少事件图表中的节点数量

    • 尽量将复杂的逻辑拆分为多个函数,避免在事件图表中堆积大量的节点。

    • 使用蓝图宏库(Blueprint Macro Library)创建可重用的逻辑块,减少重复代码。

  2. 使用事件派遣和委托

    • 事件派遣(Event Dispatchers)和委托(Delegates)可以减少蓝图之间的直接调用,提高性能。

    • 例如,可以在一个蓝图中触发事件派遣,而不是在多个蓝图中直接调用函数。

  3. 优化动画逻辑

    • 动画蓝图(Animation Blueprint)中,尽量使用动画混合(Blend)和动画蒙版(Mask)来减少动画状态机的复杂性。

    • 使用动画通知(Anim Notifies)来触发特定的事件,而不是在每一帧中进行检查。

  4. 避免频繁的Tick事件

    • Tick事件每帧触发,如果处理不当,可能会导致性能下降。

    • 尽量在需要时使用事件或函数,而不是依赖频繁的Tick事件。

    • 如果必须使用Tick事件,确保在不必要时禁用它,例如通过条件判断来控制。

  5. 使用C++实现关键逻辑

    • 对于性能要求较高的逻辑,可以使用C++来实现,然后在蓝图中调用。

    • C++代码通常比蓝图更高效,尤其是在处理大量数据或复杂计算时。

优化示例

假设我们有一个角色蓝图,该角色在每帧中进行复杂的计算来更新其位置和状态。我们可以对以下方面进行优化:

  1. 减少事件图表中的节点数量

    • 将复杂的逻辑拆分为多个函数,例如“UpdatePosition”和“UpdateState”。
  2. 使用事件派遣

    • 创建一个事件派遣“OnUpdate”来通知其他蓝图更新。
  3. 优化动画逻辑

    • 在动画蓝图中使用动画混合和蒙版来减少状态机的复杂性。
  4. 避免频繁的Tick事件

    • 使用条件判断来控制Tick事件的执行频率。
  5. 使用C++实现关键逻辑

    • 创建一个C++类来处理角色的位置更新,然后在蓝图中调用该类的方法。

示例:优化角色蓝图

  1. 创建C++类

    • 在Unreal Engine中创建一个新的C++类,例如“CharacterMovement”。

    • 编写一个方法来更新角色的位置和状态。


// CharacterMovement.h

#pragma once



#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "CharacterMovement.generated.h"



UCLASS()

class YOURGAME_API ACharacterMovement : public AActor

{

    GENERATED_BODY()



public:	

    ACharacterMovement();



protected:

    virtual void BeginPlay() override;



public:	

    virtual void Tick(float DeltaTime) override;



    UFUNCTION()

    void UpdatePosition(float DeltaTime);



    UFUNCTION()

    void UpdateState();

};


// CharacterMovement.cpp

#include "CharacterMovement.h"



ACharacterMovement::ACharacterMovement()

{

    PrimaryActorTick.bCanEverTick = true;

}



void ACharacterMovement::BeginPlay()

{

    Super::BeginPlay();

}



void ACharacterMovement::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    if (ShouldUpdatePosition())

    {

        UpdatePosition(DeltaTime);

    }



    if (ShouldUpdateState())

    {

        UpdateState();

    }

}



void ACharacterMovement::UpdatePosition(float DeltaTime)

{

    // 更新角色位置的逻辑

}



void ACharacterMovement::UpdateState()

{

    // 更新角色状态的逻辑

}

  1. 在蓝图中调用C++方法

    • 创建一个角色蓝图,例如“PlayerCharacter”。

    • 在角色蓝图中添加一个变量“CharacterMovement”,类型选择“CharacterMovement”。

    • 在事件图表中调用“CharacterMovement”的“UpdatePosition”和“UpdateState”方法。


// PlayerCharacter蓝图中调用C++方法

Event Tick (DeltaSeconds)

  Get CharacterMovement

  Call Function UpdatePosition (DeltaSeconds)

  Call Function UpdateState

优化效果

通过这些优化技巧,我们可以显著提高角色蓝图的性能。例如,将复杂的计算逻辑移到C++类中,可以减少蓝图的节点数量和执行时间。使用事件派遣和委托可以减少蓝图之间的直接调用,提高代码的可维护性和性能。

总结

蓝图是Unreal Engine中一种强大的可视化脚本系统,使得游戏开发变得更加直观和简单。然而,为了确保游戏的高性能和稳定性,我们需要在开发过程中注意性能优化。通过减少节点数量、使用事件派遣、优化动画逻辑、避免频繁的Tick事件以及使用C++实现关键逻辑,我们可以有效地提高蓝图的性能,为玩家提供更好的游戏体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值