孟宇 2 ヶ月 前
コミット
e9e9d1086b

+ 7 - 7
Ability/Plugins/EzAbility/Source/EzAbility/Private/EzAbilityComponent.cpp

@@ -81,13 +81,13 @@ void UEzAbilityComponent::TickComponent(
 {
 	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
 
-	// EAbilityRunStatus Previous	= AbilityContext.GetAbilityRunStatus();
-	// EAbilityRunStatus Current	= AbilityContext.Tick(DeltaTime);
-	//
-	// if(Previous != Current)
-	// {
-	// 	OnAbilityRunStatusChanged.Broadcast(Current);
-	// }
+	EAbilityRunStatus Previous	= AbilityContext.GetAbilityRunStatus();
+	EAbilityRunStatus Current	= AbilityContext.Tick(DeltaTime);
+	
+	if(Previous != Current)
+	{
+		OnAbilityRunStatusChanged.Broadcast(Current);
+	}
 }
 
 void UEzAbilityComponent::CacheIsNetSimulated()

+ 276 - 224
Ability/Plugins/EzAbility/Source/EzAbility/Private/EzAbilityContext.cpp

@@ -570,6 +570,16 @@ TArray<FName> FEzAbilityContext::GetActiveStateNames() const
 	return Result;
 }
 
+bool FEzAbilityContext::CanExecute(EExecutePolicy Policy) const
+{
+	switch (Policy) {
+	case EExecutePolicy::ClientOnly:		return IsLocallyControlled();
+	case EExecutePolicy::ServerOnly:		return IsNetAuthority();
+	case EExecutePolicy::ClientAndServer:	return true;
+	}
+	return false;
+}
+
 void FEzAbilityContext::Reset()
 {
 	Instigator = nullptr;
@@ -833,30 +843,34 @@ EAbilityRunStatus FEzAbilityContext::StartTemporaryEvaluatorsAndGlobalTasks(cons
 	for (int32 EvalIndex = CurrentEzAbility->EvaluatorsBegin; EvalIndex < (CurrentEzAbility->EvaluatorsBegin + CurrentEzAbility->EvaluatorsNum); EvalIndex++)
 	{
 		const FEzAbilityEvaluator& Eval = CurrentEzAbility->Nodes[EvalIndex].Get<const FEzAbilityEvaluator>();
-		FEzAbilityDataView EvalInstanceView = GetDataViewOrTemporary(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
-		bool bWasCreated = false;
-		if (!EvalInstanceView.IsValid())
+
+		if(CanExecute(Eval.Policy))
 		{
-			EvalInstanceView = AddTemporaryInstance(CurrentFrame, FEzAbilityIndex16(EvalIndex), Eval.InstanceDataHandle, CurrentFrame.Ability->DefaultInstanceData.GetStruct(Eval.InstanceTemplateIndex.Get()));
-			check(EvalInstanceView.IsValid());
-			bWasCreated = true;
-		}
+			FEzAbilityDataView EvalInstanceView = GetDataViewOrTemporary(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
+			bool bWasCreated = false;
+			if (!EvalInstanceView.IsValid())
+			{
+				EvalInstanceView = AddTemporaryInstance(CurrentFrame, FEzAbilityIndex16(EvalIndex), Eval.InstanceDataHandle, CurrentFrame.Ability->DefaultInstanceData.GetStruct(Eval.InstanceTemplateIndex.Get()));
+				check(EvalInstanceView.IsValid());
+				bWasCreated = true;
+			}
 		
-		FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
-		// Copy bound properties.
-		if (Eval.BindingsBatch.IsValid())
-		{
-			CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
-		}
+			FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
+			// Copy bound properties.
+			if (Eval.BindingsBatch.IsValid())
+			{
+				CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
+			}
 
-		if (bWasCreated)
-		{
-			EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Eval.Name.ToString());
+			if (bWasCreated)
 			{
-				QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStart);
-				Eval.Start(*this);
+				EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Eval.Name.ToString());
+				{
+					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStart);
+					Eval.Start(*this);
 
-				EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnAbilityStarted);
+					EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnAbilityStarted);
+				}
 			}
 		}
 	}
@@ -875,35 +889,38 @@ EAbilityRunStatus FEzAbilityContext::StartTemporaryEvaluatorsAndGlobalTasks(cons
 			continue;
 		}
 
-		FEzAbilityDataView TaskDataView = GetDataViewOrTemporary(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
-		bool bWasCreated = false;
-		if (!TaskDataView.IsValid())
+		if(CanExecute(Task.Policy))
 		{
-			TaskDataView = AddTemporaryInstance(CurrentFrame, FEzAbilityIndex16(TaskIndex), Task.InstanceDataHandle, CurrentFrame.Ability->DefaultInstanceData.GetStruct(Task.InstanceTemplateIndex.Get()));
-			check(TaskDataView.IsValid())
-			bWasCreated = true;
-		}
+			FEzAbilityDataView TaskDataView = GetDataViewOrTemporary(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
+			bool bWasCreated = false;
+			if (!TaskDataView.IsValid())
+			{
+				TaskDataView = AddTemporaryInstance(CurrentFrame, FEzAbilityIndex16(TaskIndex), Task.InstanceDataHandle, CurrentFrame.Ability->DefaultInstanceData.GetStruct(Task.InstanceTemplateIndex.Get()));
+				check(TaskDataView.IsValid())
+				bWasCreated = true;
+			}
 
-		FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskDataView);
+			FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskDataView);
 
-		// Copy bound properties.
-		if (Task.BindingsBatch.IsValid())
-		{
-			CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskDataView, Task.BindingsBatch);
-		}
+			// Copy bound properties.
+			if (Task.BindingsBatch.IsValid())
+			{
+				CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskDataView, Task.BindingsBatch);
+			}
 
-		EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Task.Name.ToString());
-		if (bWasCreated)
-		{
-			QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_TreeStart);
-			const EAbilityRunStatus TaskStatus = Task.EnterState(*this, Transition);
+			EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Task.Name.ToString());
+			if (bWasCreated)
+			{
+				QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_TreeStart);
+				const EAbilityRunStatus TaskStatus = Task.EnterState(*this, Transition);
 
-			EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskDataView, EEzAbilityTraceEventType::OnEntered, TaskStatus);
+				EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskDataView, EEzAbilityTraceEventType::OnEntered, TaskStatus);
 
-			if (TaskStatus != EAbilityRunStatus::Running)
-			{
-				Result = TaskStatus;
-				break;
+				if (TaskStatus != EAbilityRunStatus::Running)
+				{
+					Result = TaskStatus;
+					break;
+				}
 			}
 		}
 	}
@@ -947,21 +964,27 @@ void FEzAbilityContext::StopTemporaryEvaluatorsAndGlobalTasks(TArrayView<FEzAbil
 			FConstStructView NodeView = TempFrame.Ability->Nodes[TempInstance.OwnerNodeIndex.Get()];
 			if (const FEzAbilityTask* Task = NodeView.GetPtr<const FEzAbilityTask>())
 			{
-				EZ_ABILITY_LOG(Verbose, TEXT("  Stop: '%s'"), *Task->Name.ToString());
+				if(CanExecute(Task->Policy))
 				{
-					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_Stop);
-					Task->ExitState(*this, Transition);
+					EZ_ABILITY_LOG(Verbose, TEXT("  Stop: '%s'"), *Task->Name.ToString());
+					{
+						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_Stop);
+						Task->ExitState(*this, Transition);
+					}
+					EZ_ABILITY_TRACE_TASK_EVENT(TempInstance.OwnerNodeIndex.Get(), NodeInstanceView, EEzAbilityTraceEventType::OnExited, Transition.CurrentRunStatus);
 				}
-				EZ_ABILITY_TRACE_TASK_EVENT(TempInstance.OwnerNodeIndex.Get(), NodeInstanceView, EEzAbilityTraceEventType::OnExited, Transition.CurrentRunStatus);
 			}
 			else if (const FEzAbilityEvaluator* Eval = NodeView.GetPtr<const FEzAbilityEvaluator>())
 			{
-				EZ_ABILITY_LOG(Verbose, TEXT("  Stop: '%s'"), *Eval->Name.ToString());
+				if(CanExecute(Eval->Policy))
 				{
-					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_Stop);
-					Eval->Stop(*this);
+					EZ_ABILITY_LOG(Verbose, TEXT("  Stop: '%s'"), *Eval->Name.ToString());
+					{
+						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_Stop);
+						Eval->Stop(*this);
 
-					EZ_ABILITY_TRACE_EVALUATOR_EVENT(TempInstance.OwnerNodeIndex.Get(), NodeInstanceView, EEzAbilityTraceEventType::OnAbilityStopped);
+						EZ_ABILITY_TRACE_EVALUATOR_EVENT(TempInstance.OwnerNodeIndex.Get(), NodeInstanceView, EEzAbilityTraceEventType::OnAbilityStopped);
+					}
 				}
 			}
 		}
@@ -1075,59 +1098,64 @@ EAbilityRunStatus FEzAbilityContext::EnterState(FEzAbilityTransitionResult& Tran
 			for (int32 TaskIndex = State.TasksBegin; TaskIndex < (State.TasksBegin + State.TasksNum); TaskIndex++)
 			{
 				const FEzAbilityTask& Task = NextFrame.Ability->Nodes[TaskIndex].Get<const FEzAbilityTask>();
-				const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
-
-				FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
-
-				// Copy bound properties.
-				if (Task.BindingsBatch.IsValid())
-				{
-					CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
-				}
 
-				// Ignore disabled task
-				if (Task.bTaskEnabled == false)
+				if(CanExecute(Task.Policy))
 				{
-					EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'EnterState' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
-					continue;
-				}
+					const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
 
-				const bool bShouldCallStateChange = CurrentTransition.ChangeType == EEzAbilityStateChangeType::Changed
-													|| (CurrentTransition.ChangeType == EEzAbilityStateChangeType::Sustained && Task.bShouldStateChangeOnReselect);
+					FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
 
-				if (bIsEnteringState && bShouldCallStateChange)
-				{
-					EZ_ABILITY_LOG(Verbose, TEXT("%*s  Task '%s'"), Index*UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
+					// Copy bound properties.
+					if (Task.BindingsBatch.IsValid())
+					{
+						CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
+					}
 
-					EAbilityRunStatus Status = EAbilityRunStatus::Unset;
+					// Ignore disabled task
+					if (Task.bTaskEnabled == false)
 					{
-						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_EnterState);
-						CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_Task_EnterState);
-					
-						Status = Task.EnterState(*this, CurrentTransition);
+						EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'EnterState' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
+						continue;
 					}
 
-					EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView, EEzAbilityTraceEventType::OnEntered, Status);
+					const bool bShouldCallStateChange = CurrentTransition.ChangeType == EEzAbilityStateChangeType::Changed
+														|| (CurrentTransition.ChangeType == EEzAbilityStateChangeType::Sustained && Task.bShouldStateChangeOnReselect);
 
-					if (Status != EAbilityRunStatus::Running)
+					if (bIsEnteringState && bShouldCallStateChange)
 					{
-						// Store the first state that completed, will be used to decide where to trigger transitions.
-						if (!Exec.CompletedStateHandle.IsValid())
+						EZ_ABILITY_LOG(Verbose, TEXT("%*s  Task '%s'"), Index*UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
+
+						EAbilityRunStatus Status = EAbilityRunStatus::Unset;
 						{
-							Exec.CompletedFrameIndex = FEzAbilityIndex16(FrameIndex);
-							Exec.CompletedStateHandle = CurrentHandle;
+							QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_EnterState);
+							CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_Task_EnterState);
+						
+							Status = Task.EnterState(*this, CurrentTransition);
+						}
+
+						EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView, EEzAbilityTraceEventType::OnEntered, Status);
+
+						if (Status != EAbilityRunStatus::Running)
+						{
+							// Store the first state that completed, will be used to decide where to trigger transitions.
+							if (!Exec.CompletedStateHandle.IsValid())
+							{
+								Exec.CompletedFrameIndex = FEzAbilityIndex16(FrameIndex);
+								Exec.CompletedStateHandle = CurrentHandle;
+							}
+							Result = Status;
+						}
+						
+						if (Status == EAbilityRunStatus::Failed)
+						{
+							// Store how far in the enter state we got. This will be used to match the StateCompleted() and ExitState() calls.
+							Exec.EnterStateFailedFrameIndex = FEzAbilityIndex16(FrameIndex); 
+							Exec.EnterStateFailedTaskIndex = FEzAbilityIndex16(TaskIndex);
+							break;
 						}
-						Result = Status;
-					}
-					
-					if (Status == EAbilityRunStatus::Failed)
-					{
-						// Store how far in the enter state we got. This will be used to match the StateCompleted() and ExitState() calls.
-						Exec.EnterStateFailedFrameIndex = FEzAbilityIndex16(FrameIndex); 
-						Exec.EnterStateFailedTaskIndex = FEzAbilityIndex16(TaskIndex);
-						break;
 					}
 				}
+				
 			}
 
 			if (bIsEnteringState)
@@ -1405,21 +1433,25 @@ EAbilityRunStatus FEzAbilityContext::TickEvaluatorsAndGlobalTasks(const float De
 			for (int32 EvalIndex = CurrentEzAbility->EvaluatorsBegin; EvalIndex < (CurrentEzAbility->EvaluatorsBegin + CurrentEzAbility->EvaluatorsNum); EvalIndex++)
 			{
 				const FEzAbilityEvaluator& Eval = CurrentEzAbility->Nodes[EvalIndex].Get<const FEzAbilityEvaluator>();
-				const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
-				FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
 
-				// Copy bound properties.
-				if (Eval.BindingsBatch.IsValid())
+				if(CanExecute(Eval.Policy))
 				{
-					CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
-				}
+					const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
+					FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
+
+					// Copy bound properties.
+					if (Eval.BindingsBatch.IsValid())
+					{
+						CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
+					}
 				
-				EZ_ABILITY_LOG(VeryVerbose, TEXT("  Tick: '%s'"), *Eval.Name.ToString());
-				{
-					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_Tick);
-					Eval.Tick(*this, DeltaTime);
+					EZ_ABILITY_LOG(VeryVerbose, TEXT("  Tick: '%s'"), *Eval.Name.ToString());
+					{
+						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_Tick);
+						Eval.Tick(*this, DeltaTime);
 				
-					EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnTicked);
+						EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnTicked);
+					}
 				}
 			}
 
@@ -1432,52 +1464,56 @@ EAbilityRunStatus FEzAbilityContext::TickEvaluatorsAndGlobalTasks(const float De
 				for (int32 TaskIndex = CurrentEzAbility->GlobalTasksBegin; TaskIndex < (CurrentEzAbility->GlobalTasksBegin + CurrentEzAbility->GlobalTasksNum); TaskIndex++)
 				{
 					const FEzAbilityTask& Task = CurrentEzAbility->Nodes[TaskIndex].Get<const FEzAbilityTask>();
-					const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
-					FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
 
-					// Ignore disabled task
-					if (Task.bTaskEnabled == false)
+					if(CanExecute(Task.Policy))
 					{
-						EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'Tick' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
-						continue;
-					}
+						const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
+						FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
 
-					 const bool bNeedsTick = bShouldTickTasks && (Task.bShouldCallTick || (bHasEvents && Task.bShouldCallTickOnlyOnEvents));
-					EZ_ABILITY_LOG(VeryVerbose, TEXT("  Tick: '%s' %s"), *Task.Name.ToString(), !bNeedsTick ? TEXT("[not ticked]") : TEXT(""));
-					if (!bNeedsTick)
-					{
-						continue;
-					}
+						// Ignore disabled task
+						if (Task.bTaskEnabled == false)
+						{
+							EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'Tick' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
+							continue;
+						}
+
+						const bool bNeedsTick = bShouldTickTasks && (Task.bShouldCallTick || (bHasEvents && Task.bShouldCallTickOnlyOnEvents));
+						EZ_ABILITY_LOG(VeryVerbose, TEXT("  Tick: '%s' %s"), *Task.Name.ToString(), !bNeedsTick ? TEXT("[not ticked]") : TEXT(""));
+						if (!bNeedsTick)
+						{
+							continue;
+						}
 					
-					// Copy bound properties.
-					// Only copy properties when the task is actually ticked, and copy properties at tick is requested.
-					if (Task.BindingsBatch.IsValid() && Task.bShouldCopyBoundPropertiesOnTick)
-					{
-						CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
-					}
+						// Copy bound properties.
+						// Only copy properties when the task is actually ticked, and copy properties at tick is requested.
+						if (Task.BindingsBatch.IsValid() && Task.bShouldCopyBoundPropertiesOnTick)
+						{
+							CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
+						}
 					
-					//EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskDataView, EEzAbilityTraceEventType::OnTickingTask, EAbilityRunStatus::Running);
-					EAbilityRunStatus TaskResult = EAbilityRunStatus::Unset;
-					{
-						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_Tick);
-						CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_Task_Tick);
+						//EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskDataView, EEzAbilityTraceEventType::OnTickingTask, EAbilityRunStatus::Running);
+						EAbilityRunStatus TaskResult = EAbilityRunStatus::Unset;
+						{
+							QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_Tick);
+							CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_Task_Tick);
 					
-						TaskResult = Task.Tick(*this, DeltaTime);
-					}
+							TaskResult = Task.Tick(*this, DeltaTime);
+						}
 
-					EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView,
-						TaskResult != EAbilityRunStatus::Running ? EEzAbilityTraceEventType::OnTaskCompleted : EEzAbilityTraceEventType::OnTicked,
-						TaskResult);
+						EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView,
+							TaskResult != EAbilityRunStatus::Running ? EEzAbilityTraceEventType::OnTaskCompleted : EEzAbilityTraceEventType::OnTicked,
+							TaskResult);
 					
-					// If a global task succeeds or fails, it will stop the whole tree.
-					if (TaskResult != EAbilityRunStatus::Running)
-					{
-						Result = TaskResult;
-					}
+						// If a global task succeeds or fails, it will stop the whole tree.
+						if (TaskResult != EAbilityRunStatus::Running)
+						{
+							Result = TaskResult;
+						}
 						
-					if (TaskResult == EAbilityRunStatus::Failed)
-					{
-						bShouldTickTasks = false;
+						if (TaskResult == EAbilityRunStatus::Failed)
+						{
+							bShouldTickTasks = false;
+						}
 					}
 				}
 			}
@@ -1514,21 +1550,25 @@ EAbilityRunStatus FEzAbilityContext::StartEvaluatorsAndGlobalTasks(FEzAbilityInd
         	for (int32 EvalIndex = CurrentAbility->EvaluatorsBegin; EvalIndex < (CurrentAbility->EvaluatorsBegin + CurrentAbility->EvaluatorsNum); EvalIndex++)
         	{
         		const FEzAbilityEvaluator& Eval = CurrentAbility->Nodes[EvalIndex].Get<const FEzAbilityEvaluator>();
-        		const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
-        		FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
-        
-        		// Copy bound properties.
-        		if (Eval.BindingsBatch.IsValid())
+
+        		if(CanExecute(Eval.Policy))
         		{
-        			CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
-        		}
+        			const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
+        			FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
+        
+        			// Copy bound properties.
+        			if (Eval.BindingsBatch.IsValid())
+        			{
+        				CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
+        			}
         		
-        		EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Eval.Name.ToString());
-        		{
-        			QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStart);
-        			Eval.Start(*this);
+        			EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Eval.Name.ToString());
+        			{
+        				QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStart);
+        				Eval.Start(*this);
            
-        			EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnAbilityStarted);
+        				EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnAbilityStarted);
+        			}
         		}
         	}
         
@@ -1539,36 +1579,40 @@ EAbilityRunStatus FEzAbilityContext::StartEvaluatorsAndGlobalTasks(FEzAbilityInd
 			for (int32 TaskIndex = CurrentAbility->GlobalTasksBegin; TaskIndex < (CurrentAbility->GlobalTasksBegin + CurrentAbility->GlobalTasksNum); TaskIndex++)
 			{
 				const FEzAbilityTask& Task =  CurrentAbility->Nodes[TaskIndex].Get<const FEzAbilityTask>();
-				const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
-				FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
-        
-				// Copy bound properties.
-				if (Task.BindingsBatch.IsValid())
-				{
-					CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
-				}
-        
-				// Ignore disabled task
-				if (Task.bTaskEnabled == false)
+
+				if(CanExecute(Task.Policy))
 				{
-					EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'EnterState' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
-					continue;
-				}
+					const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
+					FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
         
-				EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Task.Name.ToString());
-				{
-					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_TreeStart);
-					const EAbilityRunStatus TaskStatus = Task.EnterState(*this, Transition); 
+					// Copy bound properties.
+					if (Task.BindingsBatch.IsValid())
+					{
+						CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
+					}
         
-					EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView, EEzAbilityTraceEventType::OnEntered, TaskStatus);
+					// Ignore disabled task
+					if (Task.bTaskEnabled == false)
+					{
+						EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'EnterState' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
+						continue;
+					}
         
-					if (TaskStatus != EAbilityRunStatus::Running)
+					EZ_ABILITY_LOG(Verbose, TEXT("  Start: '%s'"), *Task.Name.ToString());
 					{
-						OutLastInitializedTaskIndex = FEzAbilityIndex16(TaskIndex);
-						Result = TaskStatus;
-						break;
-        			}
-        		}
+						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_TreeStart);
+						const EAbilityRunStatus TaskStatus = Task.EnterState(*this, Transition); 
+        
+						EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView, EEzAbilityTraceEventType::OnEntered, TaskStatus);
+        
+						if (TaskStatus != EAbilityRunStatus::Running)
+						{
+							OutLastInitializedTaskIndex = FEzAbilityIndex16(TaskIndex);
+							Result = TaskStatus;
+							break;
+						}
+					}
+				}
         	}
         }
 	}
@@ -1667,15 +1711,19 @@ void FEzAbilityContext::StopEvaluatorsAndGlobalTasks(const EAbilityRunStatus Com
 			for (int32 EvalIndex = (CurrentEzAbility->EvaluatorsBegin + CurrentEzAbility->EvaluatorsNum) - 1; EvalIndex >= CurrentEzAbility->EvaluatorsBegin; EvalIndex--)
 			{
 				const FEzAbilityEvaluator& Eval = CurrentEzAbility->Nodes[EvalIndex].Get<const FEzAbilityEvaluator>();
-				const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
-				FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
 
-				EZ_ABILITY_LOG(Verbose, TEXT("  Stop: '%s'"), *Eval.Name.ToString());
+				if(CanExecute(Eval.Policy))
 				{
-					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStop);
-					Eval.Stop(*this);
+					const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
+					FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
+
+					EZ_ABILITY_LOG(Verbose, TEXT("  Stop: '%s'"), *Eval.Name.ToString());
+					{
+						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStop);
+						Eval.Stop(*this);
 
-					EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnAbilityStopped);
+						EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnAbilityStopped);
+					}
 				}
 			}
 		}
@@ -2894,58 +2942,62 @@ EAbilityRunStatus FEzAbilityContext::TickTasks(const float DeltaTime)
 			for (int32 TaskIndex = State.TasksBegin; TaskIndex < (State.TasksBegin + State.TasksNum); TaskIndex++)
 			{
 				const FEzAbilityTask& Task = CurrentEzAbility->Nodes[TaskIndex].Get<const FEzAbilityTask>();
-				const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
-				FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
 
-				// Ignore disabled task
-				if (Task.bTaskEnabled == false)
+				if(CanExecute(Task.Policy))
 				{
-					EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'Tick' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
-					continue;
-				}
+					const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
+					FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
 
-				const bool bNeedsTick = bShouldTickTasks && (Task.bShouldCallTick || (bHasEvents && Task.bShouldCallTickOnlyOnEvents));
-				EZ_ABILITY_LOG(VeryVerbose, TEXT("%*s  Tick: '%s' %s"), Index*UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString(), !bNeedsTick ? TEXT("[not ticked]") : TEXT(""));
-				if (!bNeedsTick)
-				{
-					continue;
-				}
-				
-				// Copy bound properties.
-				// Only copy properties when the task is actually ticked, and copy properties at tick is requested.
-				if (Task.BindingsBatch.IsValid() && Task.bShouldCopyBoundPropertiesOnTick)
-				{
-					CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
-				}
+					// Ignore disabled task
+					if (Task.bTaskEnabled == false)
+					{
+						EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'Tick' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
+						continue;
+					}
 
-				//EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskDataView, EEzAbilityTraceEventType::OnTickingTask, EAbilityRunStatus::Running);
-				EAbilityRunStatus TaskResult = EAbilityRunStatus::Unset;
-				{
-					QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_Tick);
-					CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_Task_Tick);
+					const bool bNeedsTick = bShouldTickTasks && (Task.bShouldCallTick || (bHasEvents && Task.bShouldCallTickOnlyOnEvents));
+					EZ_ABILITY_LOG(VeryVerbose, TEXT("%*s  Tick: '%s' %s"), Index*UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString(), !bNeedsTick ? TEXT("[not ticked]") : TEXT(""));
+					if (!bNeedsTick)
+					{
+						continue;
+					}
+					
+					// Copy bound properties.
+					// Only copy properties when the task is actually ticked, and copy properties at tick is requested.
+					if (Task.BindingsBatch.IsValid() && Task.bShouldCopyBoundPropertiesOnTick)
+					{
+						CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
+					}
 
-					TaskResult = Task.Tick(*this, DeltaTime);
-				}
+					//EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskDataView, EEzAbilityTraceEventType::OnTickingTask, EAbilityRunStatus::Running);
+					EAbilityRunStatus TaskResult = EAbilityRunStatus::Unset;
+					{
+						QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_Tick);
+						CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_Task_Tick);
 
-				EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView,
-					TaskResult != EAbilityRunStatus::Running ? EEzAbilityTraceEventType::OnTaskCompleted : EEzAbilityTraceEventType::OnTicked,
-					TaskResult);
-				
-				// TODO: Add more control over which states can control the failed/succeeded result.
-				if (TaskResult != EAbilityRunStatus::Running)
-				{
-					// Store the first state that completed, will be used to decide where to trigger transitions.
-					if (!Exec.CompletedStateHandle.IsValid())
+						TaskResult = Task.Tick(*this, DeltaTime);
+					}
+
+					EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView,
+						TaskResult != EAbilityRunStatus::Running ? EEzAbilityTraceEventType::OnTaskCompleted : EEzAbilityTraceEventType::OnTicked,
+						TaskResult);
+					
+					// TODO: Add more control over which states can control the failed/succeeded result.
+					if (TaskResult != EAbilityRunStatus::Running)
 					{
-						Exec.CompletedFrameIndex = FEzAbilityIndex16(FrameIndex);
-						Exec.CompletedStateHandle = CurrentHandle;
+						// Store the first state that completed, will be used to decide where to trigger transitions.
+						if (!Exec.CompletedStateHandle.IsValid())
+						{
+							Exec.CompletedFrameIndex = FEzAbilityIndex16(FrameIndex);
+							Exec.CompletedStateHandle = CurrentHandle;
+						}
+						Result = TaskResult;
+					}
+					
+					if (TaskResult == EAbilityRunStatus::Failed)
+					{
+						bShouldTickTasks = false;
 					}
-					Result = TaskResult;
-				}
-				
-				if (TaskResult == EAbilityRunStatus::Failed)
-				{
-					bShouldTickTasks = false;
 				}
 			}
 			NumTotalTasks += State.TasksNum;

+ 2 - 1
Ability/Plugins/EzAbility/Source/EzAbility/Public/EzAbilityContext.h

@@ -92,7 +92,8 @@ public:
 	const UEzAbility*	GetAbility() const { return Ability; }
 	
 protected:
-	
+
+	bool CanExecute(EExecutePolicy Policy) const;
 	void Reset();
 	FString GetInstanceDescription() const;
 	void UpdateInstanceData(TConstArrayView<FEzAbilityExecutionFrame> CurrentActiveFrames, TArrayView<FEzAbilityExecutionFrame> NextActiveFrames);

+ 3 - 0
Ability/Plugins/EzAbility/Source/EzAbility/Public/EzAbilityNodeBase.h

@@ -79,5 +79,8 @@ PRAGMA_ENABLE_DEPRECATION_WARNINGS
 	
 	UPROPERTY()
 	FEzAbilityDataHandle	InstanceDataHandle		= FEzAbilityDataHandle::Invalid;
+
+	UPROPERTY(EditAnywhere, Category = Default)
+	EExecutePolicy	Policy = EExecutePolicy::ClientAndServer;
 };
 

+ 0 - 7
Ability/Plugins/EzAbility/Source/EzAbility/Public/Task/EzAbilityTask.h

@@ -80,11 +80,4 @@ struct EZABILITY_API FEzAbilityTask : public FEzAbilityNodeBase
 	/** True if the node is Enabled (i.e. not explicitly disabled in the asset). */
 	UPROPERTY()
 	uint8 bTaskEnabled : 1;
-
-	
-	UPROPERTY(EditAnywhere, Category = Task)
-	EExecutePolicy	Policy = EExecutePolicy::ClientAndServer;
-
-	// If set to false, task not call, default true
-	uint8 bShouldExecuteTask : 1;
 };

+ 2 - 0
Ability/Plugins/EzAbility/Source/EzAbilityEditor/Private/EzAbilityTimelinePanel.cpp

@@ -184,3 +184,5 @@ TSharedRef<SWidget> SEzAbilityTimelinePanel::BuildTimelineControls()
 				]
 		];
 }
+
+#undef LOCTEXT_NAMESPACE

+ 2 - 2
Ability/Source/Ability.Target.cs

@@ -8,8 +8,8 @@ public class AbilityTarget : TargetRules
 	public AbilityTarget(TargetInfo Target) : base(Target)
 	{
 		Type = TargetType.Game;
-		DefaultBuildSettings = BuildSettingsVersion.V5;
-		IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_4;
+		DefaultBuildSettings = BuildSettingsVersion.Latest;
+		IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
 		ExtraModuleNames.Add("Ability");
 	}
 }

+ 2 - 2
Ability/Source/AbilityEditor.Target.cs

@@ -8,8 +8,8 @@ public class AbilityEditorTarget : TargetRules
 	public AbilityEditorTarget(TargetInfo Target) : base(Target)
 	{
 		Type = TargetType.Editor;
-		DefaultBuildSettings = BuildSettingsVersion.V5;
-		IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_4;
+		DefaultBuildSettings = BuildSettingsVersion.Latest;
+		IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
 		ExtraModuleNames.Add("Ability");
 	}
 }