Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Saved/
*.sln
*.suo
*.xcodeproj
.vs/
75 changes: 43 additions & 32 deletions Config/DefaultEngine.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,6 @@
UIScaleCurve=(EditorCurveData=(Keys=((Time=480,Value=0.444),(Time=720,Value=0.666),(Time=1080,Value=1.0),(Time=8640,Value=8.0))),ExternalCurve=None)
UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=8.000000))),ExternalCurve=None)

[/Script/Engine.RendererSettings]
r.MobileHDR=True
r.AllowOcclusionQueries=True
r.MinScreenRadiusForLights=0.030000
r.MinScreenRadiusForDepthPrepass=0.030000
r.PrecomputedVisibilityWarning=False
r.TextureStreaming=True
Compat.UseDXT5NormalMaps=False
r.AllowStaticLighting=True
r.NormalMapsForStaticLighting=False
r.GBuffer=True
r.GenerateMeshDistanceFields=False
r.Shadow.DistanceFieldPenumbraSize=0.050000
r.TessellationAdaptivePixelsPerTriangle=48.000000
r.SeparateTranslucency=True
r.CustomDepth=1
r.DefaultFeature.Bloom=True
r.DefaultFeature.AmbientOcclusion=True
r.DefaultFeature.AmbientOcclusionStaticFraction=True
r.DefaultFeature.AutoExposure=True
r.DefaultFeature.MotionBlur=True
r.DefaultFeature.LensFlare=True
r.DefaultFeature.AntiAliasing=2
r.EarlyZPass=3
r.EarlyZPassMovable=False
r.DBuffer=False
r.ClearSceneMethod=1
r.MSAA.CompositingSampleCount=2
r.WireframeCullThreshold=5.000000
UIScaleRule=ShortestSide
UIScaleCurve=(EditorCurveData=(Keys=),ExternalCurve=None)

[/Script/HardwareTargeting.HardwareTargetingSettings]
TargetedHardwareClass=Desktop
AppliedTargetedHardwareClass=Desktop
Expand All @@ -65,4 +33,47 @@ ServerDefaultMap=/Engine/Maps/Entry
GlobalDefaultGameMode=/Game/Blueprints/MyGameMode.MyGameMode_C
GlobalDefaultServerGameMode=None

[/Script/Engine.PhysicsSettings]
DefaultGravityZ=-980.000000
DefaultTerminalVelocity=4000.000000
DefaultFluidFriction=0.300000
SimulateScratchMemorySize=262144
RagdollAggregateThreshold=4
TriangleMeshTriangleMinAreaThreshold=5.000000
bEnableShapeSharing=False
bEnablePCM=True
bEnableStabilization=False
bWarnMissingLocks=True
bEnable2DPhysics=False
PhysicErrorCorrection=(PingExtrapolation=0.100000,PingLimit=100.000000,ErrorPerLinearDifference=1.000000,ErrorPerAngularDifference=1.000000,MaxRestoredStateError=1.000000,MaxLinearHardSnapDistance=400.000000,PositionLerp=0.000000,AngleLerp=0.400000,LinearVelocityCoefficient=100.000000,AngularVelocityCoefficient=10.000000,ErrorAccumulationSeconds=0.500000,ErrorAccumulationDistanceSq=15.000000,ErrorAccumulationSimilarity=100.000000)
LockedAxis=Invalid
DefaultDegreesOfFreedom=Full3D
BounceThresholdVelocity=200.000000
FrictionCombineMode=Average
RestitutionCombineMode=Average
MaxAngularVelocity=3600.000000
MaxDepenetrationVelocity=0.000000
ContactOffsetMultiplier=0.020000
MinContactOffset=2.000000
MaxContactOffset=8.000000
bSimulateSkeletalMeshOnDedicatedServer=True
DefaultShapeComplexity=CTF_UseSimpleAndComplex
bDefaultHasComplexCollision=True
bSuppressFaceRemapTable=False
bSupportUVFromHitResults=False
bDisableActiveActors=False
bDisableKinematicStaticPairs=False
bDisableKinematicKinematicPairs=False
bDisableCCD=False
bEnableEnhancedDeterminism=False
MaxPhysicsDeltaTime=0.033333
bSubstepping=False
bSubsteppingAsync=False
MaxSubstepDeltaTime=0.016667
MaxSubsteps=6
SyncSceneSmoothingFactor=0.000000
InitialAverageFrameRate=0.016667
PhysXTreeRebuildRate=10
DefaultBroadphaseSettings=(bUseMBPOnClient=False,bUseMBPOnServer=False,MBPBounds=(Min=(X=0.000000,Y=0.000000,Z=0.000000),Max=(X=0.000000,Y=0.000000,Z=0.000000),IsValid=0),MBPNumSubdivs=2)


3 changes: 1 addition & 2 deletions Config/DefaultGame.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ LicensingTerms=
PrivacyPolicy=
ProjectID=1D61FE7D544EDE8A25D93CB98BB60D75
ProjectName=FlockAI
ProjectVersion=
ProjectVersion=1.0
SupportContact=parmandorc@gmail.com
ProjectDisplayedTitle=FlockAI


Binary file modified Content/Blueprints/AgentBP.uasset
Binary file not shown.
2 changes: 1 addition & 1 deletion FlockAI.uproject
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"FileVersion": 3,
"EngineAssociation": "4.7",
"EngineAssociation": "4.22",
"Category": "",
"Description": "",
"Modules": [
Expand Down
16 changes: 2 additions & 14 deletions Source/FlockAI.Target.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,9 @@

public class FlockAITarget : TargetRules
{
public FlockAITarget(TargetInfo Target)
public FlockAITarget(TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
}

//
// TargetRules interface.
//

public override void SetupBinaries(
TargetInfo Target,
ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,
ref List<string> OutExtraModuleNames
)
{
OutExtraModuleNames.Add("FlockAI");
ExtraModuleNames.Add("FlockAI");
}
}
6 changes: 4 additions & 2 deletions Source/FlockAI/FlockAI.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

public class FlockAI : ModuleRules
{
public FlockAI(TargetInfo Target)
public FlockAI(ReadOnlyTargetRules Target) : base(Target)
{
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivatePCHHeaderFile = "Public/FlockAI.h";

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
}
}
110 changes: 105 additions & 5 deletions Source/FlockAI/Private/Agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

#include "FlockAI.h"
#include "Agent.h"
#include "Stimulus.h"


AAgent::AAgent()
{
PrimaryActorTick.bCanEverTick = true;

PrimaryActorTick.bStartWithTickEnabled = true;

// Initializing default values
BaseMovementSpeed = 200.0f;
MaxMovementSpeed = 300.0f;
Expand All @@ -25,26 +27,124 @@ AAgent::AAgent()
VisionSphere = CreateDefaultSubobject<USphereComponent>(TEXT("VisionSphere"));
VisionSphere->AttachTo(RootComponent);
VisionSphere->SetSphereRadius(VisionRadius);

InertiaWeigh = 0.0f;
AgentPhysicalRadius = 45.0f;
SeparationWeight = 0.5f;
}

void AAgent::BeginPlay()
{
Super::BeginPlay();

// Initialize move vector
NewMoveVector = GetActorRotation().Vector().GetSafeNormal();
}

void AAgent::ResetComponents()
{
AlignmentComponent = FVector::ZeroVector;
CohesionComponent = FVector::ZeroVector;
SeparationComponent = FVector::ZeroVector;
NegativeStimuliComponent = FVector::ZeroVector;
NegativeStimuliMaxFactor = 0.0f;
PositiveStimuliComponent = FVector::ZeroVector;
PositiveStimuliMaxFactor = 0.0f;
}

void AAgent::DebugComponents()
{
FVector TempVector;
TempVector = AlignmentComponent * AlignmentWeight;
UE_LOG(LogFlockAI, Log, TEXT("Alignment: %s"), *TempVector.ToString());
TempVector = CohesionComponent * CohesionWeight;
UE_LOG(LogFlockAI, Log, TEXT("Cohesion: %s"), *TempVector.ToString());
TempVector = SeparationComponent * SeparationWeight;
UE_LOG(LogFlockAI, Log, TEXT("Separation: %s"), *TempVector.ToString());
UE_LOG(LogFlockAI, Log, TEXT("NegativeStimuli: %s"), *NegativeStimuliComponent.ToString());
UE_LOG(LogFlockAI, Log, TEXT("PositiveStimuli: %s"), *PositiveStimuliComponent.ToString());
}

void AAgent::CalculateNewMoveVector_Implementation()
{
ResetComponents();

FVector ActorLocation = GetActorLocation();

VisionSphere->GetOverlappingActors(Neighbourhood, StaticClass());
// Compute Alignment Component Vector
for (AActor* Actor : Neighbourhood)
{
AAgent* Agent = (AAgent*)Actor;
AlignmentComponent += Agent->CurrentMoveVector.GetSafeNormal();
}
AlignmentComponent.Normalize();
Neighbourhood.Remove(this);
if (Neighbourhood.Num() > 0)
{
// Compute Cohesion Component Vector
for (AActor* Agent : Neighbourhood)
{
CohesionComponent += Agent->GetActorLocation() - ActorLocation;
}
CohesionComponent /= Neighbourhood.Num() * 100.0f;
// Compute Separation Component Vector
for (AActor* Agent : Neighbourhood)
{
FVector SeparationVector = ActorLocation - Agent->GetActorLocation();
SeparationComponent += SeparationVector.GetSafeNormal() / FMath::Abs(SeparationVector.Size() - AgentPhysicalRadius * 2.0f);
}
SeparationComponent *= (1.0f + Neighbourhood.Num() / 5.0f) * 100.0f;
}

TArray<AActor*> StimulusActors;
VisionSphere->GetOverlappingActors(StimulusActors, AStimulus::StaticClass());
for (AActor* Actor : StimulusActors)
{
AStimulus* Stimulus = (AStimulus*)Actor;
FVector StimuliVector = Stimulus->GetActorLocation() - ActorLocation;
if (Stimulus->Value < 0.0f)
{
// Compute Negative Stimuli Component Vector
FVector NegativeStimuliVector = StimuliVector.GetSafeNormal() / FMath::Abs(StimuliVector.Size() - AgentPhysicalRadius) * 100.0f * Stimulus->Value;
NegativeStimuliComponent += NegativeStimuliVector;
NegativeStimuliMaxFactor = FMath::Max(NegativeStimuliMaxFactor, NegativeStimuliVector.Size());
}
else
{
// Compute Positive Stimuli Component Vector
float PositiveStimuliFactor = Stimulus->Value / StimuliVector.Size();
if (PositiveStimuliFactor > PositiveStimuliMaxFactor)
{
PositiveStimuliComponent = StimuliVector.GetSafeNormal() * Stimulus->Value;
PositiveStimuliMaxFactor = PositiveStimuliFactor;
}
}
}
// Compute Aggregation of Components
NegativeStimuliComponent = NegativeStimuliComponent.GetSafeNormal() * NegativeStimuliMaxFactor;
NewMoveVector = NegativeStimuliComponent + PositiveStimuliComponent;
NewMoveVector += AlignmentComponent * AlignmentWeight;
NewMoveVector += CohesionComponent * CohesionWeight;
NewMoveVector += SeparationComponent * SeparationWeight;

//DebugComponents();
}

void AAgent::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);

CurrentMoveVector = NewMoveVector;

CalculateNewMoveVector();

const FVector NewDirection = (NewMoveVector * BaseMovementSpeed * DeltaSeconds).GetClampedToMaxSize(MaxMovementSpeed * DeltaSeconds);
const FRotator NewRotation = NewMoveVector.Rotation();

FHitResult Hit(1.f);
RootComponent->MoveComponent(NewDirection, NewRotation, true, &Hit);

if (Hit.IsValidBlockingHit())
{
const FVector Normal2D = Hit.Normal.GetSafeNormal2D();
Expand Down
55 changes: 38 additions & 17 deletions Source/FlockAI/Public/Agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,84 @@
#include "Agent.generated.h"

/**
*
*
*/
UCLASS()
class FLOCKAI_API AAgent : public AActor
{
GENERATED_BODY()
GENERATED_BODY()

/* The mesh component */
UPROPERTY(Category = Mesh, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
class UStaticMeshComponent* MeshComponent;

/* The collider for the area of vision of the Agent, where it can detect other Agents */
UPROPERTY(Category = AI, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
class USphereComponent* VisionSphere;

public:
AAgent();

/* The weight of the Alignment vector component */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
float AlignmentWeight;

/* The weight of the Cohesion vector component */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
float CohesionWeight;

/* The weight of the Separation vector component */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
float SeparationWeight;

/* The base movement speed for the Agents */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
float BaseMovementSpeed;

/* The maximum movement speed the Agents can have */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
float MaxMovementSpeed;

/* The maximum radius at which the Agent can detect other Agents */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
float VisionRadius;


UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
FVector AlignmentComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
FVector CohesionComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
FVector SeparationComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
FVector NegativeStimuliComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
FVector PositiveStimuliComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
float NegativeStimuliMaxFactor;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
float PositiveStimuliMaxFactor;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
TArray<AActor*> Neighbourhood;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
float InertiaWeigh;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = AI)
float AgentPhysicalRadius;

/* This event is called every tick, before applying the calculated move vector to move the Agent */
UFUNCTION(BlueprintImplementableEvent, Category = AI)
UFUNCTION(BlueprintNativeEvent, Category = AI)
void CalculateNewMoveVector();

void CalculateNewMoveVector_Implementation();

// Begin Actor Interface
virtual void Tick(float DeltaSeconds) override;
virtual void BeginPlay() override;
// End Actor Interface


protected:
void ResetComponents();
void DebugComponents();

protected:
/* The movement vector (in local) this agent should move this tick. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AI)
FVector NewMoveVector;

/* The movement vector (in local) this agent had last tick. */
UPROPERTY(EditAnywhere , BlueprintReadOnly, Category = AI)
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = AI)
FVector CurrentMoveVector;
};
Loading