Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a0600b4
ClampLocationToNavigableWorld pulls in the result by a tiny margin, f…
OregonJunco Jan 15, 2019
844ae3f
No longer applying the margin for clamping up values that were too lo…
OregonJunco Jan 15, 2019
112d4a1
Moved the callback for async requests to happen after the task is ful…
OregonJunco Jan 15, 2019
830bbbd
remove binary files
FAUSheppy Feb 4, 2021
76cf1bc
add Binaries/ and Intermediate/ to gitignore
FAUSheppy Feb 4, 2021
95b47d7
check internal state before checking task
FAUSheppy Feb 4, 2021
e9533af
improve error-log for internal state check
FAUSheppy Feb 4, 2021
b2fcb47
update to major version 4.25
FAUSheppy Feb 4, 2021
b49dc5b
Update version numbers
FAUSheppy Feb 4, 2021
084d950
Merge Fix_async_callback_order-of-operations_bug
FAUSheppy Feb 4, 2021
afe9278
Merge Inner-margin-ClampLocationToNavigableWorld
FAUSheppy Feb 4, 2021
247aab5
cleanup/update readme
FAUSheppy Feb 4, 2021
ad724d4
update readme with new tutorial link
FAUSheppy Apr 1, 2021
ea81d00
update version
FAUSheppy May 31, 2021
9819f25
bEnableShadowVariableWarnings is deprecated
FAUSheppy Oct 3, 2021
991b9b3
Update to engine version 4.27
FAUSheppy Dec 15, 2021
27f9249
Update Engine Version to 4.27
FAUSheppy Feb 19, 2022
9a4b0a5
Merge branch 'master' of github.com:FAUSheppy/DonAINavigation
FAUSheppy Feb 19, 2022
659c3ff
Collapse multiline (UE5 does not support it)
FAUSheppy Feb 19, 2022
674d2ea
Add note about UE5 support
FAUSheppy Feb 20, 2022
dc3add0
typo
FAUSheppy Feb 20, 2022
2968da9
Adds support for Unbound manager and timeout cancel in FindPathSoluti…
tayl74 Jul 11, 2022
009ab1e
Merge pull request #1 from tayl74/master
FAUSheppy Aug 14, 2022
3fc84f9
fix: remove UE-5.1deprecated win32 platfrom
FAUSheppy Jan 25, 2023
8d436f8
fix: unreachable return & ambigious call for ue_5.4
FAUSheppy Sep 13, 2024
1d59150
chore: bump version to 5.4
FAUSheppy Sep 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
Binaries/
Intermediate/

# Folder config file
Desktop.ini
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed Binaries/Win64/UE4Editor-DonAINavigation.dll
Binary file not shown.
Binary file removed Binaries/Win64/UE4Editor-DonAINavigation.pdb
Binary file not shown.
7 changes: 0 additions & 7 deletions Binaries/Win64/UE4Editor.modules

This file was deleted.

13 changes: 4 additions & 9 deletions DonAINavigation.uplugin
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
{
"FileVersion" : 3,
"FriendlyName" : "DoN AI Navigation Plugin (Flying AI /3D Aerial Pathfinding)",
"Version" : 10,
"VersionName" : "1.10",
"EngineVersion" : "4.19.0",
"Version" : 11,
"VersionName" : "1.12",
"EngineVersion" : "5.4.0",
"Category" : "AI Navigation",
"CreatedBy" : "Venugopalan Sreedharan",
"CreatedByURL" : "http://www.drunkonnectar.com/3d-pathfinding-ue4/",
"Description" : "This plugin is a solution for 3D pathfinding for flying creatures.

It uses voxel based navigation, supports dynamic collision updates and comes with a behavior tree task 'Fly to' which you may directly use in your behavior trees.

Also provided is an API with pathfinding functions for custom navigation queries",
"Description" : "This plugin is a solution for 3D pathfinding for flying creatures. It uses voxel based navigation, supports dynamic collision updates and comes with a behavior tree task 'Fly to' which you may directly use in your behavior trees. Also provided is an API with pathfinding functions for custom navigation queries",
"MarketplaceURL" : "com.epicgames.launcher://ue/marketplace/content/81b4bd085c8c41508edfeb160b6ddf62",
"SupportURL" : "https://forums.unrealengine.com/showthread.php?102933-DoN-s-3D-Pathfinding-Flying-AI-system-(with-full-source!)/",
"DocsURL" : "https://www.youtube.com/watch?v=6Tr_K551zvI",
Expand All @@ -26,7 +22,6 @@
"WhitelistPlatforms" :
[
"Win64",
"Win32",
"Linux"
]
}
Expand Down
33 changes: 10 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
=============================================
DoN AI Navigation Plugin for Unreal Engine 4
=============================================
# DoN AI Navigation Plugin for Unreal Engine 4
This plugin provides a 3D dynamic pathfinding system for use with Unreal Engine 4 **(UE5 should work too now, if not open an Issue)**. This system was first developed for [DoN The Nature Game](http://www.drunkonnectar.com/) and the owner decided to make a plugin out of the navigation module as a gift to the Unreal community. He abandoned the project some years back and I started to collect various fixes and pull requests after I updated it to the current version.

This plugin provides a 3D dynamic pathfinding system for use with Unreal Engine 4. This system was first developed for my game [DoN The Nature Game](http://www.drunkonnectar.com/) and I decided to make a plugin out of the navigation module as a gift to the Unreal community.

It's primarly designed for Flying AI creatures based in dynamic or procedural worlds that need to solve complex pathfinding tasks and other behavior that cannot be readily solved by Unreal's native AI navigation system and also for maps that are too complex to be solved by simple ray-tracing/sweeping heuristics or by waypoint systems.
The plugin is primarly designed for Flying AIs based in dynamic or procedural worlds, which need to solve complex pathfinding tasks and other behavior not covered by Unreal's native AI navigation system or maps, which are too complex to be solved by simple ray-tracing/sweeping heuristics or a waypoint system.

Where possible, I recommend that you use Unreal's native AI navigation or simpler navigation strategies; use this system when the more conventional strategies cannot solve your pathfinding usecases.

Expand All @@ -14,23 +11,13 @@ The plugin provides the following:
* Nodes for managing dynamic collision and pathfinding in your scene.
* A pathfinding API that advanced users can use for custom navigation queries from either Blueprints or C++

=============================================
Download Sample Project
=============================================
I've created a sample project for you to quickly test the system and understand the different usecases it covers.

Please visit the following page to grab it:

http://www.drunkonnectar.com/3d-pathfinding-ue4/
# Sample Project
There is still is an old [sample project](http://www.drunkonnectar.com/3d-pathfinding-ue4/) to quickly test the system and understand the different usecases it covers.

=============================================
Overview and Tutorial
=============================================
[![Youtube video - Overview and Tutorial](http://www.drunkonnectar.com/wp-content/uploads/2016/03/ThumbnailWithYoutubeIcon.jpg)](https://www.youtube.com/watch?v=6Tr_K551zvI)
# Overviews and Tutorials
* [Article describing how to build the plugin from source and apply a basic use case](https://medium.com/anti-clickbait-coalition/3d-pathfinding-in-unreal-engine-9b04f58ca50c?source=friends_link&sk=aeb7269c3c85841f87bb7ca99658c176)
* [![Youtube video - Overview and Tutorial](http://www.drunkonnectar.com/wp-content/uploads/2016/03/ThumbnailWithYoutubeIcon.jpg)](https://www.youtube.com/watch?v=6Tr_K551zvI)

=============================================
Technical Overview
=============================================
For a technical overview of the project, please visit this link:<br>
http://www.drunkonnectar.com/3d-pathfinding-ue4/#TechnicalOverview
# Technical Overview
For a technical overview of the project, please visit this [link](http://www.drunkonnectar.com/3d-pathfinding-ue4/#TechnicalOverview)

4 changes: 2 additions & 2 deletions Source/DonAINavigation/Classes/DonNavigationCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <vector>

#if PLATFORM_WINDOWS
#include "AllowWindowsPlatformTypes.h"
#include "Windows/AllowWindowsPlatformTypes.h"
#elif PLATFORM_XBOXONE
#include "XboxOneAllowPlatformTypes.h"
#endif
Expand Down Expand Up @@ -95,5 +95,5 @@ namespace DoNNavigation
}

#if PLATFORM_WINDOWS
#include "HideWindowsPlatformTypes.h"
#include "Windows/HideWindowsPlatformTypes.h"
#endif
15 changes: 9 additions & 6 deletions Source/DonAINavigation/Classes/DonNavigationManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "Multithreading/DonDrawDebugThreadSafe.h"
#include "CollisionQueryParams.h"
#include "WorldCollision.h"
#include "Queue.h"
#include "Containers/Queue.h"
#include "Components/BoxComponent.h"

#include "DonNavigationManager.generated.h"
Expand Down Expand Up @@ -998,17 +998,20 @@ class DONAINAVIGATION_API ADonNavigationManager : public AActor
return VolumeAtSafe(x, y, z);
}

/* Clamps a vector to the navigation bounds as defined by the grid configuration of the navigation object you've placed in the map*/
/** Clamps a vector within the navigation bounds, as defined by the grid configuration of the navigation object you've placed in the map,
* brought in by a margin of InnerMarginOffset when clamping downward to prevent rounding errors */
UFUNCTION(BlueprintPure, Category = "DoN Navigation")
FVector ClampLocationToNavigableWorld(FVector DesiredLocation)
FVector ClampLocationToNavigableWorld(FVector DesiredLocation, float InnerMarginOffset = 0.001f)
{
if (bIsUnbound)
return DesiredLocation;

FVector origin = GetActorLocation();
float xClamped = FMath::Clamp(DesiredLocation.X, origin.X, origin.X + XGridSize * VoxelSize);
float yClamped = FMath::Clamp(DesiredLocation.Y, origin.Y, origin.Y + YGridSize * VoxelSize);
float zClamped = FMath::Clamp(DesiredLocation.Z, origin.Z, origin.Z + ZGridSize * VoxelSize);
// When clamping down, bring the vector in by an extra InnerMarginOffset cm. Necessary because VolumeIdAt does a float-to-int rounding, and thus clamping
// to a max world dimension would otherwise round to an invalid index (e.g. rounding 100.5 to invalid index 100 instead of 99 in a 100-voxel world)
float xClamped = FMath::Clamp(DesiredLocation.X, origin.X, origin.X + XGridSize * VoxelSize - InnerMarginOffset);
float yClamped = FMath::Clamp(DesiredLocation.Y, origin.Y, origin.Y + YGridSize * VoxelSize - InnerMarginOffset);
float zClamped = FMath::Clamp(DesiredLocation.Z, origin.Z, origin.Z + ZGridSize * VoxelSize - InnerMarginOffset);

return FVector(xClamped, yClamped, zClamped);
}
Expand Down
4 changes: 2 additions & 2 deletions Source/DonAINavigation/DonAINavigation.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class DonAINavigation : ModuleRules
public DonAINavigation(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
bEnableShadowVariableWarnings = false;
ShadowVariableWarningLevel = WarningLevel.Off;

PublicIncludePaths.AddRange(
new string[] {
Expand Down Expand Up @@ -48,4 +48,4 @@ public DonAINavigation(ReadOnlyTargetRules Target) : base(Target)
);
}
}
}
}
20 changes: 15 additions & 5 deletions Source/DonAINavigation/Private/BehaviorTree/BTTask_FlyTo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,26 @@ EBTNodeResult::Type UBTTask_FlyTo::SchedulePathfindingRequest(UBehaviorTreeCompo
LastRequestTimestamps.Add(pawn, currentTime); //LastRequestTimestamp = currentTime;
*/
NavigationManager = UDonNavigationHelper::DonNavigationManagerForActor(pawn);
if (NavigationManager->HasTask(pawn) && !QueryParams.bForceRescheduleQuery)
return EBTNodeResult::Failed; // early exit instead of going through the manager's internal checks and fallback via HandleTaskFailure (which isn't appropriate here)

// Validate internal state:
if (!pawn || !myMemory || !blackboard || !NavigationManager)
{
UE_LOG(DoNNavigationLog, Log, TEXT("BTTask_FlyTo has invalid data for AI Pawn or NodeMemory or NavigationManager. Unable to proceed."));

if(!pawn){
UE_LOG(DoNNavigationLog, Log, TEXT("Pawn invalid"));
}
if(!myMemory){
UE_LOG(DoNNavigationLog, Log, TEXT("NodeMemory invalid"));
}
if(!blackboard){
UE_LOG(DoNNavigationLog, Log, TEXT("Blackboard invalid"));
}
if(!NavigationManager){
UE_LOG(DoNNavigationLog, Log, TEXT("NavigationManager invalid"));
}
return HandleTaskFailure(OwnerComp, NodeMemory, blackboard);
}

if (NavigationManager->HasTask(pawn) && !QueryParams.bForceRescheduleQuery)
return EBTNodeResult::Failed; // early exit instead of going through the manager's internal checks and fallback via HandleTaskFailure (which isn't appropriate here)

// Validate blackboard key data:
if(FlightLocationKey.SelectedKeyType != UBlackboardKeyType_Vector::StaticClass())
Expand Down
103 changes: 57 additions & 46 deletions Source/DonAINavigation/Private/DonNavigationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,8 @@ void ADonNavigationManager::ReceiveAsyncResults()
{
FDonNavigationQueryTask task;
CompletedNavigationTasks.Dequeue(task);
task.BroadcastResult();

ActiveNavigationTaskOwners.Remove(task.Data.Actor.Get());
task.BroadcastResult();

#if DEBUG_DoNAI_THREADS
auto owner = task.Data.Actor.Get();
Expand Down Expand Up @@ -284,7 +283,7 @@ void ADonNavigationManager::OnConstruction(const FTransform& Transform)
#if WITH_EDITOR
void ADonNavigationManager::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
UProperty* PropertyThatChanged = PropertyChangedEvent.Property;
FProperty* PropertyThatChanged = PropertyChangedEvent.Property;
FName PropertyName = PropertyThatChanged != NULL ? PropertyThatChanged->GetFName() : NAME_None;

if (PropertyName == GET_MEMBER_NAME_CHECKED(ADonNavigationManager, bDisplayWorldBoundary))
Expand Down Expand Up @@ -774,12 +773,9 @@ bool ADonNavigationManager::ScheduleDynamicCollisionUpdate(UPrimitiveComponent*
if(bNeedsToScheduleTask)
AddDynamicCollisionTask(task);

return bOverallStatus;

UE_LOG(DoNNavigationLog, Verbose, TEXT("Num collision tasks: %d"), ActiveDynamicCollisionTasks.Num());

return true;

return bOverallStatus;
}

bool ADonNavigationManager::IsDynamicCollisionTaskActive(const FDonNavigationDynamicCollisionTask& Task)
Expand Down Expand Up @@ -1951,10 +1947,10 @@ bool ADonNavigationManager::FindPathSolution_StressTesting(AActor* Actor, FVecto
// Input Validations - I
if (!Actor || !CollisionComponent)
{
FString actorLog = Actor ? *Actor->GetName() : *FString("Invalid");
FString collisionComponentLog = CollisionComponent ? *CollisionComponent->GetName() : *FString("Invalid");
FString actorLog = Actor ? *Actor->GetName() : *FString("Invalid");
FString collisionComponentLog = CollisionComponent ? *CollisionComponent->GetName() : *FString("Invalid");
UE_LOG(DoNNavigationLog, Error, TEXT("%s"), *FString::Printf(TEXT("Invalid input parameters received. Actor: %s CollisionComponent: %s"), *actorLog, *collisionComponentLog));

return false;
}

Expand All @@ -1977,39 +1973,62 @@ bool ADonNavigationManager::FindPathSolution_StressTesting(AActor* Actor, FVecto
// Input Visualization - I
if (DebugParams.DrawDebugVolumes)
{
DrawDebugPoint_Safe(GetWorld(), Origin, 20.f, FColor::White, true, -1.f);
DrawDebugPoint_Safe(GetWorld(), Origin, 20.f, FColor::White, true, -1.f);
DrawDebugPoint_Safe(GetWorld(), Destination, 20.f, FColor::Green, true, -1.f);
}

uint64 timerVolumeResolution = DoNNavigation::Debug_GetTimer();

// Resolve origin and destination volumes
auto originVolume = ResolveVolume(Origin, CollisionComponent, QueryParams.bFlexibleOriginGoal, QueryParams.CollisionShapeInflation);
auto destinationVolume = ResolveVolume(Destination, CollisionComponent, QueryParams.bFlexibleOriginGoal, QueryParams.CollisionShapeInflation);
FDonNavigationVoxel* originVolume = NULL;
FDonNavigationVoxel* destinationVolume = NULL;

FVector resolvedOriginCenter = VolumeOriginAt(Origin);
FVector resolvedDestinationCenter = VolumeOriginAt(Destination);

bool bResolvedOrigin = false;
bool bResolvedDestination = false;

if (!bIsUnbound)
{
// Resolve origin and destination volumes
originVolume = ResolveVolume(Origin, CollisionComponent, QueryParams.bFlexibleOriginGoal, QueryParams.CollisionShapeInflation);
destinationVolume = ResolveVolume(Destination, CollisionComponent, QueryParams.bFlexibleOriginGoal, QueryParams.CollisionShapeInflation);

DoNNavigation::Debug_StopTimer(timerVolumeResolution);
UE_LOG(DoNNavigationLog, Verbose, TEXT("%s"), *FString::Printf(TEXT("Time spent resolving origin and destination volumes - %f seconds"), timerVolumeResolution / 1000.0));
// Input Visualization - II
if (DebugParams.DrawDebugVolumes)
{
if (originVolume)
DrawDebugVoxel_Safe(GetWorld(), originVolume->Location, NavVolumeExtent(), FColor::White, false, 0.13f, 0, DebugVoxelsLineThickness);

if (destinationVolume)
DrawDebugVoxel_Safe(GetWorld(), destinationVolume->Location, NavVolumeExtent(), FColor::Green, false, 0.13f, 0, DebugVoxelsLineThickness);
}
}
else
{
bResolvedOrigin = ResolveVector(Origin, resolvedOriginCenter, CollisionComponent, QueryParams.bFlexibleOriginGoal, QueryParams.CollisionShapeInflation);
bResolvedDestination = ResolveVector(Destination, resolvedDestinationCenter, CollisionComponent, QueryParams.bFlexibleOriginGoal, QueryParams.CollisionShapeInflation);
}

// Input Validations - II
if (!originVolume || !destinationVolume)
if ((!bIsUnbound && (!originVolume || !destinationVolume)) || (bIsUnbound && (!bResolvedOrigin || !bResolvedDestination)))
{
InvalidVolumeErrorLog(originVolume, destinationVolume, Origin, Destination);

return false;
}
else

// Flexible Origin adaptation:
if (Origin != Actor->GetActorLocation())
{
if (Origin != Actor->GetActorLocation())
{
UE_LOG(DoNNavigationLog, Warning, TEXT("Forcibly shifting %s's pathfinding origin to new origin %s for viable pathfinding. (Can be disabled in QueryParams)"), *Actor->GetName());
Actor->SetActorLocation(Origin, false); // New design: We no longer teleport the pawn. If all our calculations have gone right the pawn should be free to travel to the new origin.
}
UE_LOG(DoNNavigationLog, Warning, TEXT("Forcibly moving %s to new origin for viable pathfinding. (Can be disabled in QueryParams)"), *Actor->GetName());
Actor->SetActorLocation(Origin, false);
}

// Input Visualization - II
if (DebugParams.DrawDebugVolumes)
{
DrawDebugVoxel_Safe(GetWorld(), originVolume->Location, NavVolumeExtent(), FColor::White, false, 0.13f, 0, DebugVoxelsLineThickness);
DrawDebugVoxel_Safe(GetWorld(), originVolume->Location, NavVolumeExtent(), FColor::White, false, 0.13f, 0, DebugVoxelsLineThickness);
DrawDebugVoxel_Safe(GetWorld(), destinationVolume->Location, NavVolumeExtent(), FColor::Green, false, 0.13f, 0, DebugVoxelsLineThickness);
}

Expand All @@ -2019,31 +2038,22 @@ bool ADonNavigationManager::FindPathSolution_StressTesting(AActor* Actor, FVecto
auto voxelCollisionProfile = GetVoxelCollisionProfileFromMesh(FDonMeshIdentifier(CollisionComponent), bResultIsValid, VoxelCollisionProfileCache_GameThread, bIgnoreMeshOriginOccupancy);

uint64 timerPathfinding = DoNNavigation::Debug_GetTimer();

FDonNavigationQueryTask synchronousTask = FDonNavigationQueryTask(
FDoNNavigationQueryData(Actor, CollisionComponent, Origin, Destination, QueryParams, DebugParams, originVolume, destinationVolume, originVolume->Location, destinationVolume->Location, voxelCollisionProfile),
FDoNNavigationQueryData(Actor, CollisionComponent, Origin, Destination, QueryParams, DebugParams, originVolume, destinationVolume, resolvedOriginCenter, resolvedDestinationCenter, voxelCollisionProfile),
FDoNNavigationResultHandler(),
FDonNavigationDynamicCollisionDelegate()
);
);

auto& data = synchronousTask.Data;

float timeSpend = 0;
// Core pathfinding algorithm
while (!data.Frontier.empty())
while (!data.bGoalFound && timeSpend <= QueryParams.QueryTimeout)
{
auto currentVolume = data.Frontier.get(); // the current volume is the "best neighbor" (highest priority) of the previous volume

if (currentVolume == destinationVolume)
{
data.bGoalFound = true;
break;
}

const auto& neighbors = FindOrSetupNeighborsForVolume(currentVolume);
for (auto neighbor : neighbors)
{
ExpandFrontierTowardsTarget(synchronousTask, currentVolume, neighbor);
}
uint64 timeoutTimer = DoNNavigation::Debug_GetTimer();
TickNavigationSolver(synchronousTask);
DoNNavigation::Debug_StopTimer(timeoutTimer);
timeSpend += timeoutTimer / 1000.0;
}

// Goal validation:
Expand All @@ -2056,15 +2066,16 @@ bool ADonNavigationManager::FindPathSolution_StressTesting(AActor* Actor, FVecto
}

// Translate volume path solution to vector path solution:
TArray<FDonNavigationVoxel*> volumeSolution;
data.bGoalFound = PathSolutionFromVolumeTrajectoryMap(originVolume, destinationVolume, data.VolumeVsGoalTrajectoryMap, volumeSolution, PathSolutionRaw, Origin, Destination, DebugParams);

data.bGoalFound = PrepareSolution(synchronousTask);
if (!data.bGoalFound)
{
UE_LOG(DoNNavigationLog, Error, TEXT("%s"), *FString::Printf(TEXT("Goal not found among %d goal trajectory nodes"), data.VolumeVsGoalTrajectoryMap.Num()));

return false;
}


PathSolutionRaw.Append(data.PathSolutionRaw);//synchronousTask.PathSolutionRaw.Num());
// Log time spent:
DoNNavigation::Debug_StopTimer(timerPathfinding);
FString calcTime1 = FString::Printf(TEXT("[DoN Navigation]Time spent calculating best path volumes - %f seconds"), timerPathfinding / 1000.0);
Expand Down Expand Up @@ -2836,7 +2847,7 @@ FVector ADonNavigationManager::FindRandomPointAroundOriginInNavWorld(AActor* Nav
for (int32 i = 0; i < MaxAttempts; i++)
{
float maxZAngularDispacement = FMath::Abs(MaxZAngularDispacement);
FRotator newDirection = FRotator(FMath::FRandRange(-maxZAngularDispacement, maxZAngularDispacement), FMath::FRandRange(0, 360), FMath::FRandRange(0, 360));
FRotator newDirection = FRotator(FMath::FRandRange(-maxZAngularDispacement, maxZAngularDispacement), FMath::FRandRange(0.0, 360.0), FMath::FRandRange(0.0, 360.0));
newDestination = Origin + newDirection.RotateVector(baseDisplacement);

if (MaxDesiredAltitude != -1.f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "DonEnvQueryTest_Navigation.h"
#include "EnvironmentQuery/DonEnvQueryTest_Navigation.h"
#include "../DonAINavigationPrivatePCH.h"

#include "DonNavigationManager.h"
Expand Down
Loading