An efficient way to assign IDs:
- First declare an empty structure, and then inherit from a similar
FAIBasicCounter
template structure, this structure may need to meet some conditions:
- Implement the accumulation function:
Type GetNextAvailableID() { return NextAvailableID ++;}
- Judgment of the upper limit, the method of judging when the upper limit is reached
- Implementation function to force an ID to be assigned
- variable to store the ID
- If you don’t want to support generics, you can define a structure to use according to the above rules, and the next thing to do is to add a member variable of the structure and a static ID variable to the required class to mark the current newly allocated ID , the IDs assigned in the future can be accumulated through this ID
- This method was adopted in
FAISightQuery
LiheFPerceptionListenerID
FAISenseID
FPerceptionListenerID
The idea of ID generation in (FAISenseID
similarly)template<typename TCounterType> struct FAIBasicCounter { typedef TCounterType Type; protected: Type NextAvailableID; public: FAIBasicCounter() : NextAvailableID(Type(0)) {} Type GetNextAvailableID() { return NextAvailableID++; } uint32 GetSize() const { return uint32(NextAvailableID); } void OnIndexForced(Type ForcedIndex) { NextAvailableID = FMath::Max<Type>(ForcedIndex + 1, NextAvailableID); } };
NextAvailableID
Identifies the next effective ID value to be generated
GetNextAvailableID
Function ID generation accumulative function increments one bit each time
OnIndexForced
Function is forced to append to a current index ID, this ID must be guaranteed to be greater than the already identified oneNextAvailableID
, otherwise the original identification variable will be usedstruct AIMODULE_API FPerceptionListenerCounter : FAIBasicCounter<uint32>{}; typedef FAIGenericID<FPerceptionListenerCounter> FPerceptionListenerID;
FAIGenericID
It is a template class, and the core member variables maintained in it arestatic AIMoudle_API TCounter Counter
to identify the generated quantity; theconst typename TCounter::Type Index
currently used ID, which is a constant, indicates that the function in the
ID that is currently instantiated uses the function in the ID but relies on this static member variable to accumulate The generated method is called in the perception system , which means that if the currently incoming Listener is new data, a new ListenID will be generated and stored in the Listener data structure of the perception system
FAIGenericID
GetNextID
FAIBasicCounter
GetNextAvailableID
FAIGenericID
Counter
const FPerceptionListenerID NewListenerId = FPerceptionListenerID::GetNextID();
UpdateListener
FAISenseID
What is the difference between ID allocation andFPerceptionListenerID
ID allocation?
They are all the same in essence, the only inconsistency is that the logical meaning expressed in the usage is different, the former is to assign indexes to the type and quantity of Sense, while the latter is to the holder of the perception component itselfEfficient way to write a function pointer
const TFunction<void(const FAISightQuery&)>& OnRemoveFunc auto RemoveQuery = [&ListenerId, &OnRemoveFunc](TArray<FAISightQuery&> SightQueries, const int32 QueryIndex)->EReverseForEachResult { ... OnRemoveFunc(SightQuery); ... }
UAISense_Sight::RemoveAllQueriesByListener
This function nestedly calls multiple layers of function pointers. First, the incoming one isOnRemoveFunc
passed to the Lambda function as a captureRemoveQuery
, and then it is called in the function. In theRemoveQuery
template functionReverseForEach
,ReverseForEach
theRemoveQuery
function is called in a loop, which is not as a whole. It is too suitable for frequent use of similar writing, because the readability is not very good. But in some basic general-purpose functions, it is particularly outstanding. For example,TArray
a similar function pointer call is used inDiscover a
FRotator
valid method of declaring and assigning
FRotator ViewRotation(ForceInitToZero)
In the same way, FVector supports this operation.ForceInitToZero
It is an enumeration definition member and the other isForceInitToZero
Create a delegated task with prerequisites
source code
FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateUObject( const_cast<UAIPerceptionComponent* (this),&UAIPerceptionComponent::RemoveDeadData), >>>GET_STATID(STAT_FSimpleDelegateGraphTask_RequestingRemovalOfDeadPerceptionData), NULL, ENamedThreads::GameThread);
Create a delegate to delete invalid perception data in a timely manner when invalid data is found in the perception data. This delegate is called in the game thread. This delegate uses the
Stat mechanism for performance statistical analysis. The specific implementation is as follows:DECLARE_CYCLE_STAT(TEXT("Requesting UAIPerceptionComponent::RemoveDeadData call from within a const function"), STAT_FSimpleDelegateGraphTask_RequestingRemovalOfDeadPerceptionData, STATGROUP_TaskGraphTasks);
Declare a Stat, which belongs to
STATGROUP_TaskGraphTasks
the group group, and the StatId of the identifierGET_STATID
can be obtained through the macroSTAT_FSimpleDelegateGraphTask_RequestingRemovalOfDeadPerceptionData
#define DECLARE_CYCLE_STAT(CounterName,StatId,GroupId) \ DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, >>>FPlatformMemory::MCR_Invalid); \ static DEFINE_STAT(StatId)
DECLARE_STAT is a structure declaration macro, which contains the acquisition functions of StatName, StatType, IsClearEveryFrame, etc. The
first parameter passed in will be returned as a description text in the functionCounterName
declared by the macro, and the second parameter passed in will be used as a string in GetStatName Return, also used as a suffix name in the construction structure. It is a globally unique ID. The last few parameters are used to set the data type of Stat, the state label it has, and the analysis memory area, etc.GetDescription
StatId
GroupId
DECLARE_STATS_GROUP(TEXT("AI"),STATGROUP_AI, STATCAT_Advanced)
The statement is in the Stats2.h header file. The source code comment says that not all of these GroupIDs must be defined in this file. They can be defined in their own Cpp files as needed, but they must be globally unique. Push a more detailed article
: StatGet the function in reflection and call
const UFunction* Function = Object.GetClass()->FindFunctionByName(FuncName); return Function != nullptr;
UE AIModule source code interpretation for reference (1)
Guess you like
Origin blog.csdn.net/u011047958/article/details/125631046
Ranking