vault backup: 2024-10-12 17:19:45
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# BlueprintCallable
|
||||
|
||||
- **功能描述:** 暴露到蓝图中可被调用
|
||||
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Blueprint
|
||||
- **作用机制:** 在FunctionFlags增加[FUNC_BlueprintCallable](../../../../Flags/EFunctionFlags/FUNC_BlueprintCallable.md)
|
||||
- **常用程度:** ★★★★★
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void MyFunc_BlueprintCallable() {}
|
||||
```
|
||||
|
||||
## 效果展示:
|
||||
|
||||

|
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,14 @@
|
||||
# BlueprintGetter
|
||||
|
||||
- **功能描述:** 指定该函数作为属性的自定义Get函数。
|
||||
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Blueprint
|
||||
- **作用机制:** 在Meta中加入[BlueprintGetter](../../../Meta/Blueprint/BlueprintGetter.md),在FunctionFlags加入[FUNC_BlueprintCallable](../../../Flags/EFunctionFlags/FUNC_BlueprintCallable.md)、[FUNC_BlueprintPure](../../../Flags/EFunctionFlags/FUNC_BlueprintPure.md)
|
||||
- **常用程度:** ★★
|
||||
|
||||
指定该函数作为属性的自定义Get函数。
|
||||
|
||||
此说明符隐含BlueprintPure和BlueprintCallable。
|
||||
|
||||
更多可以参考UPROPERTY的BlueprintGetter
|
@@ -0,0 +1,39 @@
|
||||
# BlueprintImplementableEvent
|
||||
|
||||
- **功能描述:** 指定一个函数调用点,可以在蓝图中重载实现。
|
||||
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Blueprint
|
||||
- **作用机制:** 在FunctionFlags中增加[FUNC_Event](../../../../Flags/EFunctionFlags/FUNC_Event.md)、[FUNC_Native](../../../../Flags/EFunctionFlags/FUNC_Native.md)、[FUNC_BlueprintEvent](../../../../Flags/EFunctionFlags/FUNC_BlueprintEvent.md)
|
||||
- **常用程度:** ★★★★★
|
||||
|
||||
指定一个函数调用点,可以在蓝图中重载实现。是一种方便的用来实现C++来调用蓝图函数的方式。
|
||||
|
||||
蓝图中如果没提供实现,调用的话相当于调用空函数。
|
||||
|
||||
BlueprintImplementableEvent也要配合BlueprintCallable使用,如果没加BlueprintCallable的话就只能在CPP里调用,在蓝图会发现找不到Call Function的节点。
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
//FunctionFlags: FUNC_Event | FUNC_Public | FUNC_BlueprintCallable | FUNC_BlueprintEvent
|
||||
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
|
||||
void MyFunc_ImplementableEvent();
|
||||
```
|
||||
|
||||
## 效果展示:
|
||||
|
||||
右键可添加自定义实现
|
||||
|
||||

|
||||
|
||||
## 原理:
|
||||
|
||||
在C++里调用的时候,里面会FindFunctionChecked根据名字寻找。如果蓝图中有找到的话,则会调用。如果在蓝图中直接调用,则其实是会直接FindFunctionChecked查找,蓝图中有定义的话则会被直接找到。
|
||||
|
||||
```cpp
|
||||
void AMyFunction_Default::MyFunc_ImplementableEvent()
|
||||
{
|
||||
ProcessEvent(FindFunctionChecked(NAME_AMyFunction_Default_MyFunc_ImplementableEvent),NULL);
|
||||
}
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
@@ -0,0 +1,49 @@
|
||||
# BlueprintNativeEvent
|
||||
|
||||
- **功能描述:** 可以在蓝图总覆盖实现,但是也在C++中提供一个默认实现。
|
||||
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Blueprint
|
||||
- **作用机制:** 在FunctionFlags中增加[FUNC_Event](../../../../Flags/EFunctionFlags/FUNC_Event.md)、[FUNC_BlueprintEvent](../../../../Flags/EFunctionFlags/FUNC_BlueprintEvent.md)
|
||||
- **常用程度:** ★★★★★
|
||||
|
||||
可以在蓝图总覆盖实现,但是也在C++中提供一个默认实现。
|
||||
|
||||
需要在CPP中声明名称与主函数相同的附加函数,但是末尾添加了_Implementation。如果未找到任何蓝图覆盖,该自动生成的代码将调用“ [FunctionName]_Implementation”方法。一般用在OnXXX之类的函数上,在C++提供实现,这样如果蓝图中没有覆盖的时候,就可以默认调用C++中默认实现版本。
|
||||
BlueprintNativeEvent,没加BlueprintCallable的话就只能在CPP里调用,因此一般也要配合加上BlueprintCallable。
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
//FunctionFlags: FUNC_Native | FUNC_Event | FUNC_Public | FUNC_BlueprintCallable | FUNC_BlueprintEvent
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void MyFunc_NativeEvent();
|
||||
|
||||
void AMyFunction_Default::MyFunc_NativeEvent_Implementation()
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, "MyFunc_NativeEvent_Implementation");
|
||||
}
|
||||
```
|
||||
|
||||
## 效果展示:
|
||||
|
||||

|
||||
|
||||
## 原理:
|
||||
|
||||
在调用MyFunc_NativeEvent的时候,内部FindFunctionChecked会根据名字查找,如果在蓝图中有定义,则会找到蓝图中的实现版本。否则的话,则会找到execMyFunc_NativeEvent这个实现版本,从而调用MyFunc_NativeEvent_Implementation。
|
||||
|
||||
```cpp
|
||||
DEFINE_FUNCTION(AMyFunction_Default::execMyFunc_NativeEvent)
|
||||
{
|
||||
P_FINISH;
|
||||
P_NATIVE_BEGIN;
|
||||
P_THIS->MyFunc_NativeEvent_Implementation();
|
||||
P_NATIVE_END;
|
||||
}
|
||||
|
||||
void AMyFunction_Default::MyFunc_NativeEvent()
|
||||
{
|
||||
ProcessEvent(FindFunctionChecked(NAME_AMyFunction_Default_MyFunc_NativeEvent),NULL);
|
||||
}
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 82 KiB |
@@ -0,0 +1,26 @@
|
||||
# BlueprintPure
|
||||
|
||||
- **功能描述:** 指定作为一个纯函数,一般用于Get函数用来返回值。
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Blueprint
|
||||
- **作用机制:** 在FunctionFlags增加[FUNC_BlueprintCallable](../../../../Flags/EFunctionFlags/FUNC_BlueprintCallable.md)、[FUNC_BlueprintPure](../../../../Flags/EFunctionFlags/FUNC_BlueprintPure.md)
|
||||
- **常用程度:** ★★★★★
|
||||
|
||||
指定作为一个纯函数,一般用于Get函数用来返回值。
|
||||
|
||||
- 纯函数是指没有执行引脚的函数,不是指const函数。
|
||||
- 纯函数可以有多个返回值,用引用参数加到函数里就行。
|
||||
- 不能用于void函数,否则会报错“error : BlueprintPure specifier is not allowed for functions with no return value and no output parameters.”
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
UFUNCTION(BlueprintPure)
|
||||
int32 GetMyInt()const { return MyInt; }
|
||||
private:
|
||||
int32 MyInt;
|
||||
```
|
||||
|
||||
## 效果展示:
|
||||
|
||||

|
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@@ -0,0 +1,13 @@
|
||||
# BlueprintSetter
|
||||
|
||||
- **功能描述:** 指定该函数作为属性的自定义Set函数。
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Blueprint
|
||||
- **作用机制:** 在Meta中加入[BlueprintSetter](../../../Meta/Blueprint/BlueprintSetter.md),在FunctionFlags中加入[FUNC_BlueprintCallable ](../../../Flags/EFunctionFlags/FUNC_BlueprintCallable.md)
|
||||
- **常用程度:** ★★
|
||||
|
||||
指定该函数作为属性的自定义Set函数。
|
||||
|
||||
此说明符隐含BlueprintCallable。
|
||||
|
||||
更多可以参考UPROPERTY的BlueprintSetter
|
@@ -0,0 +1,32 @@
|
||||
# CallInEditor
|
||||
|
||||
- **功能描述:** 可以在属性细节面板上作为一个按钮来调用该函数。
|
||||
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Editor
|
||||
- **作用机制:** 在Meta中增加[CallInEditor](../../../../Meta/Blueprint/CallInEditor.md)
|
||||
- **常用程度:** ★★★★★
|
||||
|
||||
可以在属性细节面板上作为一个按钮来调用该函数。
|
||||
|
||||
该函数写在AActor或UObject子类里都是可以的,只要有对应的属性细节面板。
|
||||
|
||||
注意这一般是处于Editor运行环境的。典型的例子是ASkyLight的Recapture按钮。因此函数里有时会调用编辑器环境下函数。但也要注意不要在runtime下混用了,比较容易出错。
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class INSIDER_API AMyFunction_Default :public AActor
|
||||
{
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(CallInEditor)
|
||||
void MyFunc_CallInEditor(){}
|
||||
};
|
||||
```
|
||||
|
||||
## 蓝图展示:
|
||||
|
||||

|
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
@@ -0,0 +1,106 @@
|
||||
# SealedEvent
|
||||
|
||||
- **功能描述:** 无法在子类中覆盖此函数。SealedEvent关键词只能用于事件。对于非事件函数,请将它们声明为static或final,以密封它们。
|
||||
|
||||
- **元数据类型:** bool
|
||||
- **引擎模块:** Behavior
|
||||
- **作用机制:** 在FunctionFlags中添加[FUNC_Final](../../../../Flags/EFunctionFlags/FUNC_Final.md)
|
||||
|
||||
在源码里搜索:发现都是用在网络的函数上
|
||||
|
||||

|
||||
|
||||
## UHT中的处理:
|
||||
|
||||
```cpp
|
||||
//先识别符号
|
||||
[UhtSpecifier(Extends = UhtTableNames.Function, ValueType = UhtSpecifierValueType.Legacy)]
|
||||
private static void SealedEventSpecifier(UhtSpecifierContext specifierContext)
|
||||
{
|
||||
UhtFunction function = (UhtFunction)specifierContext.Type;
|
||||
function.FunctionExportFlags |= UhtFunctionExportFlags.SealedEvent;
|
||||
}
|
||||
|
||||
//再设置标记
|
||||
// Handle the initial implicit/explicit final
|
||||
// A user can still specify an explicit final after the parameter list as well.
|
||||
if (automaticallyFinal || function.FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent))
|
||||
{
|
||||
function.FunctionFlags |= EFunctionFlags.Final;
|
||||
function.FunctionExportFlags |= UhtFunctionExportFlags.Final | UhtFunctionExportFlags.AutoFinal;
|
||||
}
|
||||
|
||||
再验证:限定只能用在Event上。
|
||||
|
||||
if (FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent) && !FunctionFlags.HasAnyFlags(EFunctionFlags.Event))
|
||||
{
|
||||
this.LogError("SealedEvent may only be used on events");
|
||||
}
|
||||
|
||||
if (FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent) && FunctionFlags.HasAnyFlags(EFunctionFlags.BlueprintEvent))
|
||||
{
|
||||
this.LogError("SealedEvent cannot be used on Blueprint events");
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
//Error: "SealedEvent may only be used on events"
|
||||
UFUNCTION(SealedEvent)
|
||||
void MyFunc_SealedEvent() {}
|
||||
|
||||
//Error: "SealedEvent cannot be used on Blueprint events"
|
||||
UFUNCTION(BlueprintCallable,BlueprintImplementableEvent,SealedEvent)
|
||||
void MyFunc_ImplementableEvent();
|
||||
|
||||
//Error: "SealedEvent cannot be used on Blueprint events"
|
||||
UFUNCTION(BlueprintCallable,BlueprintNativeEvent,SealedEvent)
|
||||
void MyFunc_NativeEvent();
|
||||
```
|
||||
|
||||
因此无法用于普通的函数,又无法用于蓝图中的Event。所以既是Event又不是BlueprintEvent的是什么?看源码是只有网络的一些函数。
|
||||
|
||||
通过对比,发现Sealed函数的区别是多了FUNC_Final的标记。但FUNC_Final又不一定必须要以SealedEvent才能添加,exec或普通的BlueprintCallable函数都会添加。但是如果是vitural的函数就不会添加。在UHT中的原理是:
|
||||
|
||||
```cpp
|
||||
private static UhtParseResult ParseUFunction(UhtParsingScope parentScope, UhtToken token)
|
||||
{
|
||||
if (function.FunctionFlags.HasAnyFlags(EFunctionFlags.Net))
|
||||
{
|
||||
// Network replicated functions are always events, and are only final if sealed
|
||||
scopeName = "event";
|
||||
tokenContext.Reset(scopeName);
|
||||
automaticallyFinal = false;
|
||||
}
|
||||
|
||||
// If virtual, remove the implicit final, the user can still specifying an explicit final at the end of the declaration
|
||||
if (function.FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.Virtual))
|
||||
{
|
||||
automaticallyFinal = false;
|
||||
}
|
||||
// Handle the initial implicit/explicit final
|
||||
// A user can still specify an explicit final after the parameter list as well.
|
||||
if (automaticallyFinal || function.FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent))
|
||||
{
|
||||
function.FunctionFlags |= EFunctionFlags.Final;
|
||||
function.FunctionExportFlags |= UhtFunctionExportFlags.Final | UhtFunctionExportFlags.AutoFinal;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
在自己的C++代码中测试,发现在C++中怎么继承都不会触发编译错误。因此如果想拒绝被继承,还是用C++标准是final关键字。在函数末尾加final。
|
||||
|
||||
E:\P4V\Engine\Source\Editor\KismetCompiler\Private\KismetCompiler.cpp
|
||||
|
||||
```cpp
|
||||
const uint32 OverrideFlagsToCheck = (FUNC_FuncOverrideMatch & ~FUNC_AccessSpecifiers);
|
||||
if ((Context.Function->FunctionFlags & OverrideFlagsToCheck) != (OverridenFunction->FunctionFlags & OverrideFlagsToCheck))
|
||||
{
|
||||
MessageLog.Error(*LOCTEXT("IncompatibleOverrideFlags_Error", "Overriden function is not compatible with the parent function @@. Check flags: Exec, Final, Static.").ToString(), Context.EntryPoint);
|
||||
}
|
||||
```
|
||||
|
||||
在编译的时候检测的是否是重载父类的函数,但因为SealedEvent不作用于普通函数,也不作用于BlueprintEvent,因此感觉只能在C++中继承。
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Reference in New Issue
Block a user