83 lines
3.0 KiB
Markdown
83 lines
3.0 KiB
Markdown
|
# DisableNativeTick
|
|||
|
|
|||
|
- **功能描述:** 禁用该UserWidget的NativeTick。
|
|||
|
- **使用位置:** UCLASS
|
|||
|
- **引擎模块:** Widget Property
|
|||
|
- **元数据类型:** bool
|
|||
|
- **限制类型:** UserWidget的子类
|
|||
|
- **常用程度:** ★★★
|
|||
|
|
|||
|
禁用该UserWidget的NativeTick。
|
|||
|
|
|||
|
如果只有C++类则不起作用,因为纯C++的Widget没有WidgetBPClass 。
|
|||
|
|
|||
|
而且BP的子类要删除Tick蓝图节点。
|
|||
|
|
|||
|
## 测试代码:
|
|||
|
|
|||
|
```cpp
|
|||
|
UCLASS(BlueprintType, meta=())
|
|||
|
class INSIDER_API UMyWidget_WithNativeTick :public UUserWidget
|
|||
|
{
|
|||
|
GENERATED_BODY()
|
|||
|
public:
|
|||
|
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override
|
|||
|
{
|
|||
|
Super::NativeTick(MyGeometry, InDeltaTime);
|
|||
|
UKismetSystemLibrary::PrintString(nullptr, TEXT("WithNativeTick"), true);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
UCLASS(BlueprintType,meta=(DisableNativeTick))
|
|||
|
class INSIDER_API UMyWidget_DisableNativeTick :public UUserWidget
|
|||
|
{
|
|||
|
GENERATED_BODY()
|
|||
|
public:
|
|||
|
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override
|
|||
|
{
|
|||
|
Super::NativeTick(MyGeometry, InDeltaTime);
|
|||
|
UKismetSystemLibrary::PrintString(nullptr, TEXT("DisableNativeTick"), true);
|
|||
|
}
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
## 测试效果:
|
|||
|
|
|||
|
在蓝图中分别创建UMyWidget_WithNativeTick 和UMyWidget_DisableNativeTick 的子类UMG_WithTick和UMG_DisableTick。然后把他们都添加到一个UMG里,添加到屏幕上后观察NativeTick的调用情况。
|
|||
|
|
|||
|
可见只有WithNativeTick调用。
|
|||
|
|
|||
|

|
|||
|
|
|||
|
## 原理:
|
|||
|
|
|||
|
在UCLASS上标记会导致UMG蓝图的bClassRequiresNativeTick=false。继而在UUserWidget的UpdateCanTick里判断。如果WidgetBPClass不为空(是蓝图子类)且ClassRequiresNativeTick为false,bCanTick 才一开始为false。然后判断bHasScriptImplementedTick则要求蓝图中没有EventTick(默认会创建,自己要手动删掉)。然后后面继续判断要没有延迟蓝图节点,没有动画。总之就是这个Widget要真的没有Tick的需求,则可以真的最后bCanTick=false。
|
|||
|
|
|||
|
```cpp
|
|||
|
|
|||
|
void UWidgetBlueprint::UpdateTickabilityStats(bool& OutHasLatentActions, bool& OutHasAnimations, bool& OutClassRequiresNativeTick)
|
|||
|
{
|
|||
|
static const FName DisableNativeTickMetaTag("DisableNativeTick");
|
|||
|
const bool bClassRequiresNativeTick = !NativeParent->HasMetaData(DisableNativeTickMetaTag);
|
|||
|
OutClassRequiresNativeTick = bClassRequiresNativeTick;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void FWidgetBlueprintCompilerContext::CopyTermDefaultsToDefaultObject(UObject* DefaultObject)
|
|||
|
{
|
|||
|
WidgetBP->UpdateTickabilityStats(bClassOrParentsHaveLatentActions, bClassOrParentsHaveAnimations, bClassRequiresNativeTick);
|
|||
|
WidgetClass->SetClassRequiresNativeTick(bClassRequiresNativeTick);
|
|||
|
}
|
|||
|
|
|||
|
void UUserWidget::UpdateCanTick()
|
|||
|
{
|
|||
|
UWidgetBlueprintGeneratedClass* WidgetBPClass = Cast<UWidgetBlueprintGeneratedClass>(GetClass());
|
|||
|
bCanTick |= !WidgetBPClass || WidgetBPClass->ClassRequiresNativeTick();
|
|||
|
bCanTick |= bHasScriptImplementedTick;
|
|||
|
bCanTick |= World->GetLatentActionManager().GetNumActionsForObject(this) != 0;
|
|||
|
bCanTick |= ActiveSequencePlayers.Num() > 0;
|
|||
|
bCanTick |= QueuedWidgetAnimationTransitions.Num() > 0;
|
|||
|
SafeGCWidget->SetCanTick(bCanTick);
|
|||
|
}
|
|||
|
```
|