代码命名规则
- 模版类:T 前缀(如 TArray,TMap,TSet)
- UObject 派生类:U前缀
- AActor 派生类:A 前缀
- SWidget 派生类:S 前缀
- 全局对象:G 开头(如 GEngine)
- 抽象接口:I 前缀
- 枚举:E 开头
- bool 变量:b 前缀
- 其他的大部分以 F 开头(如FString,FName)
- typedef 的以原型名前缀为准(如 typedef TArray FArrayOfMyTypes)
- 在编辑器里和 C# 里,类型名是省略掉Actor
Actor
- Actor 是载体,放在Actor 上的东西称之为组件 Component(每一个 Actor 在场景中都不具备存在的能力,但添加了场景组件 SceneComponent,就可以在场景中存在)
- 创建 Actor 的方式:
- ① 静态创建:直接在场景中编辑拖拽
- 优势:创建由引擎构建场景时进行创建,无需编码,更加直观简单
- 缺点:可能会影响游戏启动速度,增加场景构建负担
- ② 动态创建:通过编码动态进行生成
- 优势:可控性更强,动态生成的 Actor 会持有有效的操作指针,可根据实际情况生成,更加灵活
- 缺点:难,复杂
- ① 静态创建:直接在场景中编辑拖拽
常用调式方法
屏幕日志输出
全局变量GEngine指针调用函数 AddOnScreenDebugMessage,完成屏幕输出
ENGINE_API void AddOnScreenDebugMessage(
int32 Key,
float TimeToDisplay,
FColor DisplayColor,
const FString& DebugMessage,
bool bNewerOnTop = true,
const FVector2D& TextScale = FVector2D::UnitVector
);
例如:
GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Blue, TEXT("HI"));
控制台日志输出
日志类型冗余度,分为:
-
Fatal(会终止进程)致命问题
-
Error(会终止进程)错误问题
-
Warning、Display、Log(较常用的日志分类项)
-
Verbose (将日志详细信息记录到日志文档,但不向控制台输出)
-
VeryVerbose(将日志详细信息记录到日志文档,但不向控制台输出)
UE_LOG(LogAutomationController, Display, TEXT(
"Report can be opened in the editor at '%s'"), ReportExportPath.IsEmpty() ? *FPaths::ConvertRelativePathToFull(FPaths::AutomationReportsDir()) : *ReportExportPath);
宏标记
UClass
//① 可以作为蓝图中的一种变量类型使用,类默认均可被蓝图访问
UCLASS(BlueprintType)
//② 默认可被继承,标记关系向子类传递,子类可覆盖描述关系
UCLASS(Blueprintable)
UCLASS(BlueprintType,NotBlueprintable) // 可访问,但不可继承
//③ 将类声明为“抽象基类”,这样会阻止用户在虚幻编辑器中向这个世界中添加这个类的Actor,或者在游戏过程中创建这个类的实例
UCLASS(Abstract)
//④ 所有属性及函数均为常量,并应作为常量导出。该标识由子类继承
UCLASS(Const)
//⑤ 类内的成员变量数据信息保存到本地配置文件中,需要显式调用函数SaveConfig使用,并配合UPROPERTY宏操作
UCLASS(Config=Game)
//⑥ 用来配置组件在添加时分组情况
UCLASS(ClassGroup = (TestClass01))
UFUNCTION 宏
//1. BlueprintCallable:表明此函数可在蓝图中被调用(当类被蓝图继承后才有效果)
UFUNCTION(BlueprintCallable)
void Func(int32& A, const int32& B); //void Func(输出针脚, 输入针脚)
//如果函数参数是引用类型,则在蓝图中调用被当做输出针脚
//如果传入参数是const修饰的引用类型,则在蓝图中被当做输入针脚
//2. Category:标明此函数在蓝图中的分类
Category=”UE4Test|MyActor” // |符号用来划分分类级别
UFUNCTION(BlueprintCallable,Category=”UE4Test|MyActor”);
//3. BlueprintImplementableEvent:用此标记可以在C++中构建函数声明,但是定义由蓝图完成,从而达到C++向蓝图进行调用的目的,在CPP无需定义
public:
UFUNCTION(BlueprintImplementableEvent, Category = "UECPP|ACPPActory")
void Func();
//必须放在公有或受保护的访问域中,不能在C++中定义函数(本质上相当于纯虚函数virtual)
//注意:
//① 无参无返,则在蓝图中当作事件Event使用;
//② 无参有返,则在蓝图中当作函数使用(需要在函数的overlap中寻找)
//③ 有参无返(基本数据类型),当作普通事件输入参数使用
//④ 有参无返(自定义数据类型,如FString),编译不过
//⑤ 有参无返(基本数据类型/自定义数据类型引用),当作函数看待,在函数表中寻找
//4. BlueprintNativeEvent:标记的函数只能在c++中调用,在蓝图中无法调用,此标记可以标注函数可在蓝图中被重写,并且具备在C++中有另一个标记函数
UFUNCTION(BlueprintNativeEvent)
void Func01(int32 Num); //在蓝图中调用
void Func01_Implementation(int32 Num);
//如果蓝图重写此函数,则函数实现在蓝图,如果蓝图没有重写此函数,则函数实现在(函数名_ Implementation)上
//蓝图中实现后,可以右键函数节点,选择add call to parent function可以调用父类的函数逻辑(类似类中的虚函数,在继承关系中子类可以调用父类的虚函数)
//注意:
//① 无参无返,则在蓝图中当作事件Event使用;
//② 无参有返,则在蓝图中当作函数使用(需要在函数的overlap中寻找)
//5.BlueprintPure:特殊标记,构建一个蓝图中的纯函数,用来获取对象数据
//此标记的函数必须有有效返回值(无返回值编译报错),且在蓝图中无法加入到执行队列,只能以输出值的操作方式被使用,定义实现均放在cpp中
UFUNCTION(BlueprintCallable, BlueprintPure)
UPROPERTY 宏
常用宏标记:
- ① Category:分组(定义属性的分类)
UPROPERTY(Category=CategoryName) Type VariableName; UPROPERTY(Category="CategoryName|SubCategoryName") Type VariableName; UPROPERTY(EditAnywhere, Category = "MyCategory") int CategoryNum; UPROPERTY(EditAnywhere, Category = "MyCategory|SubCategory") int SubCategoryNum;
- ② Blueprint
//----------以下2个不兼容,只能取其一: //① BlueprintReadOnly:只读 UPROPERTY(BlueprintReadOnly) //② BlueprintReadWrite:可读可写 UPROPERTY(BlueprintReadWrite) //----------以下2个仅能用于Multicast代理: //③ BlueprintAssignable:应显示该属性,以供在蓝图中分配 UPROPERTY(BlueprintAssignable) //④ BlueprintCallable:应显示该属性,以在蓝图代码中调用 UPROPERTY(BlueprintCallable)
- ③ Edit
//① EditAnywhere:可从编辑器内的属性窗口编辑,在原型和实例中 //(可以在编辑器窗口中进行编辑,也可在场景细节面板中编辑) UPROPERTY(EditAnywhere) //② EditDefaultsOnly:可通过属性窗口来编辑,仅能对原型编辑 //(可以在蓝图编辑器中编辑原型数据,但无法在场景细节面板中编辑场景中的具体对象) UPROPERTY(EditDefaultsOnly) //③ EditInstanceOnly:可通过属性窗口来编辑,仅能对实例而非原型进行编辑 //(属性的修改权限在实例,不能在蓝图编辑器原型中修改) UPROPERTY(EditInstanceOnly) //④ EditFixedSize:限定动态数组长度,禁止用户在蓝图属性面板中修改(单一添加无法显式,需要配合使用上面两个标记) //只限制修改数组大小,不限制普通变量 UPROPERTY(BlueprintReadWrite, EditAnyWhere, EditFixedSize) //⑤ EditInline:使得用户可编辑UnrealEd的属性查看器中的变量所引用的对象属性 //(仅对对象引用可用,包括对象引用数组) UPROPERTY(EditInline)
- ④ Visible
//① VisibleAnywhere:在属性窗口可见但无法编辑(原型实例中均可看到) //如果标记组件指针,则表示组件内容在场景和编辑器的细节面板中显示所有编辑项 //如果标记的是普通属性(指针、基本数据类型、复合数据类型),则在场景和编辑器中只显示,无法编辑 UPROPERTY(VisibleAnywhere) //② VisibleDefaultsOnly:仅在原型蓝图编辑器属性窗口中可见,无法编辑 //如果标记组件指针,则表示组件内容在场景和编辑器的细节面板中显示所有编辑项 //如果标记的是普通属性(指针、基本数据类型、复合数据类型),则只在编辑器中会显示(不在场景细节面板中显示),无法编辑 UPROPERTY(VisibleDefaultsOnly) //⑩ VisibleInstanceOnly:仅在实例属性窗口中可见,无法编辑 //如果标记组件指针,则表示组件内容在场景和编辑器的细节面板中显示所有编辑项 ///如果标记的是普通属性(指针、基本数据类型、复合数据类型),则只在场景细节面板中会显示(不在编辑器中显示),无法编辑 UPROPERTY(VisibleInstanceOnly)
- ⑤ 其他
- AdvancedDisplay:将属性信息在细节面板中隐藏到高级显式项内容中
UPROPERTY(EditAnywhere, Category = "Adv") int AdvNum1; UPROPERTY(EditAnywhere, AdvancedDisplay, Category = "Adv") int AdvNum2;
- Config:标记此属性可被存储到指定的配置文件中,启动时属性内容将从配置文件中获取
UPROPERTY(Config)
- meta=(DisplayName=”别名”):别名标记指令
//给函数或属性取一个别名,用于蓝图显示和搜索 //可用在修饰属性和函数上,要和暴露到蓝图中的宏连用 UPROPERTY(BlueprintReadWrite, EditAnyWhere, meta=(DisplayName=”取一个别名”))
-
成员属性值域约束
//只在UI上约束,填入数据不约束 UPROPERTY(EditAnyWhere, meta = (UIMin="10", UIMax = "20")) //UI上约束,填入数据也被约束 UPROPERTY(EditAnyWhere, meta = (ClampMin = "0", ClampMax = "10"))
-
成员属性修改约束
//EditCondition="bShow",借助一个布尔变量用来控制另一个变量是否可以在面板中被修改 UPROPERTY(EditAnywhere, EditFixedSize) bool bShow; UPROPERTY(EditAnywhere, AdvancedDisplay, meta = (ClampMin = "0", ClampMax = "10", EditCondition="bShow")) int32 wock; //蓝图可以访问C++中private中的属性,作用于在private中不能使用BlueprintReadWrite,加了(AllowPrivateAccess = “true”)之后就会把C++中私有的属性继承到蓝图并变成公有属性 UPROPERTY(EditAnywhere, EditFixedSize, meta = (AllowPrivateAccess = “true”))
UMETA 宏
- 可以帮助枚举名进行蓝图别名创建,方便在蓝图中寻找操作(空间声明枚举的方式不适用)
- AdvancedDisplay:将属性信息在细节面板中隐藏到高级显式项内容中
UENUM(BlueprintType)
//必须加上
enum ZQState
{
Game UMETA(DisplayName = 'ZWJ')
};
借鉴文章【UEC++】虚幻C++基础入门 - 哟吼--小文文公主 - 博客园 (cnblogs.com)