IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> UE4中蓝图构造脚本和C++中构造函数 -> 正文阅读

[游戏开发]UE4中蓝图构造脚本和C++中构造函数

前言

初学UE4和C++,在尝试将蓝图函数转为C++代码时候,发现了一个很坑人的玩意,就是蓝图中的构造脚本(Consttruction Script)和C++中类的构造函数不是一个东西!因此想记录下来。

准备工作

先创建一个继承Actor的类,现在我有个现成的继承Pawn的类(下文就直接说Actor),可以凑合着用。

CameraOnPlane.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "CameraOnPlane.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(TestLog, Log, All);

UCLASS()
class TRAJECTORY_API ACameraOnPlane : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	ACameraOnPlane();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	virtual void OnConstruction(const FTransform& Transform) override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};

CameraOnPlane.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "CameraOnPlane.h"
DEFINE_LOG_CATEGORY(TestLog);

// Sets default values
ACameraOnPlane::ACameraOnPlane()
{
	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	UE_LOG(TestLog, Warning, TEXT("构造函数被调用"));
}

void ACameraOnPlane::OnConstruction(const FTransform& Transform)
{
	UE_LOG(TestLog, Warning, TEXT("OnConstruction"));
}

// Called when the game starts or when spawned
void ACameraOnPlane::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void ACameraOnPlane::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

// Called to bind functionality to input
void ACameraOnPlane::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
}

其中,这两行代码是用来输出一个名字为TestLog的日志:

// 这个放在.h文件中
DECLARE_LOG_CATEGORY_EXTERN(TestLog, Log, All);
// 这个放在.cpp文件中
DEFINE_LOG_CATEGORY(TestLog);

最后就是打开关卡蓝图,通过SpawnActor让它在开始运行的时候自动在场景中生成一个Actor。

在关卡蓝图事件开始运行节点添加

好了,准备工作完成,先看一下编译运行的效果。

测试

编译日志输出:

编译结果

开始运行日志输出:

运行结果

分析

编译结果在编译的时候调用了一次构造函数,运行结果显示,在运行的时候构造函数调用了一次,OnConstruction函数也被调用了一次,先来说一下OnConstruction函数,这个函数是Actor生命周期的一部分,在官方文档中是这么说的(这里是原文):

官方文档-Actor生命周期

文档怎么一直在说蓝图蓝图的,这不是写在C++里的吗,管蓝图什么事情!(气愤)等等!蓝图好像也有个构造什么玩意:

随便在一个蓝图类截的,无伤大雅

?对!就是这个玩意,Construction Script——构造脚本,我经常在这个函数里边给类弄点默认参数啊什么的,说白了就是为Actor的生成来一些准备工作,我这么说可能不太准确,来看看官方的说法(这里是原文):

创建蓝图类的实例时,构造脚本(Construction Script)?在组件列表之后运行。它包含的节点图表允许蓝图实例执行初始化操作。构造脚本的功能可以非常丰富,它们可以执行场景射线追踪、设置网格体和材质等操作,从而根据场景环境来进行设置。 例如,光源蓝图可判断其所在地面类型,然后从一组网格体中选择合适的网格体, 或者,栅栏蓝图可以向各个方向射出射线, 从而确定栅栏可以有多长。

可能我语文不太好,第一次看完一头雾水,只知道它用来初始化,功能非常丰富。等等,初始化?我自然而然又想到了C++里边的构造函数:

// Sets default values
ACameraOnPlane::ACameraOnPlane()
{
	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	UE_LOG(TestLog, Warning, TEXT("构造函数被调用"));
}

好了,构造脚本,OnConstruction和构造函数三个东西穿起来了,都能初始化,那这就是一个东西嘛(顺带一说,我起初认为的是构造脚本和构造函数是一个东西,只不过一个在蓝图一个在C++),如果这么想的话,那刚刚的测试结果怎么说?

直到看到了这篇文档(这里是原文),才懂了那么一丝。

virtual void OnConstruction(const FTransform& Transform) override;

其实,这个OnConstruction函数才是和蓝图里边的构造脚本是一个玩意,跟构造函数毛关系都没有(其实我也不知道是不是毛关系都没有),这个玩意你可得小心着点用,不然就像那个文章里说的,指不定你的编辑器怎么就crash(崩)掉了,而且一运行就让send and restart(别问我是怎么知道的),所以,我们得大概了解一下这个玩意是怎么玩的。

先是这个C++里边的构造函数,这个不多说了,从官方文档里边的好多例子也看出来可以在里边创建一些组件啊,这个组件加到这个组件上,那个组件加到这个组件上,在给组件整点默认的参数什么的,你看那方法上也写了Sets default values,还有就是这个构造函数会在编译和运行的时候调用(从我那个测试结果看出来)。

然后就是这个构造脚本和OnConstruction函数了,这玩意主要在下面三种情况调用:

  1. Actor生成的时候
  2. Actor移动的时候(可能不止调用一次)
  3. Actor一些参数改变的时候

在那个文章中我注意到一句话:

It is the most interesting point of the Construction Script: it is called in the editor, and not at runtime

?这句话的意思是说ConstructionScript会在编译的时候调用而不是在运行的时候调用吗?如果是这样的话好像跟我测试的结果不太一样,难道我哪里搞错了?欢迎指正讨论!

咱接着说这个构造脚本,文章中谈到这个滥用构造脚本会出现一些问题:

  1. 对项目性能有影响:有时候你啥玩意都写到这个构造脚本里边,东西多了运行的就慢,运行一次假设1秒,欸,还可以,但是关键是,这玩意可能不止运行一次,比如你移动一次,就可能调用好几次,然后编辑器就卡住了,然后就......
  2. 循环调用的情况:属性之间循环调用可能没什么大问题,但是要在父子组件之间出现循环调用情况可能编辑器就会crash掉,痛苦的是根本发现不了问题出在哪里。

总结

总的来说,这次学习算是知道了构造脚本和构造函数不是一个东西,和OnConstruction才是一个东西,用的时候还是要慎重一点,鬼知道会出现什么匪夷所思的问题。

最后碎碎念

第一次写这么长的文章,如有错误和不足之处还请指正。

参考文章:UE4 - Be careful with the Construction Script - Isara Tech.

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-11-26 09:10:11  更:2021-11-26 09:11:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 23:54:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码