99 lines
3.8 KiB
Markdown
Raw Normal View History

2024-10-12 17:19:46 +08:00
# ExposeOnSpawn
- **功能描述:** 使该属性在ContructObject或SpawnActor等创建对象的时候暴露出来。
- **使用位置:** UPROPERTY
- **引擎模块:** Blueprint
- **元数据类型:** bool
- **常用程度:** ★★★★★
使该属性在ContructObject或SpawnActor等创建对象的时候暴露出来。
- 具体来说通过在源码搜索这个标记在UK2Node_AddComponentUK2Node_ConstructObjectFromClassUK2Node_SpawnActorUK2Node_LatentGameplayTaskCall的时候用到。
- 在C++里设置的效果等同于在蓝图里勾上ExposeOnSpawn。
- 该meta的设置也会同时设置到PropertyFlags里的CPF_ExposeOnSpawn
## 测试代码:
```cpp
UCLASS(BlueprintType)
class INSIDER_API UMyProperty_ExposeOnSpawn :public UObject
{
GENERATED_BODY()
public:
// (Category = MyProperty_ExposeOnSpawn, ModuleRelativePath = Property/Blueprint/MyProperty_ExposeOnSpawn.h)
// PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString MyString = TEXT("First");
// (Category = MyProperty_ExposeOnSpawn, ExposeOnSpawn = , ModuleRelativePath = Property/Blueprint/MyProperty_ExposeOnSpawn.h)
// PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_ExposeOnSpawn | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn))
FString MyString_ExposeOnSpawn = TEXT("Second");
};
```
## 测试效果:
可见MyString_ExposeOnSpawn 暴露了出来而MyString 没有。
![Untitled](Untitled.png)
## 原理:
在UHT的时候会分析如果包含ExposeOnSpawn就会同步设置CPF_ExposeOnSpawn。
而在IsPropertyExposedOnSpawn这个函数里具体判断是否要暴露这个函数被上述的4个函数节点引用。源码里举UK2Node_ConstructObjectFromClass里的CreatePinsForClass作为例子可见只有bIsExposedToSpawn 的时候才会为蓝图节点开始创建额外的Pin引脚。
```cpp
if (propertySettings.MetaData.ContainsKey(UhtNames.ExposeOnSpawn))
{
propertySettings.PropertyFlags |= EPropertyFlags.ExposeOnSpawn;
}
bool UEdGraphSchema_K2::IsPropertyExposedOnSpawn(const FProperty* Property)
{
Property = FBlueprintEditorUtils::GetMostUpToDateProperty(Property);
if (Property)
{
const bool bMeta = Property->HasMetaData(FBlueprintMetadata::MD_ExposeOnSpawn);
const bool bFlag = Property->HasAllPropertyFlags(CPF_ExposeOnSpawn);
if (bMeta != bFlag)
{
const FCoreTexts& CoreTexts = FCoreTexts::Get();
UE_LOG(LogBlueprint, Warning
, TEXT("ExposeOnSpawn ambiguity. Property '%s', MetaData '%s', Flag '%s'")
, *Property->GetFullName()
, bMeta ? *CoreTexts.True.ToString() : *CoreTexts.False.ToString()
, bFlag ? *CoreTexts.True.ToString() : *CoreTexts.False.ToString());
}
return bMeta || bFlag;
}
return false;
}
void UK2Node_ConstructObjectFromClass::CreatePinsForClass(UClass* InClass, TArray<UEdGraphPin*>* OutClassPins)
{
for (TFieldIterator<FProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt)
{
FProperty* Property = *PropertyIt;
UClass* PropertyClass = CastChecked<UClass>(Property->GetOwner<UObject>());
const bool bIsDelegate = Property->IsA(FMulticastDelegateProperty::StaticClass());
const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property);
const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance);
if( bIsExposedToSpawn &&
!Property->HasAnyPropertyFlags(CPF_Parm) &&
bIsSettableExternally &&
Property->HasAllPropertyFlags(CPF_BlueprintVisible) &&
!bIsDelegate &&
(nullptr == FindPin(Property->GetFName()) ) &&
FBlueprintEditorUtils::PropertyStillExists(Property))
{
if (UEdGraphPin* Pin = CreatePin(EGPD_Input, NAME_None, Property->GetFName()))
{
}
```