vault backup: 2024-10-12 17:19:45
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
# ChildCanTick
|
||||
|
||||
- **功能描述:** 标记允许其蓝图子类可以接受响应Tick事件
|
||||
- **使用位置:** UCLASS
|
||||
- **引擎模块:** Actor
|
||||
- **元数据类型:** bool
|
||||
- **限制类型:** Actor或ActorComponent子类
|
||||
- **关联项:** [ChildCannotTick](../ChildCannotTick.md)
|
||||
- **常用程度:** ★★★
|
||||
|
||||
要在蓝图中重载Tick事件函数并只会在编译的时候触发判断。
|
||||
|
||||
```cpp
|
||||
//(BlueprintType = true, ChildCannotTick = , IncludePath = Class/Blueprint/MyActor_ChildTick.h, IsBlueprintBase = true, ModuleRelativePath = Class/Blueprint/MyActor_ChildTick.h)
|
||||
UCLASS(Blueprintable,meta=(ChildCanTick))
|
||||
class INSIDER_API AMyActor_ChildCanTick : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
AMyActor_ChildCanTick()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
}
|
||||
};
|
||||
|
||||
//(BlueprintType = true, ChildCanTick = , IncludePath = Class/Blueprint/MyActor_ChildTick.h, IsBlueprintBase = true, ModuleRelativePath = Class/Blueprint/MyActor_ChildTick.h)
|
||||
UCLASS(Blueprintable,meta=(ChildCanTick))
|
||||
class INSIDER_API UMyActorComponent_ChildCanTick : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
};
|
||||
|
||||
//(BlueprintType = true, ChildCannotTick = , IncludePath = Class/Blueprint/MyActor_ChildTick.h, IsBlueprintBase = true, ModuleRelativePath = Class/Blueprint/MyActor_ChildTick.h)
|
||||
UCLASS(Blueprintable,meta=(ChildCannotTick))
|
||||
class INSIDER_API AMyActor_ChildCannotTick : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
};
|
||||
|
||||
//(BlueprintType = true, ChildCannotTick = , IncludePath = Class/Blueprint/MyActor_ChildTick.h, IsBlueprintBase = true, ModuleRelativePath = Class/Blueprint/MyActor_ChildTick.h)
|
||||
UCLASS(Blueprintable,meta=(ChildCannotTick))
|
||||
class INSIDER_API UMyActorComponent_ChildCannotTick : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
};
|
||||
```
|
||||
|
||||
蓝图Actor或ActorComponent里测试:
|
||||
|
||||
也注意到这个判断跟蓝图中是否开启Tick并没有关系。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
而AMyActor_ChildCanTick类里虽然已经手动关闭了PrimaryActorTick.bCanEverTick,但是在子类里依然可以正常的Tick(在编译的时候内部可以正常的再重新开启bCanEverTick)。
|
||||
|
||||

|
||||
|
||||
## 源码里判断的逻辑:
|
||||
|
||||
开启bCanEverTick=true的条件有3,一是EngineSettings->bCanBlueprintsTickByDefault,二是父类是AActor或UActorComponent本身,三是C++基类上有ChildCanTick的标记。
|
||||
|
||||
```cpp
|
||||
void FKismetCompilerContext::SetCanEverTick() const
|
||||
{
|
||||
// RECEIVE TICK
|
||||
if (!TickFunction->bCanEverTick)
|
||||
{
|
||||
// Make sure that both AActor and UActorComponent have the same name for their tick method
|
||||
static FName ReceiveTickName(GET_FUNCTION_NAME_CHECKED(AActor, ReceiveTick));
|
||||
static FName ComponentReceiveTickName(GET_FUNCTION_NAME_CHECKED(UActorComponent, ReceiveTick));
|
||||
|
||||
if (const UFunction* ReceiveTickEvent = FKismetCompilerUtilities::FindOverriddenImplementableEvent(ReceiveTickName, NewClass))
|
||||
{
|
||||
// We have a tick node, but are we allowed to?
|
||||
|
||||
const UEngine* EngineSettings = GetDefault<UEngine>();
|
||||
const bool bAllowTickingByDefault = EngineSettings->bCanBlueprintsTickByDefault;
|
||||
|
||||
const UClass* FirstNativeClass = FBlueprintEditorUtils::FindFirstNativeClass(NewClass);
|
||||
const bool bHasCanTickMetadata = (FirstNativeClass != nullptr) && FirstNativeClass->HasMetaData(FBlueprintMetadata::MD_ChildCanTick);
|
||||
const bool bHasCannotTickMetadata = (FirstNativeClass != nullptr) && FirstNativeClass->HasMetaData(FBlueprintMetadata::MD_ChildCannotTick);
|
||||
const bool bHasUniversalParent = (FirstNativeClass != nullptr) && ((AActor::StaticClass() == FirstNativeClass) || (UActorComponent::StaticClass() == FirstNativeClass));
|
||||
|
||||
if (bHasCanTickMetadata && bHasCannotTickMetadata)
|
||||
{
|
||||
// User error: The C++ class has conflicting metadata
|
||||
const FString ConlictingMetadataWarning = FText::Format(
|
||||
LOCTEXT("HasBothCanAndCannotMetadataFmt", "Native class %s has both '{0}' and '{1}' metadata specified, they are mutually exclusive and '{1}' will win."),
|
||||
FText::FromString(FirstNativeClass->GetPathName()),
|
||||
FText::FromName(FBlueprintMetadata::MD_ChildCanTick),
|
||||
FText::FromName(FBlueprintMetadata::MD_ChildCannotTick)
|
||||
).ToString();
|
||||
MessageLog.Warning(*ConlictingMetadataWarning);
|
||||
}
|
||||
|
||||
if (bHasCannotTickMetadata)
|
||||
{
|
||||
// This could only happen if someone adds bad metadata to AActor or UActorComponent directly
|
||||
check(!bHasUniversalParent);
|
||||
|
||||
// Parent class has forbidden us to tick
|
||||
const FString NativeClassSaidNo = FText::Format(
|
||||
LOCTEXT("NativeClassProhibitsTickingFmt", "@@ is not allowed as the C++ parent class {0} has disallowed Blueprint subclasses from ticking. Please consider using a Timer instead of Tick."),
|
||||
FText::FromString(FirstNativeClass->GetPathName())
|
||||
).ToString();
|
||||
MessageLog.Warning(*NativeClassSaidNo, FindLocalEntryPoint(ReceiveTickEvent));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bAllowTickingByDefault || bHasUniversalParent || bHasCanTickMetadata)
|
||||
{
|
||||
// We're allowed to tick for one reason or another
|
||||
TickFunction->bCanEverTick = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing allowing us to tick
|
||||
const FString ReceiveTickEventWarning = FText::Format(
|
||||
LOCTEXT("ReceiveTick_CanNeverTickFmt", "@@ is not allowed for Blueprints based on the C++ parent class {0}, so it will never Tick!"),
|
||||
FText::FromString(FirstNativeClass ? *FirstNativeClass->GetPathName() : TEXT("<null>"))
|
||||
).ToString();
|
||||
MessageLog.Warning(*ReceiveTickEventWarning, FindLocalEntryPoint(ReceiveTickEvent));
|
||||
|
||||
const FString ReceiveTickEventRemedies = FText::Format(
|
||||
LOCTEXT("ReceiveTick_CanNeverTickRemediesFmt", "You can solve this in several ways:\n 1) Consider using a Timer instead of Tick.\n 2) Add meta=({0}) to the parent C++ class\n 3) Reparent the Blueprint to AActor or UActorComponent, which can always tick."),
|
||||
FText::FromName(FBlueprintMetadata::MD_ChildCanTick)
|
||||
).ToString();
|
||||
MessageLog.Warning(*ReceiveTickEventRemedies);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 200 KiB |
Binary file not shown.
After Width: | Height: | Size: 438 KiB |
Binary file not shown.
After Width: | Height: | Size: 216 KiB |
@@ -0,0 +1,8 @@
|
||||
# ChildCannotTick
|
||||
|
||||
- **功能描述:** 用于Actor或ActorComponent子类,标记允许其蓝图子类不可以接受响应Tick事件,哪怕父类可以Tick
|
||||
- **使用位置:** UCLASS
|
||||
- **元数据类型:** bool
|
||||
- **限制类型:** Actor类
|
||||
- **关联项:** [ChildCanTick](ChildCanTick/ChildCanTick.md)
|
||||
- **常用程度:** ★★★
|
Reference in New Issue
Block a user