ue5 UGameplayTask和 UGameplayBehavior 和USmartObjectBehaviorDefinition
ue5.3.2
UAbilityTask太庞大暂时不说
UGameplayTask是基础 ,对应的应该有UGameplayTasksComponent
启动一个Task,通过调用UGameplayTasksComponent的static方法来run一个task,还有蓝图方法
代码如下
UFUNCTION(BlueprintCallable, DisplayName="Run Gameplay Task", meta=(ScriptName="RunGameplayTask"), Category = "Gameplay Tasks", meta = (AutoCreateRefTerm = "AdditionalRequiredResources, AdditionalClaimedResources", AdvancedDisplay = "AdditionalRequiredResources, AdditionalClaimedResources"))
static GAMEPLAYTASKS_API EGameplayTaskRunResult K2_RunGameplayTask(TScriptInterface<IGameplayTaskOwnerInterface> TaskOwner, UGameplayTask* Task, uint8 Priority, TArray<TSubclassOf<UGameplayTaskResource> > AdditionalRequiredResources, TArray<TSubclassOf<UGameplayTaskResource> > AdditionalClaimedResources);
static GAMEPLAYTASKS_API EGameplayTaskRunResult RunGameplayTask(IGameplayTaskOwnerInterface& TaskOwner, UGameplayTask& Task, uint8 Priority, FGameplayResourceSet AdditionalRequiredResources, FGameplayResourceSet AdditionalClaimedResources);
EGameplayTaskRunResult UGameplayTasksComponent::RunGameplayTask(IGameplayTaskOwnerInterface& TaskOwner, UGameplayTask& Task, uint8 Priority, FGameplayResourceSet AdditionalRequiredResources, FGameplayResourceSet AdditionalClaimedResources)
{
const FText NoneText = FText::FromString(TEXT("None"));
if (Task.GetState() == EGameplayTaskState::Paused || Task.GetState() == EGameplayTaskState::Active)
{
// return as success if already running for the same owner, failure otherwise
return Task.GetTaskOwner() == &TaskOwner
? (Task.GetState() == EGameplayTaskState::Paused ? EGameplayTaskRunResult::Success_Paused : EGameplayTaskRunResult::Success_Active)
: EGameplayTaskRunResult::Error;
}
// this is a valid situation if the task has been created via "Construct Object" mechanics
if (Task.GetState() == EGameplayTaskState::Uninitialized)
{
Task.InitTask(TaskOwner, Priority);
}
Task.AddRequiredResourceSet(AdditionalRequiredResources);
Task.AddClaimedResourceSet(AdditionalClaimedResources);
Task.ReadyForActivation();
switch (Task.GetState())
{
case EGameplayTaskState::AwaitingActivation:
case EGameplayTaskState::Paused:
return EGameplayTaskRunResult::Success_Paused;
break;
case EGameplayTaskState::Active:
return EGameplayTaskRunResult::Success_Active;
break;
case EGameplayTaskState::Finished:
return EGameplayTaskRunResult::Success_Active;
break;
}
return EGameplayTaskRunResult::Error;
}
??另外一种调用的方法就是手动的调用void UGameplayTask::InitTask方法也可以
void UGameplayTask::InitTask(IGameplayTaskOwnerInterface& InTaskOwner, uint8 InPriority)
{
Priority = InPriority;
TaskOwner = &InTaskOwner;
TaskState = EGameplayTaskState::AwaitingActivation;
if (bClaimRequiredResources)
{
ClaimedResources.AddSet(RequiredResources);
}
// call owner.OnGameplayTaskInitialized before accessing owner.GetGameplayTasksComponent, this is required for child tasks
InTaskOwner.OnGameplayTaskInitialized(*this);
UGameplayTasksComponent* GTComponent = InTaskOwner.GetGameplayTasksComponent(*this);
TasksComponent = GTComponent;
bOwnedByTasksComponent = (TaskOwner.GetObject() == GTComponent);
// make sure that task component knows about new task
if (GTComponent && !bOwnedByTasksComponent)
{
//Task初始化事件通知
GTComponent->OnGameplayTaskInitialized(*this);
}
}
调用的时候需要指定IGameplayTaskOwnerInterface& Owner,目前所知道的被AAIController控制的APawn都会默认创建UGameplayTasksComponent对象,而UGameplayTasksComponent就是继承了IGameplayTaskOwnerInterface接口。所以NPC具有运行UGameplaytask的天然优势。
void AAIController::OnPossess(APawn* InPawn)
{
// don't even try possessing pending-kill pawns
if (InPawn != nullptr && !IsValid(InPawn))
{
return;
}
Super::OnPossess(InPawn);
if (GetPawn() == nullptr || InPawn == nullptr)
{
return;
}
// not calling UpdateNavigationComponents() anymore. The PathFollowingComponent
// is now observing newly possessed pawns (via OnNewPawn)
if (PathFollowingComponent)
{
PathFollowingComponent->Initialize();
}
if (bWantsPlayerState)
{
ChangeState(NAME_Playing);
}
// a Pawn controlled by AI _requires_ a GameplayTasksComponent, so if Pawn
// doesn't have one we need to create it
if (CachedGameplayTasksComponent == nullptr)
{
UGameplayTasksComponent* GTComp = InPawn->FindComponentByClass<UGameplayTasksComponent>();
if (GTComp == nullptr)
{
GTComp = NewObject<UGameplayTasksComponent>(InPawn, TEXT("GameplayTasksComponent"));
GTComp->RegisterComponent();
}
CachedGameplayTasksComponent = GTComp;
}
..........................
}
void UGameplayTask::ReadyForActivation()
?如果想立刻执行,而不是根据优先级排序执行
就要确保
FORCEINLINE bool RequiresPriorityOrResourceManagement() const { return bCaresAboutPriority == true || RequiredResources.IsEmpty() == false || ClaimedResources.IsEmpty() == false; }
这个返回是false就行
void UGameplayTask::ReadyForActivation()
{
//没有UGameplayTasksComponent 就endtask
if (UGameplayTasksComponent* TasksPtr = TasksComponent.Get())
{
//是否需要按权重执行
if (RequiresPriorityOrResourceManagement() == false)
{
PerformActivation();
}
else
{
TasksPtr->AddTaskReadyForActivation(*this);
}
}
else
{
EndTask();
}
}
?先说不按权重的执行
void UGameplayTask::PerformActivation()
{
//如果此Task是在运行状态就直接Return
if (TaskState == EGameplayTaskState::Active)
{
UE_VLOG(GetGameplayTasksComponent(), LogGameplayTasks, Warning
, TEXT("%s PerformActivation called while TaskState is already Active. Bailing out.")
, *GetName());
return;
}
TaskState = EGameplayTaskState::Active;
//激活task
Activate();
// Activate call may result in the task actually "instantly" finishing.
// If this happens we don't want to bother the TaskComponent
// with information on this task
if (IsFinished() == false)
{
//激活事件通知
TasksComponent->OnGameplayTaskActivated(*this);
}
}
?
void UGameplayTask::Activate()
{
//一般都要重载这个函数
UE_VLOG(GetGameplayTasksComponent(), LogGameplayTasks, Verbose
, TEXT("%s Activate called, current State: %s")
, *GetName(), *GetTaskStateName());
}
?
//本来以为Task的Active函数就是执行逻辑了,没想到到这里又根据不同属性分发到不同的容器中
//那就看看这三个容器分别是干啥的
void UGameplayTasksComponent::OnGameplayTaskActivated(UGameplayTask& Task)
{
// process events after finishing all operations
FEventLock ScopeEventLock(this);
//容器1,总容器来一个收一个
KnownTasks.Add(&Task);
if (Task.IsTickingTask())
{
check(TickingTasks.Contains(&Task) == false);
//容器2,看来准备在tick中用
TickingTasks.Add(&Task);
// If this is our first ticking task, set this component as active so it begins ticking
if (TickingTasks.Num() == 1)
{
UpdateShouldTick();
}
}
//这个能网络同步,牛
if (Task.IsSimulatedTask())
{
//容器3,能网络同步到客户端
const bool bWasAdded = AddSimulatedTask(&Task);
check(bWasAdded == true);
}
IGameplayTaskOwnerInterface* TaskOwner = Task.GetTaskOwner();
if (!Task.IsOwnedByTasksComponent() && TaskOwner)
{
TaskOwner->OnGameplayTaskActivated(Task);
}
}
?KnownTasks就是收录了所有active的task,只是收集记录,并没有操作task
TickingTasks存放需要tick的task
然后在
void UGameplayTasksComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
SCOPE_CYCLE_COUNTER(STAT_TickGameplayTasks);
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// Because we have no control over what a task may do when it ticks, we must be careful.
// Ticking a task may kill the task right here. It could also potentially kill another task
// which was waiting on the original task to do something. Since when a tasks is killed, it removes
// itself from the TickingTask list, we will make a copy of the tasks we want to service before ticking any
int32 NumTickingTasks = TickingTasks.Num();
int32 NumActuallyTicked = 0;
switch (NumTickingTasks)
{
case 0:
break;
case 1:
{
UGameplayTask* TickingTask = TickingTasks[0];
if (IsValid(TickingTask))
{
TickingTask->TickTask(DeltaTime);
NumActuallyTicked++;
}
}
break;
default:
{
static TArray<UGameplayTask*> LocalTickingTasks;
LocalTickingTasks.Reset();
LocalTickingTasks.Append(TickingTasks);
for (UGameplayTask* TickingTask : LocalTickingTasks)
{
if (IsValid(TickingTask))
{
TickingTask->TickTask(DeltaTime);
NumActuallyTicked++;
}
}
}
break;
};
// Stop ticking if no more active tasks
if (NumActuallyTicked == 0)
{
TickingTasks.SetNum(0, false);
UpdateShouldTick();
}
}
UAITask_UseGameplayBehaviorSmartObject
?? ?UAITask_UseGameplayBehaviorSmartObject* UseSOTask = NewBTAITask<UAITask_UseGameplayBehaviorSmartObject>(OwnerComp);
?? ?UseSOTask->SetClaimHandle(ClaimHandle);
?? ?UseSOTask->ReadyForActivation();
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!