// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_4 #include "CoreMinimal.h" #endif #include "UObject/ObjectMacros.h" #include "Templates/SubclassOf.h" #include "UObject/WeakObjectPtr.h" #include "Misc/CoreMisc.h" #include "Misc/CoreDelegates.h" #if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_4 #include "NavFilters/NavigationQueryFilter.h" #endif #include "AI/Navigation/NavigationTypes.h" #include "AI/Navigation/NavigationDirtyElement.h" #include "AI/Navigation/NavigationInvokerPriority.h" #include "NavigationSystemTypes.h" #include "NavigationData.h" #include "AI/NavigationSystemBase.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "NavigationOctree.h" #include "AI/NavigationSystemConfig.h" #include "NavigationOctreeController.h" #include "NavigationDirtyAreasController.h" #include "Math/MovingWindowAverageFast.h" #include "AI/Navigation/NavigationBounds.h" #include "Containers/ContainerAllocationPolicies.h" #include "NavigationSystem.generated.h" class AController; class ANavMeshBoundsVolume; class AWorldSettings; class FEdMode; class FNavDataGenerator; class INavigationInvokerInterface; class INavLinkCustomInterface; class INavRelevantInterface; class UCrowdManagerBase; class UNavArea; class UNavigationPath; class UNavigationObjectRepository; class UNavigationSystemModuleConfig; struct FDebugText; struct FNavigationRelevantData; struct FNavigationOctreeElement; struct FNavigationElement; #if !UE_BUILD_SHIPPING #define ALLOW_TIME_SLICE_DEBUG 1 #else #define ALLOW_TIME_SLICE_DEBUG 0 #endif /** delegate to let interested parties know that new nav area class has been registered */ DECLARE_MULTICAST_DELEGATE_OneParam(FOnNavAreaChanged, const UClass* /*AreaClass*/); /** Delegate to let interested parties know that Nav Data has been registered */ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNavDataGenericEvent, ANavigationData*, NavData); DECLARE_MULTICAST_DELEGATE(FOnNavigationInitDone); namespace NavigationDebugDrawing { extern const NAVIGATIONSYSTEM_API float PathLineThickness; extern const NAVIGATIONSYSTEM_API FVector PathOffset; extern const NAVIGATIONSYSTEM_API FVector PathNodeBoxExtent; } namespace FNavigationSystem { /** * Used to construct an ANavigationData instance for specified navigation data agent */ typedef ANavigationData* (*FNavigationDataInstanceCreator)(UWorld*, const FNavDataConfig&); struct FCustomLinkOwnerInfo { FWeakObjectPtr LinkOwner; INavLinkCustomInterface* LinkInterface; FCustomLinkOwnerInfo() : LinkInterface(nullptr) {} NAVIGATIONSYSTEM_API FCustomLinkOwnerInfo(INavLinkCustomInterface* Link); bool IsValid() const { return LinkOwner.IsValid(); } }; bool NAVIGATIONSYSTEM_API ShouldLoadNavigationOnClient(ANavigationData& NavData); void NAVIGATIONSYSTEM_API MakeAllComponentsNeverAffectNav(AActor& Actor); #if ALLOW_TIME_SLICE_DEBUG const FName DebugTimeSliceDefaultSectionName = FName(TEXT("DefaultSection")); #endif // ALLOW_TIME_SLICE_DEBUG } struct FNavigationSystemExec: public FSelfRegisteringExec { protected: //~ Begin FExec Interface virtual bool Exec_Runtime(UWorld* Inworld, const TCHAR* Cmd, FOutputDevice& Ar) override; //~ End FExec Interface }; namespace ENavigationBuildLock { enum Type { NoUpdateInEditor = 1 << 1, // editor doesn't allow automatic updates NoUpdateInPIE = 1 << 2, // PIE doesn't allow automatic updates InitialLock = 1 << 3, // initial lock, release manually after levels are ready for rebuild (e.g. streaming) Custom = 1 << 4, }; } // Use this just before a call to TestTimeSliceFinished() to allow the time slice logging to use a debug name for the section of code being timed. #if ALLOW_TIME_SLICE_DEBUG #define MARK_TIMESLICE_SECTION_DEBUG(TIME_SLICER, TIME_SLICE_FNAME) \ static const FName TIME_SLICE_FNAME(TEXT(#TIME_SLICE_FNAME)); \ TIME_SLICER.DebugSetSectionName(TIME_SLICE_FNAME); #else #define MARK_TIMESLICE_SECTION_DEBUG(TIME_SLICER, TIME_SLICE_FNAME) ; #endif class FNavRegenTimeSlicer { public: /** Setup the initial values for a time slice. This can be called on an instance after TestTimeSliceFinished() has returned true and EndTimeSliceAndAdjustDuration() has been called */ NAVIGATIONSYSTEM_API void SetupTimeSlice(double SliceDuration); /** * Starts the time slice, this can be called multiple times as long as EndTimeSliceAndAdjustDuration() is called between each call. * StartTimeSlice should not be called after TestTimeSliceFinished() has returned true */ NAVIGATIONSYSTEM_API void StartTimeSlice(); /** * Useful when multiple sections of code need to be timesliced per frame using the same time slice duration that do not necessarily occur concurrently. * This ends the time sliced code section and adjusts the RemainingDuration based on the time used between calls to StartTimeSlice and the last call to TestTimeSliceFinished. * Note the actual time slice is not tested in this function. Thats done in TestTimeSliceFinished! * This can be called multiple times as long as StartTimeSlice() is called before EndTimeSliceAndAdjustDuration(). * EndTimeSliceAndAdjustDuration can be called after TestTimeSliceFinished() has returned true in this case the RemainingDuration will just be zero */ NAVIGATIONSYSTEM_API void EndTimeSliceAndAdjustDuration(); double GetStartTime() const { return StartTime; } NAVIGATIONSYSTEM_API bool TestTimeSliceFinished() const; //* Returns the cached result of calling TestTimeSliceFinished, false by default */ bool IsTimeSliceFinishedCached() const { return bTimeSliceFinishedCached; } double GetRemainingDuration() const { return RemainingDuration; } double GetRemainingDurationFraction() const { return OriginalDuration > 0. ? RemainingDuration / OriginalDuration : 0.; } #if ALLOW_TIME_SLICE_DEBUG /* * Sets data used for debugging time slices that are taking too long to process. * @param LongTimeSliceFunction function called when a time slice is taking too long to process. * @param LongTimeSliceDuration when a time slice takes longer than this duration LongTimeSliceFunction will be called. */ NAVIGATIONSYSTEM_API void DebugSetLongTimeSliceData(TFunction LongTimeSliceFunction, double LongTimeSliceDuration) const; NAVIGATIONSYSTEM_API void DebugResetLongTimeSliceFunction() const; /** * Sets the debug name for a time sliced section of code. * Do not call this directly use MARK_TIMESLICE_SECTION_DEBUG */ void DebugSetSectionName(FName InDebugSectionName) const { DebugSectionName = InDebugSectionName; } #endif // ALLOW_TIME_SLICE_DEBUG protected: double OriginalDuration = 0.; double RemainingDuration = 0.; double StartTime = 0.; mutable double TimeLastTested = 0.; mutable bool bTimeSliceFinishedCached = false; #if ALLOW_TIME_SLICE_DEBUG mutable TFunction DebugLongTimeSliceFunction; mutable double DebugLongTimeSliceDuration = 0.; mutable FName DebugSectionName = FNavigationSystem::DebugTimeSliceDefaultSectionName; #endif }; #if !UE_BUILD_SHIPPING struct FTileHistoryData { /** Tile coordinates **/ int32 TileX = 0; int32 TileY = 0; /** Accumulated time spent processing the tile (seconds). */ float TileRegenTime = 0.f; /** Time between the tile was requested and when it's finished building (seconds). */ float TileWaitTime = 0.f; /** Frame when tile processing started. */ int64 StartRegenFrame = 0; /** Frame when tile processing ended. */ int64 EndRegenFrame = 0; }; #endif // !UE_BUILD_SHIPPING class FNavRegenTimeSliceManager { public: NAVIGATIONSYSTEM_API FNavRegenTimeSliceManager(); void PushTileRegenTime(double NewTime) { MovingWindowTileRegenTime.PushValue(NewTime); } double GetAverageTileRegenTime() const { return MovingWindowTileRegenTime.GetAverage(); } double GetAverageDeltaTime() const { return MovingWindowDeltaTime.GetAverage(); } NAVIGATIONSYSTEM_API void ResetTileWaitTimeArrays(const TArray>& NavDataSet); NAVIGATIONSYSTEM_API void PushTileWaitTime(const int32 NavDataIndex, const double NewTime); #if !UE_BUILD_SHIPPING NAVIGATIONSYSTEM_API void ResetTileHistoryData(const TArray>& NavDataSet); NAVIGATIONSYSTEM_API void PushTileHistoryData(const int32 NavDataIndex, const FTileHistoryData& TileData); #endif // UE_BUILD_SHIPPING NAVIGATIONSYSTEM_API double GetAverageTileWaitTime(const int32 NavDataIndex) const; NAVIGATIONSYSTEM_API void ResetTileWaitTime(const int32 NavDataIndex); bool DoTimeSlicedUpdate() const { return bDoTimeSlicedUpdate; } NAVIGATIONSYSTEM_API void CalcAverageDeltaTime(uint64 FrameNum); NAVIGATIONSYSTEM_API void CalcTimeSliceDuration(const TArray>& NavDataSet, int32 NumTilesToRegen, const TArray& CurrentTileRegenDurations); NAVIGATIONSYSTEM_API void SetMinTimeSliceDuration(double NewMinTimeSliceDuration); NAVIGATIONSYSTEM_API void SetMaxTimeSliceDuration(double NewMaxTimeSliceDuration); NAVIGATIONSYSTEM_API void SetMaxDesiredTileRegenDuration(float NewMaxDesiredTileRegenDuration); int32 GetNavDataIdx() const { return NavDataIdx; } void SetNavDataIdx(int32 InNavDataIdx) { NavDataIdx = InNavDataIdx; } FNavRegenTimeSlicer& GetTimeSlicer() { return TimeSlicer; } const FNavRegenTimeSlicer& GetTimeSlicer() const { return TimeSlicer; } #if !UE_BUILD_SHIPPING NAVIGATIONSYSTEM_API void LogTileStatistics(const TArray>& NavDataSet) const; #endif // !UE_BUILD_SHIPPING protected: FNavRegenTimeSlicer TimeSlicer; /** Used to calculate the moving window average of the actual time spent inside functions used to regenerate a tile, this is processing time not actual time over multiple frames */ FMovingWindowAverageFast MovingWindowTileRegenTime; /** Used to calculate the actual moving window delta time */ FMovingWindowAverageFast MovingWindowDeltaTime; /** Average tile wait time per NavDataIndex */ TArray> TileWaitTimes; #if !UE_BUILD_SHIPPING /** Tile processing time per NavDataIndex */ TArray> TileHistoryData; double TileHistoryStartTime = 0; #endif // UE_BUILD_SHIPPING /** If there are enough tiles to process this in the Min Time Slice Duration */ double MinTimeSliceDuration; /** The max Desired Time Slice Duration */ double MaxTimeSliceDuration; uint64 FrameNumOld; /** The max real world desired time to Regen all the tiles in PendingDirtyTiles, * Note it could take longer than this, as the time slice is clamped per frame between * MinTimeSliceDuration and MaxTimeSliceDuration. */ float MaxDesiredTileRegenDuration; double TimeLastCall; int32 NavDataIdx; bool bDoTimeSlicedUpdate; }; UCLASS(Within=World, config=Engine, defaultconfig, MinimalAPI) class UNavigationSystemV1 : public UNavigationSystemBase { GENERATED_BODY() friend UNavigationSystemModuleConfig; public: NAVIGATIONSYSTEM_API UNavigationSystemV1(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); virtual ~UNavigationSystemV1() = default; NAVIGATIONSYSTEM_API void GatherDebugLabels(TArray& InOutDebugLabels) const; UPROPERTY(Transient) TObjectPtr MainNavData; /** special navigation data for managing direct paths, not part of NavDataSet! */ UPROPERTY(Transient) TObjectPtr AbstractNavData; protected: /** If not None indicates which of navigation datas and supported agents are * going to be used as the default ones. If navigation agent of this type does * not exist or is not enabled then the first available nav data will be used * as the default one */ UPROPERTY(config, EditAnywhere, BlueprintReadOnly, Category = Navigation) FName DefaultAgentName; UPROPERTY(config, EditAnywhere, BlueprintReadOnly, Category = Navigation) TSoftClassPtr CrowdManagerClass; /** Should navigation system spawn default Navigation Data when there's none and there are navigation bounds present? */ UPROPERTY(config, EditAnywhere, Category=NavigationSystem) uint32 bAutoCreateNavigationData:1; /** If true will try to spawn the navigation data instance in the sublevel with navigation bounds, if false it will spawn in the persistent level */ UPROPERTY(config, EditAnywhere, Category = NavigationSystem) uint32 bSpawnNavDataInNavBoundsLevel:1; /** If false, will not create nav collision when connecting as a client */ UPROPERTY(config, EditAnywhere, Category=NavigationSystem) uint32 bAllowClientSideNavigation:1; /** If true, games should ignore navigation data inside loaded sublevels */ UPROPERTY(config, EditAnywhere, Category = NavigationSystem) uint32 bShouldDiscardSubLevelNavData:1; /** If true, will update navigation even when the game is paused */ UPROPERTY(config, EditAnywhere, Category=NavigationSystem) uint32 bTickWhilePaused:1; /** gets set to true if gathering navigation data (like in navoctree) is required due to the need of navigation generation * Is always true in Editor Mode. In other modes it depends on bRebuildAtRuntime of every required NavigationData class' CDO */ UPROPERTY() uint32 bSupportRebuilding : 1; public: /** if set to true will result navigation system not rebuild navigation until * a call to ReleaseInitialBuildingLock() is called. Does not influence * editor-time generation (i.e. does influence PIE and Game). * Defaults to false.*/ UPROPERTY(config, EditAnywhere, Category=NavigationSystem) uint32 bInitialBuildingLocked:1; /** If set to true (default) navigation will be generated only within special navigation * bounds volumes (like ANavMeshBoundsVolume). Set to false means navigation should be generated * everywhere. */ // @todo removing it from edition since it's currently broken and I'm not sure we want that at all // since I'm not sure we can make it efficient in a generic case //UPROPERTY(config, EditAnywhere, Category=NavigationSystem) uint32 bWholeWorldNavigable:1; /** false by default, if set to true will result in not caring about nav agent height * when trying to match navigation data to passed in nav agent */ UPROPERTY(config, EditAnywhere, Category=NavigationSystem) uint32 bSkipAgentHeightCheckWhenPickingNavData:1; /** Warnings are logged if exporting the navigation collision for an object exceed this triangle count. * Use -1 to disable. */ UPROPERTY(config, EditAnywhere, AdvancedDisplay, Category = NavigationSystem) int32 GeometryExportTriangleCountWarningThreshold = 200000; protected: /** If set to true navigation will be generated only around registered "navigation enforcers" * This has a range of consequences (including how navigation octree operates) so it needs to * be a conscious decision. * Once enabled results in whole world being navigable. * @see RegisterNavigationInvoker */ UPROPERTY(EditDefaultsOnly, Category = "Navigation Enforcing", config) uint32 bGenerateNavigationOnlyAroundNavigationInvokers:1; /** Minimal time, in seconds, between active tiles set update */ UPROPERTY(EditAnywhere, Category = "Navigation Enforcing", meta = (ClampMin = "0.1", UIMin = "0.1", EditCondition = "bGenerateNavigationOnlyAroundNavigationInvokers"), config) float ActiveTilesUpdateInterval; /** When in use, invokers farther away from any invoker seed will be ignored (set to -1 to disable). */ UPROPERTY(EditAnywhere, Category = "Navigation Enforcing", meta = (EditCondition = "bGenerateNavigationOnlyAroundNavigationInvokers"), config) double InvokersMaximumDistanceFromSeed = -1; /** Sets how navigation data should be gathered when building collision information */ UPROPERTY(EditDefaultsOnly, Category = "NavigationSystem", config) ENavDataGatheringModeConfig DataGatheringMode; /** -1 by default, if set to a positive value dirty areas with any dimensions in 2d over the threshold created at runtime will be logged */ UPROPERTY(config, EditAnywhere, AdvancedDisplay, Category = NavigationSystem, meta = (ClampMin = "-1.0", UIMin = "-1.0")) float DirtyAreaWarningSizeThreshold; /** -1.0f by default, if set to a positive value, all calls to GetNavigationData will be timed and compared to it. * Over the limit calls will be logged as warnings. * In seconds. Non-shipping build only. */ UPROPERTY(config, EditAnywhere, AdvancedDisplay, Category = NavigationSystem, meta = (ClampMin = "-1.0", UIMin = "-1.0")) float GatheringNavModifiersWarningLimitTime; /** List of agents types supported by this navigation system */ UPROPERTY(config, EditAnywhere, Category = Agents) TArray SupportedAgents; /** NavigationSystem's properties in Project Settings define all possible supported agents, * but a specific navigation system can choose to support only a subset of agents. Set via * NavigationSystemConfig */ UPROPERTY(config, EditAnywhere, Category = Agents) FNavAgentSelector SupportedAgentsMask; public: /** Bounds of tiles to be built */ UPROPERTY(Transient) FBox BuildBounds; UPROPERTY(Transient) TArray> NavDataSet; UPROPERTY(Transient) TArray> NavDataRegistrationQueue; // List of pending navigation bounds update requests (add, remove, update size) TArray PendingNavBoundsUpdates; UPROPERTY(/*BlueprintAssignable, */Transient) FOnNavDataGenericEvent OnNavDataRegisteredEvent; UPROPERTY(BlueprintAssignable, Transient, meta = (displayname = OnNavigationGenerationFinished)) FOnNavDataGenericEvent OnNavigationGenerationFinishedDelegate; FOnNavigationInitDone OnNavigationInitDone; private: TWeakObjectPtr CrowdManager; /** set to true when navigation processing was blocked due to missing nav bounds */ uint32 bNavDataRemovedDueToMissingNavBounds : 1; protected: /** All areas where we build/have navigation */ TSet RegisteredNavBounds; private: TMap Invokers; /** Contains pre-digested and cached invokers' info. Generated by UpdateInvokers */ TArray InvokerLocations; TArray InvokersSeedBounds; double NextInvokersUpdateTime; NAVIGATIONSYSTEM_API void UpdateInvokers(); public: #if !UE_BUILD_SHIPPING void DebugLogInvokers(FOutputDevice& OutputDevice) const; #endif // !UE_BUILD_SHIPPING protected: NAVIGATIONSYSTEM_API virtual void UpdateNavDataActiveTiles(); private: NAVIGATIONSYSTEM_API void DirtyTilesInBuildBounds(); void UnregisterInvoker_Internal(const UObject& Invoker); /** Registers to the navigation objects repository subsystem delegates to get notified on object registration */ void RegisterToRepositoryDelegates(); /** Unregisters from the navigation objects repository subsystem delegates */ void UnregisterFromRepositoryDelegates() const; public: //----------------------------------------------------------------------// // Blueprint functions //----------------------------------------------------------------------// UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject")) static NAVIGATIONSYSTEM_API UNavigationSystemV1* GetNavigationSystem(UObject* WorldContextObject); /** Project a point onto the NavigationData */ UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "Project Point to Navigation", ScriptName = "ProjectPointToNavigation")) static NAVIGATIONSYSTEM_API bool K2_ProjectPointToNavigation(UObject* WorldContextObject, const FVector& Point, FVector& ProjectedLocation, ANavigationData* NavData, TSubclassOf FilterClass, const FVector QueryExtent = FVector::ZeroVector); /** Generates a random location reachable from given Origin location. * @return Return Value represents if the call was successful */ UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "Get Random Reachable Point in Radius", ScriptName = "GetRandomReachablePointInRadius")) static NAVIGATIONSYSTEM_API bool K2_GetRandomReachablePointInRadius(UObject* WorldContextObject, const FVector& Origin, FVector& RandomLocation, float Radius, ANavigationData* NavData = NULL, TSubclassOf FilterClass = NULL); /** Generates a random location in navigable space within given radius of Origin. * @return Return Value represents if the call was successful */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "Get Random Location in Navigable Radius", ScriptName = "GetRandomLocationInNavigableRadius")) static NAVIGATIONSYSTEM_API bool K2_GetRandomLocationInNavigableRadius(UObject* WorldContextObject, const FVector& Origin, FVector& RandomLocation, float Radius, ANavigationData* NavData = NULL, TSubclassOf FilterClass = NULL); /** Potentially expensive. Use with caution. Consider using UPathFollowingComponent::GetRemainingPathCost instead */ UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject")) static NAVIGATIONSYSTEM_API ENavigationQueryResult::Type GetPathCost(UObject* WorldContextObject, const FVector& PathStart, const FVector& PathEnd, double& PathCost, ANavigationData* NavData = NULL, TSubclassOf FilterClass = NULL); /** Potentially expensive. Use with caution */ UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject")) static NAVIGATIONSYSTEM_API ENavigationQueryResult::Type GetPathLength(UObject* WorldContextObject, const FVector& PathStart, const FVector& PathEnd, double& PathLength, ANavigationData* NavData = NULL, TSubclassOf FilterClass = NULL); UFUNCTION(BlueprintPure, Category="AI|Navigation", meta=(WorldContext="WorldContextObject" ) ) static NAVIGATIONSYSTEM_API bool IsNavigationBeingBuilt(UObject* WorldContextObject); UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject")) static NAVIGATIONSYSTEM_API bool IsNavigationBeingBuiltOrLocked(UObject* WorldContextObject); /** Finds path instantly, in a FindPath Synchronously. * @param PathfindingContext could be one of following: NavigationData (like Navmesh actor), Pawn or Controller. This parameter determines parameters of specific pathfinding query */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (WorldContext="WorldContextObject")) static NAVIGATIONSYSTEM_API UNavigationPath* FindPathToLocationSynchronously(UObject* WorldContextObject, const FVector& PathStart, const FVector& PathEnd, AActor* PathfindingContext = NULL, TSubclassOf FilterClass = NULL); /** Finds path instantly, in a FindPath Synchronously. Main advantage over FindPathToLocationSynchronously is that * the resulting path will automatically get updated if goal actor moves more than TetherDistance away from last path node * @param PathfindingContext could be one of following: NavigationData (like Navmesh actor), Pawn or Controller. This parameter determines parameters of specific pathfinding query */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (WorldContext="WorldContextObject")) static NAVIGATIONSYSTEM_API UNavigationPath* FindPathToActorSynchronously(UObject* WorldContextObject, const FVector& PathStart, AActor* GoalActor, float TetherDistance = 50.f, AActor* PathfindingContext = NULL, TSubclassOf FilterClass = NULL); /** Performs navigation raycast on NavigationData appropriate for given Querier. * @param Querier if not passed default navigation data will be used * @param HitLocation if line was obstructed this will be set to hit location. Otherwise it contains SegmentEnd * @return true if line from RayStart to RayEnd was obstructed. Also, true when no navigation data present */ UFUNCTION(BlueprintCallable, Category="AI|Navigation", meta=(WorldContext="WorldContextObject" )) static NAVIGATIONSYSTEM_API bool NavigationRaycast(UObject* WorldContextObject, const FVector& RayStart, const FVector& RayEnd, FVector& HitLocation, TSubclassOf FilterClass = NULL, AController* Querier = NULL); /** Performs navigation raycast on NavigationData appropriate for given Querier. * @param Querier if not passed default navigation data will be used * @param HitLocation if line was obstructed this will be set to hit location. Otherwise it contains SegmentEnd * @param AdditionalResults contains more information about the result of the raycast query. See FNavigationRaycastAdditionalResults description for details * @return true if line from RayStart to RayEnd was obstructed. Also, true when no navigation data present */ static NAVIGATIONSYSTEM_API bool NavigationRaycastWithAdditionalResults(UObject* WorldContextObject, const FVector& RayStart, const FVector& RayEnd, FVector& HitLocation, FNavigationRaycastAdditionalResults* AdditionalResults, TSubclassOf FilterClass = NULL, AController* Querier = NULL); /** will limit the number of simultaneously running navmesh tile generation jobs to specified number. * @param MaxNumberOfJobs gets trimmed to be at least 1. You cannot use this function to pause navmesh generation */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation") NAVIGATIONSYSTEM_API void SetMaxSimultaneousTileGenerationJobsCount(int32 MaxNumberOfJobs); /** Brings limit of simultaneous navmesh tile generation jobs back to Project Setting's default value */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation") NAVIGATIONSYSTEM_API void ResetMaxSimultaneousTileGenerationJobsCount(); /** Registers given actor as a "navigation enforcer" which means navigation system will * make sure navigation is being generated in specified radius around it. * @note: you need NavigationSystem's GenerateNavigationOnlyAroundNavigationInvokers to be set to true * to take advantage of this feature */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation") NAVIGATIONSYSTEM_API void RegisterNavigationInvoker(AActor* Invoker, float TileGenerationRadius = 3000, float TileRemovalRadius = 5000); /** Removes given actor from the list of active navigation enforcers. * @see RegisterNavigationInvoker for more details */ UFUNCTION(BlueprintCallable, Category = "AI|Navigation") NAVIGATIONSYSTEM_API void UnregisterNavigationInvoker(AActor* Invoker); UFUNCTION(BlueprintCallable, Category = "AI|Navigation|Generation") NAVIGATIONSYSTEM_API void SetGeometryGatheringMode(ENavDataGatheringModeConfig NewMode); UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta=(DisplayName="Replace Area in Octree Data")) NAVIGATIONSYSTEM_API bool K2_ReplaceAreaInOctreeData(const UObject* Object, TSubclassOf OldArea, TSubclassOf NewArea); FORCEINLINE bool IsActiveTilesGenerationEnabled() const{ return bGenerateNavigationOnlyAroundNavigationInvokers; } /** delegate type for events that dirty the navigation data ( Params: const FBox& DirtyBounds ) */ DECLARE_MULTICAST_DELEGATE_OneParam(FOnNavigationDirty, const FBox&); /** called after navigation influencing event takes place*/ static NAVIGATIONSYSTEM_API FOnNavigationDirty NavigationDirtyEvent; enum ERegistrationResult { RegistrationError, RegistrationFailed_DataPendingKill, // means navigation data being registered is marked as pending kill RegistrationFailed_AgentAlreadySupported, // this means that navigation agent supported by given nav data is already handled by some other, previously registered instance RegistrationFailed_AgentNotValid, // given instance contains navmesh that doesn't support any of expected agent types, or instance doesn't specify any agent RegistrationFailed_NotSuitable, // given instance had been considered unsuitable by current navigation system instance itself. NOTE: this value is not currently being used by the engine-supplied navigation system classes RegistrationSuccessful, }; // EOctreeUpdateMode is deprecated. Use FNavigationOctreeController::EOctreeUpdateMode instead enum EOctreeUpdateMode { OctreeUpdate_Default = 0, // regular update, mark dirty areas depending on exported content OctreeUpdate_Geometry = 1, // full update, mark dirty areas for geometry rebuild OctreeUpdate_Modifiers = 2, // quick update, mark dirty areas for modifier rebuild OctreeUpdate_Refresh = 4, // update is used for refresh, don't invalidate pending queue OctreeUpdate_ParentChain = 8, // update child nodes, don't remove anything }; //~ Begin UObject Interface NAVIGATIONSYSTEM_API virtual void PostInitProperties() override; NAVIGATIONSYSTEM_API virtual void FinishDestroy() override; static NAVIGATIONSYSTEM_API void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector); #if WITH_EDITOR NAVIGATIONSYSTEM_API virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override; NAVIGATIONSYSTEM_API virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override; #endif // WITH_EDITOR //~ End UObject Interface NAVIGATIONSYSTEM_API virtual void Tick(float DeltaSeconds) override; UWorld* GetWorld() const override { return GetOuterUWorld(); } UCrowdManagerBase* GetCrowdManager() const { return CrowdManager.Get(); } protected: NAVIGATIONSYSTEM_API void CalcTimeSlicedUpdateData(TArray& OutCurrentTimeSlicedBuildTaskDurations, TArray& OutIsTimeSlicingArray, bool& bOutAnyNonTimeSlicedGenerators, TArray>& OutNumTimeSlicedRemainingBuildTasksArray); /** spawn new crowd manager */ NAVIGATIONSYSTEM_API virtual void CreateCrowdManager(); /** Used to properly set navigation class for indicated agent and propagate information to other places * (like project settings) that may need this information */ NAVIGATIONSYSTEM_API void SetSupportedAgentsNavigationClass(int32 AgentIndex, TSubclassOf NavigationDataClass); public: //----------------------------------------------------------------------// //~ Begin Public querying Interface //----------------------------------------------------------------------// /** * Synchronously looks for a path from @fLocation to @EndLocation for agent with properties @AgentProperties. NavData actor appropriate for specified * FNavAgentProperties will be found automatically * @param ResultPath results are put here * @param NavData optional navigation data that will be used instead of the one that would be deducted from AgentProperties * @param Mode switch between normal and hierarchical path finding algorithms */ NAVIGATIONSYSTEM_API FPathFindingResult FindPathSync(const FNavAgentProperties& AgentProperties, FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular); /** * Does a simple path finding from @StartLocation to @EndLocation on specified NavData. If none passed MainNavData will be used * Result gets placed in ResultPath * @param NavData optional navigation data that will be used instead main navigation data * @param Mode switch between normal and hierarchical path finding algorithms */ NAVIGATIONSYSTEM_API FPathFindingResult FindPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular); /** * Asynchronously looks for a path from @StartLocation to @EndLocation for agent with properties @AgentProperties. NavData actor appropriate for specified * FNavAgentProperties will be found automatically * @param AgentProperties optional agent properties used to determine the NavData to use, only when the NavData inside the FPathFindingQuery was left empty. * @param ResultDelegate delegate that will be called once query has been processed and finished. Will be called even if query fails - in such case see comments for delegate's params * @param Mode switch between normal and hierarchical path finding algorithms * @return request ID */ NAVIGATIONSYSTEM_API uint32 FindPathAsync(const FNavAgentProperties& AgentProperties, FPathFindingQuery Query, const FNavPathQueryDelegate& ResultDelegate, EPathFindingMode::Type Mode = EPathFindingMode::Regular); /** Removes query indicated by given ID from queue of path finding requests to process. */ NAVIGATIONSYSTEM_API void AbortAsyncFindPathRequest(uint32 AsynPathQueryID); /** * Synchronously check if path between two points exists * Does not return path object, but will run faster (especially in hierarchical mode) * @param Mode switch between normal and hierarchical path finding algorithms. @note Hierarchical mode ignores QueryFilter * @return true if path exists */ NAVIGATIONSYSTEM_API bool TestPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular, int32* NumVisitedNodes = NULL) const; /** Finds random point in navigable space * @param ResultLocation Found point is put here * @param NavData If NavData == NULL then MainNavData is used. * @return true if any location found, false otherwise */ NAVIGATIONSYSTEM_API bool GetRandomPoint(FNavLocation& ResultLocation, ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL); /** Finds random, reachable point in navigable space restricted to Radius around Origin * @param ResultLocation Found point is put here * @param NavData If NavData == NULL then MainNavData is used. * @return true if any location found, false otherwise */ NAVIGATIONSYSTEM_API bool GetRandomReachablePointInRadius(const FVector& Origin, float Radius, FNavLocation& ResultLocation, ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const; /** Finds random, point in navigable space restricted to Radius around Origin. Resulting location is not tested for reachability from the Origin * @param ResultLocation Found point is put here * @param NavData If NavData == NULL then MainNavData is used. * @return true if any location found, false otherwise */ NAVIGATIONSYSTEM_API bool GetRandomPointInNavigableRadius(const FVector& Origin, float Radius, FNavLocation& ResultLocation, ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const; /** Calculates a path from PathStart to PathEnd and retrieves its cost. * @NOTE potentially expensive, so use it with caution */ NAVIGATIONSYSTEM_API ENavigationQueryResult::Type GetPathCost(const FVector& PathStart, const FVector& PathEnd, FVector::FReal& PathCost, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const; /** Calculates a path from PathStart to PathEnd and retrieves its overestimated length. * @NOTE potentially expensive, so use it with caution */ NAVIGATIONSYSTEM_API ENavigationQueryResult::Type GetPathLength(const FVector& PathStart, const FVector& PathEnd, FVector::FReal& PathLength, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const; /** Calculates a path from PathStart to PathEnd and retrieves its overestimated length and cost. * @NOTE potentially expensive, so use it with caution */ NAVIGATIONSYSTEM_API ENavigationQueryResult::Type GetPathLengthAndCost(const FVector& PathStart, const FVector& PathEnd, FVector::FReal& PathLength, FVector::FReal& PathCost, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const; // @todo document bool ProjectPointToNavigation(const FVector& Point, FNavLocation& OutLocation, const FVector& Extent = INVALID_NAVEXTENT, const FNavAgentProperties* AgentProperties = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) { return ProjectPointToNavigation(Point, OutLocation, Extent, AgentProperties != NULL ? GetNavDataForProps(*AgentProperties, Point) : GetDefaultNavDataInstance(FNavigationSystem::DontCreate), QueryFilter); } // @todo document NAVIGATIONSYSTEM_API bool ProjectPointToNavigation(const FVector& Point, FNavLocation& OutLocation, const FVector& Extent = INVALID_NAVEXTENT, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const; /** * Looks for NavData generated for specified movement properties and returns it. NULL if not found; */ NAVIGATIONSYSTEM_API virtual ANavigationData* GetNavDataForProps(const FNavAgentProperties& AgentProperties); /** * Looks for NavData generated for specified movement properties and returns it. NULL if not found; Const version. */ NAVIGATIONSYSTEM_API virtual const ANavigationData* GetNavDataForProps(const FNavAgentProperties& AgentProperties) const; /** Goes through all registered NavigationData instances and retrieves the one * supporting agent named AgentName */ NAVIGATIONSYSTEM_API virtual ANavigationData* GetNavDataForAgentName(const FName AgentName) const; /** * Looks up NavData appropriate for specified movement properties and returns it. NULL if not found; * This is the encouraged way of querying for the appropriate NavData. It makes no difference for NavigationSystemV1 * (AgentLocation and Extent parameters not being used) but NaV2 will take advantage of it and all engine-level * AI navigation code is going to use call this flavor. */ NAVIGATIONSYSTEM_API virtual ANavigationData* GetNavDataForProps(const FNavAgentProperties& AgentProperties, const FVector& AgentLocation, const FVector& Extent = INVALID_NAVEXTENT) const; /** Returns the world default navigation data instance. Creates one if it doesn't exist. */ NAVIGATIONSYSTEM_API ANavigationData* GetDefaultNavDataInstance(FNavigationSystem::ECreateIfMissing CreateNewIfNoneFound); /** Returns the world default navigation data instance. */ virtual INavigationDataInterface* GetMainNavData() const override { return Cast(GetDefaultNavDataInstance()); } ANavigationData& GetMainNavDataChecked() const { check(MainNavData); return *MainNavData; } /** Set limiting bounds to be used when building navigation data. */ NAVIGATIONSYSTEM_API virtual void SetBuildBounds(const FBox& Bounds) override; NAVIGATIONSYSTEM_API virtual FBox GetNavigableWorldBounds() const override; NAVIGATIONSYSTEM_API virtual bool ContainsNavData(const FBox& Bounds) const override; NAVIGATIONSYSTEM_API virtual FBox ComputeNavDataBounds() const override; NAVIGATIONSYSTEM_API virtual void AddNavigationDataChunk(class ANavigationDataChunkActor& DataChunkActor) override; NAVIGATIONSYSTEM_API virtual void RemoveNavigationDataChunk(class ANavigationDataChunkActor& DataChunkActor) override; NAVIGATIONSYSTEM_API virtual void FillNavigationDataChunkActor(const FBox& QueryBounds, class ANavigationDataChunkActor& DataChunkActor, FBox& OutTilesBounds) override; ANavigationData* GetDefaultNavDataInstance() const { return MainNavData; } ANavigationData* GetAbstractNavData() const { return AbstractNavData; } /** constructs a navigation data instance of specified NavDataClass, in passed Level * for supplied NavConfig. If Level == null and bSpawnNavDataInNavBoundsLevel == true * then the first volume actor in RegisteredNavBounds will be used to source the level. * Otherwise the navdata instance will be spawned in NavigationSystem's world */ NAVIGATIONSYSTEM_API virtual ANavigationData* CreateNavigationDataInstanceInLevel(const FNavDataConfig& NavConfig, ULevel* SpawnLevel); NAVIGATIONSYSTEM_API FSharedNavQueryFilter CreateDefaultQueryFilterCopy() const; /** Super-hacky safety feature for threaded navmesh building. Will be gone once figure out why keeping TSharedPointer to Navigation Generator doesn't * guarantee its existence */ NAVIGATIONSYSTEM_API bool ShouldGeneratorRun(const FNavDataGenerator* Generator) const; NAVIGATIONSYSTEM_API virtual bool IsNavigationBuilt(const AWorldSettings* Settings) const override; NAVIGATIONSYSTEM_API virtual bool IsThereAnywhereToBuildNavigation() const; bool ShouldGenerateNavigationEverywhere() const { return bWholeWorldNavigable; } bool ShouldAllowClientSideNavigation() const { return bAllowClientSideNavigation; } virtual bool ShouldLoadNavigationOnClient(ANavigationData* NavData = nullptr) const { return bAllowClientSideNavigation; } virtual bool ShouldDiscardSubLevelNavData(ANavigationData* NavData = nullptr) const { return bShouldDiscardSubLevelNavData; } NAVIGATIONSYSTEM_API FBox GetWorldBounds() const; NAVIGATIONSYSTEM_API FBox GetLevelBounds(ULevel* InLevel) const; NAVIGATIONSYSTEM_API bool IsNavigationRelevant(const AActor* TestActor) const; NAVIGATIONSYSTEM_API const TSet& GetNavigationBounds() const; static NAVIGATIONSYSTEM_API const FNavDataConfig& GetDefaultSupportedAgent(); static NAVIGATIONSYSTEM_API const FNavDataConfig& GetBiggestSupportedAgent(const UWorld* World); #if WITH_EDITOR static NAVIGATIONSYSTEM_API double GetWorldPartitionNavigationDataBuilderOverlap(const UWorld& World); #endif NAVIGATIONSYSTEM_API const FNavDataConfig& GetDefaultSupportedAgentConfig() const; FORCEINLINE const TArray& GetSupportedAgents() const { return SupportedAgents; } NAVIGATIONSYSTEM_API void OverrideSupportedAgents(const TArray& NewSupportedAgents); NAVIGATIONSYSTEM_API void SetSupportedAgentsMask(const FNavAgentSelector& InSupportedAgentsMask); FNavAgentSelector GetSupportedAgentsMask() const { return SupportedAgentsMask; } NAVIGATIONSYSTEM_API virtual void ApplyWorldOffset(const FVector& InOffset, bool bWorldShift) override; /** checks if navigation/navmesh is dirty and needs to be rebuilt */ NAVIGATIONSYSTEM_API bool IsNavigationDirty() const; /** checks if dirty navigation data can rebuild itself */ NAVIGATIONSYSTEM_API bool CanRebuildDirtyNavigation() const; FORCEINLINE bool SupportsNavigationGeneration() const { return bSupportRebuilding; } static NAVIGATIONSYSTEM_API bool DoesPathIntersectBox(const FNavigationPath* Path, const FBox& Box, uint32 StartingIndex = 0, FVector* AgentExtent = NULL); static NAVIGATIONSYSTEM_API bool DoesPathIntersectBox(const FNavigationPath* Path, const FBox& Box, const FVector& AgentLocation, uint32 StartingIndex = 0, FVector* AgentExtent = NULL); //----------------------------------------------------------------------// // Active tiles //----------------------------------------------------------------------// NAVIGATIONSYSTEM_API virtual void RegisterInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents, ENavigationInvokerPriority InPriority); NAVIGATIONSYSTEM_API virtual void RegisterInvoker(const TWeakInterfacePtr& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents, ENavigationInvokerPriority InPriority); NAVIGATIONSYSTEM_API virtual void UnregisterInvoker(AActor& Invoker); NAVIGATIONSYSTEM_API virtual void UnregisterInvoker(const TWeakInterfacePtr& Invoker); static NAVIGATIONSYSTEM_API void RegisterNavigationInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents = FNavAgentSelector(), ENavigationInvokerPriority Priority = ENavigationInvokerPriority::Default); static NAVIGATIONSYSTEM_API void UnregisterNavigationInvoker(AActor& Invoker); const TArray& GetInvokerLocations() const { return InvokerLocations; } const TArray& GetInvokersSeedBounds() const { return InvokersSeedBounds; } //----------------------------------------------------------------------// // Bookkeeping //----------------------------------------------------------------------// // @todo document NAVIGATIONSYSTEM_API virtual void UnregisterNavData(ANavigationData* NavData); /** Traverses SupportedAgents and for all agents not supported (i.e. filtered * out by SupportedAgentsMask) checks if there's a currently registered * NavigationData instance for that agent, and if so it unregisters that agent */ NAVIGATIONSYSTEM_API virtual void UnregisterUnusedNavData(); /** Adds NavData to registration candidates queue - NavDataRegistrationQueue*/ NAVIGATIONSYSTEM_API virtual void RequestRegistrationDeferred(ANavigationData& NavData); protected: NAVIGATIONSYSTEM_API void ApplySupportedAgentsFilter(); /** Processes all NavigationData instances in UWorld owning navigation system instance, and registers * all previously unregistered */ NAVIGATIONSYSTEM_API void RegisterNavigationDataInstances(); /** called in places where we need to spawn the NavOctree, but is checking additional conditions if we really want to do that * depending on navigation data setup among others * @return true if NavOctree instance has been created, or if one is already present */ NAVIGATIONSYSTEM_API virtual bool ConditionalPopulateNavOctree(); /** called to instantiate NavigationSystem's NavOctree instance */ NAVIGATIONSYSTEM_API virtual void ConstructNavOctree(); /** Processes registration of candidates queues via RequestRegistration and stored in NavDataRegistrationQueue */ NAVIGATIONSYSTEM_API virtual void ProcessRegistrationCandidates(); /** Registers custom navigation links awaiting registration in the navigation object repository */ NAVIGATIONSYSTEM_API void ProcessCustomLinkPendingRegistration(); UE_DEPRECATED(5.4, "Obsolete since navigation related objects register to the NavigationObjectRepository world subsytem.") static NAVIGATIONSYSTEM_API FCriticalSection CustomLinkRegistrationSection; UE_DEPRECATED(5.4, "Obsolete since navigation related objects register to the NavigationObjectRepository world subsytem.") static NAVIGATIONSYSTEM_API TMap PendingCustomLinkRegistration; /** used to apply updates of nav volumes in navigation system's tick */ NAVIGATIONSYSTEM_API virtual void PerformNavigationBoundsUpdate(const TArray& UpdateRequests); /** adds data to RegisteredNavBounds */ NAVIGATIONSYSTEM_API void AddNavigationBounds(const FNavigationBounds& NewBounds); /** Searches for all valid navigation bounds in the world and stores them */ NAVIGATIONSYSTEM_API virtual void GatherNavigationBounds(); /** Get seed locations for invokers, @see InvokersMaximumDistanceFromSeed * By default these are the player pawn locations. If a player controller has no pawn assigned, the player's camera location will be used instead. */ NAVIGATIONSYSTEM_API virtual void GetInvokerSeedLocations(const UWorld& InWorld, TArray>& OutSeedLocations); UE_DEPRECATED(5.4, "This function is deprecated. Use GetInvokerSeedLocations using TArray of FVector.") NAVIGATIONSYSTEM_API virtual void GetInvokerSeedLocations(const UWorld& InWorld, TArray>& OutSeedLocations); /** @return pointer to ANavigationData instance of given ID, or NULL if it was not found. Note it looks only through registered navigation data */ NAVIGATIONSYSTEM_API ANavigationData* GetNavDataWithID(const uint16 NavDataID) const; /** @return Valid shared pointer on a FNavigationElement if the provided UObject is registered in the navigation system, an invalid one otherwise. */ NAVIGATIONSYSTEM_API TSharedPtr GetNavigationElementForUObject(const UObject*) const; /** @return Valid handle if the provided UObject is registered in the navigation system, FNavigationElementHandle::Invalid otherwise. */ NAVIGATIONSYSTEM_API FNavigationElementHandle GetNavigationElementHandleForUObject(const UObject*) const; static NAVIGATIONSYSTEM_API void RegisterComponentToNavOctree(UActorComponent* Comp); static NAVIGATIONSYSTEM_API void UnregisterComponentToNavOctree(UActorComponent* Comp); public: NAVIGATIONSYSTEM_API virtual void ReleaseInitialBuildingLock(); //----------------------------------------------------------------------// // navigation octree related functions //----------------------------------------------------------------------// static NAVIGATIONSYSTEM_API bool SupportsDynamicChanges(UWorld* World); static NAVIGATIONSYSTEM_API FNavigationElementHandle AddNavigationElement(UWorld* World, FNavigationElement&& Element); static NAVIGATIONSYSTEM_API void RemoveNavigationElement(UWorld* World, FNavigationElementHandle ElementHandle); static NAVIGATIONSYSTEM_API void OnNavigationElementUpdated(UWorld* World, FNavigationElementHandle ElementHandle, FNavigationElement&& Element); static NAVIGATIONSYSTEM_API void OnNavRelevantObjectRegistered(UObject& Object); static NAVIGATIONSYSTEM_API void UpdateNavRelevantObjectInNavOctree(UObject& Object); static NAVIGATIONSYSTEM_API void OnNavRelevantObjectUnregistered(UObject& Object); static NAVIGATIONSYSTEM_API void OnComponentRegistered(UActorComponent* Comp); static NAVIGATIONSYSTEM_API void OnComponentUnregistered(UActorComponent* Comp); static NAVIGATIONSYSTEM_API void RegisterComponent(UActorComponent* Comp); static NAVIGATIONSYSTEM_API void UnregisterComponent(UActorComponent* Comp); static NAVIGATIONSYSTEM_API void OnActorRegistered(AActor* Actor); static NAVIGATIONSYSTEM_API void OnActorUnregistered(AActor* Actor); /** update navoctree entry for specified actor/component */ static NAVIGATIONSYSTEM_API void UpdateActorInNavOctree(AActor& Actor); static NAVIGATIONSYSTEM_API void UpdateComponentInNavOctree(UActorComponent& Comp); /** update all navoctree entries for actor and its components */ static NAVIGATIONSYSTEM_API void UpdateActorAndComponentsInNavOctree(AActor& Actor, bool bUpdateAttachedActors = true); /** update all navoctree entries for actor and its non scene components after root movement */ static NAVIGATIONSYSTEM_API void UpdateNavOctreeAfterMove(USceneComponent* Comp); protected: /** Fetches the repository from the provided object and registers the object with it. */ static NAVIGATIONSYSTEM_API void RegisterNavRelevantObjectStatic(const INavRelevantInterface& NavRelevantObject, const UObject& Object); /** Similar to UnregisterNavRelevantObjectStatic but uses the cached repository. */ NAVIGATIONSYSTEM_API void RegisterNavRelevantObjectInternal(const INavRelevantInterface& NavRelevantObject, const UObject& Object); /** Fetches the repository from the provided object and unregisters the object with it. */ static NAVIGATIONSYSTEM_API void UnregisterNavRelevantObjectStatic(const UObject& Object); /** Similar to UnregisterNavRelevantObjectStatic but uses the cached repository. */ NAVIGATIONSYSTEM_API void UnregisterNavRelevantObjectInternal(const UObject& Object); /** * In actor/component code paths it is possible that updates get called without a previous call to register (wasn't relevant at that time). * In those cases we create a new, or an updated, navigation element if needed. * @note Method expects only navigation relevant objects and will ensure otherwise. */ static NAVIGATIONSYSTEM_API void UpdateNavRelevantObjectInNavOctreeStatic( const INavRelevantInterface& InNavRelevantObject, const UObject& InObject, UNavigationSystemV1* InNavigationSystem, TFunctionRef&)> InCallback); /** A helper function that gathers all actors attached to RootActor and fetches * them back. The function does consider multi-level attachments. * @param RootActor The reference actor to get the attached actors from. * @param OutAttachedActors is getting reset at the beginning of the function. * When done it is guaranteed to contain unique, non-null ptrs. It * will not include RootActor. * @return the number of unique attached actors */ static NAVIGATIONSYSTEM_API int32 GetAllAttachedActors(const AActor& RootActor, TArray& OutAttachedActors); /** updates navoctree information on actors attached to RootActor */ static NAVIGATIONSYSTEM_API void UpdateAttachedActorsInNavOctree(AActor& RootActor); public: /** removes all navoctree entries for actor and its components */ static NAVIGATIONSYSTEM_API void ClearNavOctreeAll(AActor* Actor); /** updates bounds of all components implementing INavRelevantInterface */ static NAVIGATIONSYSTEM_API void UpdateNavOctreeBounds(AActor* Actor); NAVIGATIONSYSTEM_API void AddDirtyArea(const FBox& NewArea, ENavigationDirtyFlag Flags, const FName& DebugReason = NAME_None); NAVIGATIONSYSTEM_API void AddDirtyArea(const FBox& NewArea, ENavigationDirtyFlag Flags, const TFunction()>& ElementProviderFunc, const FName& DebugReason = NAME_None); NAVIGATIONSYSTEM_API void AddDirtyAreas(const TArray& NewAreas, ENavigationDirtyFlag Flags, const FName& DebugReason = NAME_None); UE_DEPRECATED(5.5, "Use the version taking ENavigationDirtyFlag instead.") NAVIGATIONSYSTEM_API void AddDirtyArea(const FBox& NewArea, int32 Flags, const FName& DebugReason = NAME_None); UE_DEPRECATED(5.5, "Use the version taking ENavigationDirtyFlag instead.") NAVIGATIONSYSTEM_API void AddDirtyArea(const FBox& NewArea, int32 Flags, const TFunction& ObjectProviderFunc, const FName& DebugReason = NAME_None); UE_DEPRECATED(5.5, "Use the version taking ENavigationDirtyFlag instead.") NAVIGATIONSYSTEM_API void AddDirtyAreas(const TArray& NewAreas, int32 Flags, const FName& DebugReason = NAME_None); NAVIGATIONSYSTEM_API bool HasDirtyAreasQueued() const; NAVIGATIONSYSTEM_API int32 GetNumDirtyAreas() const; float GetDirtyAreaWarningSizeThreshold() const { return DirtyAreaWarningSizeThreshold; } const FNavigationOctree* GetNavOctree() const { return DefaultOctreeController.GetOctree(); } FNavigationOctree* GetMutableNavOctree() { return DefaultOctreeController.GetMutableOctree(); } UE_DEPRECATED(5.5, "This method is no longer used by the navigation system.") NAVIGATIONSYSTEM_API static uint32 HashObject(const UObject& Object); FORCEINLINE const FOctreeElementId2* GetNavOctreeIdForElement(FNavigationElementHandle Element) const { return DefaultOctreeController.GetNavOctreeIdForElement(Element); } UE_DEPRECATED(5.5, "Use GetNavOctreeIdForElement instead.") NAVIGATIONSYSTEM_API const FOctreeElementId2* GetObjectsNavOctreeId(const UObject& Object) const; FORCEINLINE bool HasPendingUpdateForElement(FNavigationElementHandle Element) const { return DefaultOctreeController.HasPendingUpdateForElement(Element); } UE_DEPRECATED(5.5, "Use HasPendingUpdateForElement instead.") NAVIGATIONSYSTEM_API bool HasPendingObjectNavOctreeId(UObject* Object) const; UE_DEPRECATED(5.5, "This functionality should not be exposed and will be removed.") NAVIGATIONSYSTEM_API void RemoveObjectsNavOctreeId(const UObject& Object); UE_DEPRECATED(5.5, "This functionality should not be exposed publicly and will be removed. Derived classes should use RemoveFromNavOctree instead.") NAVIGATIONSYSTEM_API void RemoveNavOctreeElementId(const FOctreeElementId2& ElementId, int32 UpdateFlags); protected: NAVIGATIONSYSTEM_API void RemoveFromNavOctree(const FOctreeElementId2& ElementId, int32 UpdateFlags); public: NAVIGATIONSYSTEM_API const FNavigationRelevantData* GetDataForElement(FNavigationElementHandle Element) const; UE_DEPRECATED(5.5, "Use GetDataForElement instead.") NAVIGATIONSYSTEM_API const FNavigationRelevantData* GetDataForObject(const UObject& Object) const; NAVIGATIONSYSTEM_API FNavigationRelevantData* GetMutableDataForElement(FNavigationElementHandle Element); UE_DEPRECATED(5.5, "Use GetMutableDataForElement instead.") NAVIGATIONSYSTEM_API FNavigationRelevantData* GetMutableDataForObject(const UObject& Object); /** find all elements in navigation octree within given box (intersection) */ NAVIGATIONSYSTEM_API void FindElementsInNavOctree(const FBox& QueryBox, const FNavigationOctreeFilter& Filter, TArray& Elements); /** update single element in navoctree */ NAVIGATIONSYSTEM_API void UpdateNavOctreeElement(FNavigationElementHandle Handle, const TSharedRef& Element, int32 UpdateFlags); UE_DEPRECATED(5.5, "Use the version taking FNavigationElement instead.") void UpdateNavOctreeElement(UObject* ElementOwner, INavRelevantInterface* ElementInterface, int32 UpdateFlags); UE_DEPRECATED(5.5, "This method will no longer be public and should not be called directly.") NAVIGATIONSYSTEM_API void UpdateNavOctreeParentChain(UObject* ElementOwner, bool bSkipElementOwnerUpdate = false); /** update element's bounds in navigation octree and mark only specified area as dirty, doesn't re-export geometry */ NAVIGATIONSYSTEM_API bool UpdateNavOctreeElementBounds(FNavigationElementHandle Handle, const FBox& NewBounds, TConstArrayView DirtyAreas); UE_DEPRECATED(5.4, "Use the overloaded version with object reference and list of dirty areas as parameters instead.") /** update component bounds in navigation octree and mark only specified area as dirty, doesn't re-export component geometry */ NAVIGATIONSYSTEM_API bool UpdateNavOctreeElementBounds(UActorComponent* Comp, const FBox& NewBounds, const FBox& DirtyArea); UE_DEPRECATED(5.5, "Use the version taking FNavigationElement instead.") NAVIGATIONSYSTEM_API bool UpdateNavOctreeElementBounds(UObject& Object, const FBox& NewBounds, TConstArrayView DirtyAreas); /** fetched element's data from the octree and replaces occurrences of OldArea with NewArea */ NAVIGATIONSYSTEM_API bool ReplaceAreaInOctreeData(FNavigationElementHandle Handle, TSubclassOf OldArea, TSubclassOf NewArea, bool bReplaceChildClasses = false); UE_DEPRECATED(5.5, "Use the version taking FNavigationElement instead.") NAVIGATIONSYSTEM_API bool ReplaceAreaInOctreeData(const UObject& Object, TSubclassOf OldArea, TSubclassOf NewArea, bool bReplaceChildClasses = false); //----------------------------------------------------------------------// // Custom navigation links //----------------------------------------------------------------------// NAVIGATIONSYSTEM_API virtual void RegisterCustomLink(INavLinkCustomInterface& CustomLink); NAVIGATIONSYSTEM_API void UnregisterCustomLink(INavLinkCustomInterface& CustomLink); int32 GetNumCustomLinks() const { return CustomNavLinksMap.Num(); } static NAVIGATIONSYSTEM_API void RequestCustomLinkRegistering(INavLinkCustomInterface& CustomLink, UObject* OwnerOb); static NAVIGATIONSYSTEM_API void RequestCustomLinkUnregistering(INavLinkCustomInterface& CustomLink, UObject* ObjectOb); UE_DEPRECATED(5.3, "LinkIds are now based on FNavLinkId call the version of this function that takes FNavLinkId. This function only returns nullptr.") INavLinkCustomInterface* GetCustomLink(uint32 UniqueLinkId) const { return nullptr; } /** find custom link by unique ID */ NAVIGATIONSYSTEM_API INavLinkCustomInterface* GetCustomLink(FNavLinkId UniqueLinkId) const; /** updates custom link for all active navigation data instances */ NAVIGATIONSYSTEM_API void UpdateCustomLink(const INavLinkCustomInterface* CustomLink); /** Return a Bounding Box containing the navlink points */ static NAVIGATIONSYSTEM_API FBox ComputeCustomLinkBounds(const INavLinkCustomInterface& CustomLink); //----------------------------------------------------------------------// // Areas //----------------------------------------------------------------------// static NAVIGATIONSYSTEM_API void RequestAreaRegistering(UClass* NavAreaClass); static NAVIGATIONSYSTEM_API void RequestAreaUnregistering(UClass* NavAreaClass); /** find index in SupportedAgents array for given navigation data */ NAVIGATIONSYSTEM_API int32 GetSupportedAgentIndex(const ANavigationData* NavData) const; /** find index in SupportedAgents array for agent type */ NAVIGATIONSYSTEM_API int32 GetSupportedAgentIndex(const FNavAgentProperties& NavAgent) const; //----------------------------------------------------------------------// // Filters //----------------------------------------------------------------------// /** prepare descriptions of navigation flags in UNavigationQueryFilter class: using enum */ NAVIGATIONSYSTEM_API void DescribeFilterFlags(UEnum* FlagsEnum) const; /** prepare descriptions of navigation flags in UNavigationQueryFilter class: using array */ NAVIGATIONSYSTEM_API void DescribeFilterFlags(const TArray& FlagsDesc) const; /** removes cached filters from currently registered navigation data */ NAVIGATIONSYSTEM_API void ResetCachedFilter(TSubclassOf FilterClass); //----------------------------------------------------------------------// // building //----------------------------------------------------------------------// /** Triggers navigation building on all eligible navigation data. */ NAVIGATIONSYSTEM_API virtual void Build(); /** Cancels all currently running navigation builds */ NAVIGATIONSYSTEM_API virtual void CancelBuild(); // @todo document NAVIGATIONSYSTEM_API void OnPIEStart(); // @todo document NAVIGATIONSYSTEM_API void OnPIEEnd(); // @todo document FORCEINLINE bool IsNavigationBuildingLocked(uint8 Flags = ~0) const { return (NavBuildingLockFlags & Flags) != 0; } /** check if building is permanently locked to avoid showing navmesh building notify (due to queued dirty areas) */ FORCEINLINE bool IsNavigationBuildingPermanentlyLocked() const { return (NavBuildingLockFlags & ~ENavigationBuildLock::InitialLock) != 0; } /** check if navigation octree updates are currently ignored */ FORCEINLINE bool IsNavigationOctreeLocked() const { return DefaultOctreeController.IsNavigationOctreeLocked(); } // @todo document UFUNCTION(BlueprintCallable, Category = "AI|Navigation") NAVIGATIONSYSTEM_API void OnNavigationBoundsUpdated(ANavMeshBoundsVolume* NavVolume); NAVIGATIONSYSTEM_API virtual void OnNavigationBoundsAdded(ANavMeshBoundsVolume* NavVolume); NAVIGATIONSYSTEM_API virtual void OnNavigationBoundsRemoved(ANavMeshBoundsVolume* NavVolume); /** determines whether any generator is performing navigation building actions at the moment, dirty areas are also checked */ NAVIGATIONSYSTEM_API bool IsNavigationBuildInProgress(); NAVIGATIONSYSTEM_API virtual void OnNavigationGenerationFinished(ANavigationData& NavData); /** Used to display "navigation building in progress" counter */ NAVIGATIONSYSTEM_API int32 GetNumRemainingBuildTasks() const; /** Number of currently running tasks */ NAVIGATIONSYSTEM_API int32 GetNumRunningBuildTasks() const; protected: /** Sets up SuportedAgents and NavigationDataCreators. Override it to add additional setup, but make sure to call Super implementation */ NAVIGATIONSYSTEM_API virtual void DoInitialSetup(); /** Find or create abstract nav data */ NAVIGATIONSYSTEM_API virtual void UpdateAbstractNavData(); /** Called during ConditionalPopulateNavOctree and gives subclassess a chance * to influence what gets added */ NAVIGATIONSYSTEM_API virtual void AddLevelToOctree(ULevel& Level); /** Called as part of UWorld::BeginTearingDown */ NAVIGATIONSYSTEM_API virtual void OnBeginTearingDown(UWorld* World); public: /** Called upon UWorld destruction to release what needs to be released */ NAVIGATIONSYSTEM_API virtual void CleanUp(const FNavigationSystem::ECleanupMode Mode = FNavigationSystem::ECleanupMode::CleanupUnsafe) override; /** * Called when owner-UWorld initializes actors */ NAVIGATIONSYSTEM_API virtual void OnInitializeActors() override; /** */ NAVIGATIONSYSTEM_API virtual void OnWorldInitDone(FNavigationSystemRunMode Mode); /** Returns true if world has been initialized. */ FORCEINLINE virtual bool IsWorldInitDone() const override { return bWorldInitDone; } FORCEINLINE bool IsInitialized() const { return bWorldInitDone; } FORCEINLINE FNavigationSystemRunMode GetRunMode() const { return OperationMode; } /** adds BSP collisions of currently streamed in levels to octree */ NAVIGATIONSYSTEM_API void InitializeLevelCollisions(); enum class ELockRemovalRebuildAction { Rebuild, RebuildIfNotInEditor, NoRebuild }; NAVIGATIONSYSTEM_API void AddNavigationBuildLock(uint8 Flags); NAVIGATIONSYSTEM_API void RemoveNavigationBuildLock(uint8 Flags, const ELockRemovalRebuildAction RebuildAction = ELockRemovalRebuildAction::Rebuild); NAVIGATIONSYSTEM_API void SetNavigationOctreeLock(bool bLock); /** checks if auto-rebuilding navigation data is enabled. Defaults to bNavigationAutoUpdateEnabled * value, but can be overridden per nav sys instance */ virtual bool GetIsAutoUpdateEnabled() const { return bNavigationAutoUpdateEnabled; } #if WITH_EDITOR /** allow editor to toggle whether seamless navigation building is enabled */ static NAVIGATIONSYSTEM_API void SetNavigationAutoUpdateEnabled(bool bNewEnable, UNavigationSystemBase* InNavigationSystem); FORCEINLINE bool IsNavigationRegisterLocked() const { return NavUpdateLockFlags != 0; } FORCEINLINE bool IsNavigationUnregisterLocked() const { return NavUpdateLockFlags && !(NavUpdateLockFlags & ENavigationLockReason::AllowUnregister); } FORCEINLINE bool IsNavigationUpdateLocked() const { return IsNavigationRegisterLocked(); } FORCEINLINE void AddNavigationUpdateLock(uint8 Flags) { NavUpdateLockFlags |= Flags; } FORCEINLINE void RemoveNavigationUpdateLock(uint8 Flags) { NavUpdateLockFlags &= ~Flags; } NAVIGATIONSYSTEM_API void UpdateLevelCollision(ULevel* InLevel); #endif // WITH_EDITOR FORCEINLINE bool IsSetUpForLazyGeometryExporting() const { return bGenerateNavigationOnlyAroundNavigationInvokers; } UE_DEPRECATED(5.5, "This creation flow is deprecation. Use FNavigationSystem::AddNavigationSystemToWorld instead.") static NAVIGATIONSYSTEM_API UNavigationSystemV1* CreateNavigationSystem(UWorld* WorldOwner); static NAVIGATIONSYSTEM_API UNavigationSystemV1* GetCurrent(UWorld* World); static NAVIGATIONSYSTEM_API UNavigationSystemV1* GetCurrent(UObject* WorldContextObject); NAVIGATIONSYSTEM_API virtual void InitializeForWorld(UWorld& World, FNavigationSystemRunMode Mode) override; // Fetch the array of all nav-agent properties. NAVIGATIONSYSTEM_API void GetNavAgentPropertiesArray(TArray& OutNavAgentProperties) const; static FORCEINLINE bool ShouldUpdateNavOctreeOnComponentChange() { return (bUpdateNavOctreeOnComponentChange && !bStaticRuntimeNavigation) #if WITH_EDITOR || (GIsEditor && !GIsPlayInEditorWorld) #endif ; } /** * Indicates whether navigation is allowed for a given world. * @param World The world in which the navigation would be used * @return whether the navigation system can be used in the specified world or not */ NAVIGATIONSYSTEM_API virtual bool ShouldCreateNavigationSystemInstance(const UWorld* World) const override; static FORCEINLINE bool IsNavigationSystemStatic() { #if WITH_EDITOR return (bStaticRuntimeNavigation && !(GIsEditor && !GIsPlayInEditorWorld)) || IsRunningCookCommandlet(); // consider navigation static when cooking to eliminate useless operations #else return bStaticRuntimeNavigation; #endif // WITH_EDITOR } /** call with bEnableStatic == true to signal the NavigationSystem it doesn't need to store * any navigation-generation-related data at game runtime, because * nothing is going to use it anyway. This will short-circuit all code related * to navmesh rebuilding, so use it only if you have fully static navigation in * your game. bEnableStatic = false will reset the mechanism. * Note: this is not a runtime switch. It's highly advisable not to call it manually and * use UNavigationSystemModuleConfig.bStrictlyStatic instead */ static NAVIGATIONSYSTEM_API void ConfigureAsStatic(bool bEnableStatic = true); static NAVIGATIONSYSTEM_API void SetUpdateNavOctreeOnComponentChange(bool bNewUpdateOnComponentChange); /** * Exec command handlers */ NAVIGATIONSYSTEM_API bool HandleCycleNavDrawnCommand( const TCHAR* Cmd, FOutputDevice& Ar ); NAVIGATIONSYSTEM_API bool HandleCountNavMemCommand(); //----------------------------------------------------------------------// // debug //----------------------------------------------------------------------// NAVIGATIONSYSTEM_API void CycleNavigationDataDrawn(); FNavRegenTimeSliceManager& GetMutableNavRegenTimeSliceManager() { return NavRegenTimeSliceManager; } FNavigationSystemRunMode GetOperationMode() const { return OperationMode; } protected: UPROPERTY() FNavigationSystemRunMode OperationMode; /** Queued async pathfinding queries to process in the next update. */ TArray AsyncPathFindingQueries; /** Queued async pathfinding results computed by the dedicated task in the last frame and ready to dispatch in the next update. */ TArray AsyncPathFindingCompletedQueries; /** Graph event that the main thread will wait for to synchronize with the async pathfinding task, if any. */ FGraphEventRef AsyncPathFindingTask; /** Flag used by main thread to ask the async pathfinding task to stop and postpone remaining queries, if any. */ TAtomic bAbortAsyncQueriesRequested; FCriticalSection NavDataRegistration; TMap > AgentToNavDataMap; FNavigationOctreeController DefaultOctreeController; TMap CustomNavLinksMap; FNavigationDirtyAreasController DefaultDirtyAreasController; UPROPERTY(transient) TObjectPtr Repository = nullptr; // async queries FCriticalSection NavDataRegistrationSection; #if WITH_EDITOR uint8 NavUpdateLockFlags; #endif uint8 NavBuildingLockFlags; /** set of locking flags applied on startup of navigation system */ uint8 InitialNavBuildingLockFlags; uint8 bInitialSetupHasBeenPerformed : 1; uint8 bInitialLevelsAdded : 1; uint8 bWorldInitDone : 1; /** set when the NavSys instance has been cleaned up. This is an irreversible state */ uint8 bCleanUpDone : 1; uint8 bAsyncBuildPaused : 1; // mz@todo remove, replaced by bIsPIEActive and IsGameWorld protected: /** cached navigable world bounding box*/ mutable FBox NavigableWorldBounds; /** indicates which of multiple navigation data instances to draw*/ int32 CurrentlyDrawnNavDataIndex; #if !UE_BUILD_SHIPPING /** self-registering exec command to handle nav sys console commands */ static NAVIGATIONSYSTEM_API FNavigationSystemExec ExecHandler; #endif // !UE_BUILD_SHIPPING /** whether seamless navigation building is enabled */ static NAVIGATIONSYSTEM_API bool bNavigationAutoUpdateEnabled; static NAVIGATIONSYSTEM_API bool bUpdateNavOctreeOnComponentChange; static NAVIGATIONSYSTEM_API bool bStaticRuntimeNavigation; static NAVIGATIONSYSTEM_API bool bIsPIEActive; TSet> NavAreaClasses; FNavRegenTimeSliceManager NavRegenTimeSliceManager; /** delegate handler for PostLoadMap event */ NAVIGATIONSYSTEM_API void OnPostLoadMap(UWorld* LoadedWorld); #if WITH_EDITOR /** delegate handler for ActorMoved events */ NAVIGATIONSYSTEM_API void OnActorMoved(AActor* Actor); #endif /** delegate handler called when navigation is dirtied*/ NAVIGATIONSYSTEM_API void OnNavigationDirtied(const FBox& Bounds); FDelegateHandle ReloadCompleteDelegateHandle; /** called to notify NavigationSystem about finished reload */ NAVIGATIONSYSTEM_API virtual void OnReloadComplete(EReloadCompleteReason Reason); /** Registers given navigation data with this Navigation System. * @return RegistrationSuccessful if registration was successful, other results mean it failed * @see ERegistrationResult */ NAVIGATIONSYSTEM_API virtual ERegistrationResult RegisterNavData(ANavigationData* NavData); /** tries to register navigation area */ NAVIGATIONSYSTEM_API void RegisterNavAreaClass(UClass* NavAreaClass); /** tries to unregister navigation area */ NAVIGATIONSYSTEM_API void UnregisterNavAreaClass(UClass* NavAreaClass); NAVIGATIONSYSTEM_API void OnNavigationAreaEvent(UClass* AreaClass, ENavAreaEvent::Type Event); NAVIGATIONSYSTEM_API FSetElementId RegisterNavigationElementWithNavOctree(const TSharedRef& Element, int32 UpdateFlags); UE_DEPRECATED(5.5, "Use the version taking FNavigationElement as parameter instead.") NAVIGATIONSYSTEM_API FSetElementId RegisterNavOctreeElement(UObject* ElementOwner, INavRelevantInterface* ElementInterface, int32 UpdateFlags); NAVIGATIONSYSTEM_API void UnregisterNavigationElementWithOctree(const TSharedRef& Element, int32 UpdateFlags); UE_DEPRECATED(5.5, "Use the version taking FNavigationElement as parameter instead.") NAVIGATIONSYSTEM_API void UnregisterNavOctreeElement(UObject* ElementOwner, INavRelevantInterface* ElementInterface, int32 UpdateFlags); /** read element data from navigation octree */ NAVIGATIONSYSTEM_API bool GetNavOctreeElementData(FNavigationElementHandle Element, ENavigationDirtyFlag& OutDirtyFlags, FBox& OutDirtyBounds); UE_DEPRECATED(5.5, "Use the version taking FNavigationElement instead.") NAVIGATIONSYSTEM_API bool GetNavOctreeElementData(const UObject& NodeOwner, int32& DirtyFlags, FBox& DirtyBounds); /** Adds given element to NavOctree. No check for owner's validity are performed, * nor its presence in NavOctree - function assumes callee responsibility * in this regard **/ NAVIGATIONSYSTEM_API void AddElementToNavOctree(const FNavigationDirtyElement& DirtyElement); NAVIGATIONSYSTEM_API void SetCrowdManager(UCrowdManagerBase* NewCrowdManager); /** Add BSP collision data to navigation octree */ NAVIGATIONSYSTEM_API void AddLevelCollisionToOctree(ULevel* Level); /** Remove BSP collision data from navigation octree */ NAVIGATIONSYSTEM_API void RemoveLevelCollisionFromOctree(ULevel* Level); NAVIGATIONSYSTEM_API virtual void SpawnMissingNavigationData(); /** * Fills a mask indicating which navigation data associated to the supported agent mask are already instantiated. * @param OutInstantiatedMask The mask that will represent already instantiated navigation data. * @param InLevel If specified will be used to search for navigation data; will use the owning world otherwise. * @return Number of instantiated navigation data. */ NAVIGATIONSYSTEM_API uint8 FillInstantiatedDataMask(TBitArray<>& OutInstantiatedMask, ULevel* InLevel = nullptr); /** * Spawns missing navigation data. * @param InInstantiatedMask The mask representing already instantiated navigation data. * @param InLevel Level in which the new data must be added. See CreateNavigationDataInstanceInLevel doc. */ NAVIGATIONSYSTEM_API void SpawnMissingNavigationDataInLevel(const TBitArray<>& InInstantiatedMask, ULevel* InLevel = nullptr); public: NAVIGATIONSYSTEM_API void DemandLazyDataGathering(FNavigationRelevantData& ElementData); private: // Reduces a nav bounds only to regions overlapping loaded world partition regions (if any exist) void CheckToLimitNavigationBoundsToLoadedRegions(FNavigationBounds& OutBounds) const; protected: NAVIGATIONSYSTEM_API virtual void RebuildDirtyAreas(float DeltaSeconds); // adds navigation bounds update request to a pending list NAVIGATIONSYSTEM_API void AddNavigationBoundsUpdateRequest(const FNavigationBoundsUpdateRequest& UpdateRequest); /** Triggers navigation building on all eligible navigation data. */ NAVIGATIONSYSTEM_API virtual void RebuildAll(bool bIsLoadTime = false); /** Handler for FWorldDelegates::LevelAddedToWorld event */ NAVIGATIONSYSTEM_API void OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld); /** Handler for FWorldDelegates::LevelRemovedFromWorld event */ NAVIGATIONSYSTEM_API void OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld); /** Handler for FWorldDelegates::OnWorldPostActorTick event */ void OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaTime) { TRACE_CPUPROFILER_EVENT_SCOPE(UNavigationSystemV1::OnWorldPostActorTick) PostponeAsyncQueries(); } /** Adds given request to requests queue. Note it's to be called only on game thread only */ NAVIGATIONSYSTEM_API void AddAsyncQuery(const FAsyncPathFindingQuery& Query); /** spawns a non-game-thread task to process requests given in PathFindingQueries. * In the process PathFindingQueries gets copied. */ NAVIGATIONSYSTEM_API void TriggerAsyncQueries(TArray& PathFindingQueries); /** Processes pathfinding requests given in PathFindingQueries.*/ NAVIGATIONSYSTEM_API void PerformAsyncQueries(TArray PathFindingQueries); /** Broadcasts completion delegate for all completed async pathfinding requests. */ NAVIGATIONSYSTEM_API void DispatchAsyncQueriesResults(const TArray& PathFindingQueries) const; /** * Requests the async pathfinding task to abort and waits for it to complete * before resuming the main thread. Pathfind task will postpone remaining queries to next frame. */ NAVIGATIONSYSTEM_API void PostponeAsyncQueries(); /** */ NAVIGATIONSYSTEM_API virtual void DestroyNavOctree(); /** Whether Navigation system needs to populate nav octree. * Depends on runtime generation settings of each navigation data, always true in the editor */ NAVIGATIONSYSTEM_API bool RequiresNavOctree() const; /** Return "Strongest" runtime generation type required by registered navigation data objects * Depends on runtime generation settings of each navigation data, always ERuntimeGenerationType::Dynamic in the editor world */ NAVIGATIONSYSTEM_API ERuntimeGenerationType GetRuntimeGenerationType() const; NAVIGATIONSYSTEM_API void LogNavDataRegistrationResult(ERegistrationResult); /** Whether Navigation System is allowed to rebuild the navmesh * Depends on runtime generation settings of each navigation data, always true in the editor */ NAVIGATIONSYSTEM_API bool IsAllowedToRebuild() const; /** Handle forwarding the information where needed when the setting is changed*/ NAVIGATIONSYSTEM_API void OnGenerateNavigationOnlyAroundNavigationInvokersChanged(); //----------------------------------------------------------------------// // new stuff //----------------------------------------------------------------------// public: NAVIGATIONSYSTEM_API void VerifyNavigationRenderingComponents(const bool bShow); /** @param InLevel Optional parameter to limit the navigation bounds to consider to the ones from that level */ NAVIGATIONSYSTEM_API virtual int GetNavigationBoundsForNavData(const ANavigationData& NavData, TArray& OutBounds, ULevel* InLevel = nullptr) const; static NAVIGATIONSYSTEM_API INavigationDataInterface* GetNavDataForActor(const AActor& Actor); NAVIGATIONSYSTEM_API virtual void Configure(const UNavigationSystemConfig& Config) override; NAVIGATIONSYSTEM_API virtual void AppendConfig(const UNavigationSystemConfig& NewConfig) override; #if !UE_BUILD_SHIPPING NAVIGATIONSYSTEM_API void GetOnScreenMessages(TMultiMap& OutMessages); #endif // !UE_BUILD_SHIPPING //----------------------------------------------------------------------// // DEPRECATED //----------------------------------------------------------------------// public: // Note that this function was only deprecated for blueprint in 5.1 // Note2: originally deprecated as 4.22, bumped up to 5.1 as per comment above. UE_DEPRECATED(5.1, "This version is deprecated. Please use GetRandomLocationInNavigableRadius instead") UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "GetRandomPointInNavigableRadius", ScriptName = "GetRandomPointInNavigableRadius", DeprecatedFunction, DeprecationMessage = "GetRandomPointInNavigableRadius is deprecated. Use GetRandomLocationInNavigableRadius instead")) static NAVIGATIONSYSTEM_API bool K2_GetRandomPointInNavigableRadius(UObject* WorldContextObject, const FVector& Origin, FVector& RandomLocation, float Radius, ANavigationData* NavData = NULL, TSubclassOf FilterClass = NULL); }; //----------------------------------------------------------------------// // UNavigationSystemModuleConfig //----------------------------------------------------------------------// UCLASS(MinimalAPI) class UNavigationSystemModuleConfig : public UNavigationSystemConfig { GENERATED_BODY() protected: /** Whether at game runtime we expect any kind of dynamic navigation generation */ UPROPERTY(EditAnywhere, Category = Navigation) uint32 bStrictlyStatic : 1; UPROPERTY(EditAnywhere, Category = Navigation) uint32 bCreateOnClient : 1; UPROPERTY(EditAnywhere, Category = Navigation) uint32 bAutoSpawnMissingNavData : 1; UPROPERTY(EditAnywhere, Category = Navigation) uint32 bSpawnNavDataInNavBoundsLevel : 1; public: NAVIGATIONSYSTEM_API UNavigationSystemModuleConfig(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); NAVIGATIONSYSTEM_API virtual void PostInitProperties() override; NAVIGATIONSYSTEM_API virtual UNavigationSystemBase* CreateAndConfigureNavigationSystem(UWorld& World) const override; #if WITH_EDITOR NAVIGATIONSYSTEM_API virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; #endif // WITH_EDITOR protected: #if WITH_EDITOR friend UNavigationSystemV1; #endif // WITH_EDITOR NAVIGATIONSYSTEM_API void UpdateWithNavSysCDO(const UNavigationSystemV1& NavSysCDO); };