Space Plunder
Loading...
Searching...
No Matches
FOptimizationThread Class Reference

#include <OptimizationManager.h>

Inheritance diagram for FOptimizationThread:

Public Member Functions

 FOptimizationThread (UWorld *World, class FOptimizationManager *InManager)
 
virtual uint32 Run () override
 
virtual void Exit () override
 
virtual void AddReferencedObjects (FReferenceCollector &Collector) override
 
virtual FString GetReferencerName () const override
 
void RegisterComponent (UOptimizationProxyComponent *Component)
 
void UnregisterComponent (const UOptimizationProxyComponent *Component)
 
void HandlePostGarbageCollect ()
 

Protected Attributes

TArray< TObjectPtr< UOptimizationProxyComponent > > Components
 
FCriticalSection Mutex
 
FCriticalSection ProxyMutex
 
TUniquePtr< FRunnableThread > Thread
 
FThreadSafeBool bIsRunning = true
 
TObjectPtr< UWorld > GameWorld = nullptr
 
TObjectPtr< FOptimizationManagerManager = nullptr
 

Private Member Functions

void RemoveComponentByHandle (int32 Handle)
 

Static Private Member Functions

static EOptimizationWave GetOptimizationWave (const APawn *LocalPlayer, const APlayerCameraManager *Camera, IOptimizationProxy *Proxy, bool IsVisible)
 
static bool IsInCameraSight (const APlayerCameraManager *Camera, const APawn *LocalPlayer, IOptimizationProxy *Proxy, float InFOV)
 

Constructor & Destructor Documentation

◆ FOptimizationThread()

FOptimizationThread::FOptimizationThread ( UWorld * World,
class FOptimizationManager * InManager )
40 : bIsRunning(true), GameWorld(World), Manager(InManager)
41{
42 if (IsValid(GameWorld) /*&& GameWorld->GetNetMode() != NM_DedicatedServer*/)
43 {
44 Thread.Reset(FRunnableThread::Create(this, *FString::Printf(TEXT("NPC_Optimizator_Thread_%s"), *GameWorld->GetName())));
45 }
46}
TObjectPtr< FOptimizationManager > Manager
Definition OptimizationManager.h:51
FThreadSafeBool bIsRunning
Definition OptimizationManager.h:49
TObjectPtr< UWorld > GameWorld
Definition OptimizationManager.h:50
TUniquePtr< FRunnableThread > Thread
Definition OptimizationManager.h:48

Member Function Documentation

◆ AddReferencedObjects()

void FOptimizationThread::AddReferencedObjects ( FReferenceCollector & Collector)
overridevirtual
139{
140 Collector.AddReferencedObject(GameWorld);
141
142 for (auto& it : Components)
143 {
144 Collector.AddReferencedObject(it);
145 }
146}
TArray< TObjectPtr< UOptimizationProxyComponent > > Components
Definition OptimizationManager.h:44

◆ Exit()

void FOptimizationThread::Exit ( )
overridevirtual
133{
134 Manager = nullptr;
135 bIsRunning = false;
136}

◆ GetOptimizationWave()

EOptimizationWave FOptimizationThread::GetOptimizationWave ( const APawn * LocalPlayer,
const APlayerCameraManager * Camera,
IOptimizationProxy * Proxy,
bool IsVisible )
staticprivate
237{
238 if (!IsVisible && !Proxy->IsIgnoreCameraSightOnSmallDistance())
239 {
240 return EOptimizationWave::Invisible;
241 }
242
243 float DistToPlayer = 10000.f;
244
245 if (LocalPlayer)
246 {
247 DistToPlayer = FVector::Distance(LocalPlayer->GetActorLocation(), Proxy->GetOwnerActor()->GetActorLocation());
248 }
249
250 if (Camera && Proxy->GetOptimizationBasedType() == EOptimizationBaseType::PlayerCamera)
251 {
252 const FVector CameraLocation = Camera->GetCameraLocation();
253 DistToPlayer = FVector::Distance(CameraLocation, Proxy->GetOwnerActor()->GetActorLocation());
254 }
255
256 if (!IsVisible && Proxy->IsIgnoreCameraSightOnSmallDistance() )
257 {
258 if (DistToPlayer < Proxy->GetDistToWave(EOptimizationWave::FirstWave))
259 {
260 return EOptimizationWave::NoOptimization;
261 }
262 else
263 {
264 return EOptimizationWave::Invisible;
265 }
266 }
267
268 if (DistToPlayer < Proxy->GetDistToWave(EOptimizationWave::FirstWave))
269 {
270 return EOptimizationWave::NoOptimization;
271 }
272 else if (DistToPlayer >= Proxy->GetDistToWave(EOptimizationWave::FirstWave) && DistToPlayer < Proxy->GetDistToWave(EOptimizationWave::SecondWave))
273 {
274 return EOptimizationWave::FirstWave;
275 }
276 else if (DistToPlayer >= Proxy->GetDistToWave(EOptimizationWave::SecondWave) && DistToPlayer < Proxy->GetDistToWave(EOptimizationWave::ThirdWave))
277 {
278 return EOptimizationWave::SecondWave;
279 }
280 else if (DistToPlayer >= Proxy->GetDistToWave(EOptimizationWave::ThirdWave) && DistToPlayer < Proxy->GetMaxVisibleDistance())
281 {
282 return EOptimizationWave::ThirdWave;
283 }
284
285 return EOptimizationWave::Invisible;
286}
virtual bool IsIgnoreCameraSightOnSmallDistance() const =0
virtual float GetDistToWave(EOptimizationWave Wave) const =0
virtual AActor * GetOwnerActor()=0
virtual EOptimizationBaseType GetOptimizationBasedType() const =0

◆ GetReferencerName()

FString FOptimizationThread::GetReferencerName ( ) const
overridevirtual
149{
150 return TEXT("FOptimizationThread");
151}

◆ HandlePostGarbageCollect()

void FOptimizationThread::HandlePostGarbageCollect ( )
185{
186 Mutex.Lock();
187 {
188 bool bRemoved;
189 do
190 {
191 bRemoved = false;
192 for (int32 DataIndex = 0; DataIndex < Components.Num(); ++DataIndex)
193 {
194 if (!IsValid(Components[DataIndex]))
195 {
196 RemoveComponentByHandle(DataIndex);
197 bRemoved = true;
198 }
199 }
200 } while (bRemoved);
201 }
202 Mutex.Unlock();
203}
void RemoveComponentByHandle(int32 Handle)
Definition OptimizationManager.cpp:288
FCriticalSection Mutex
Definition OptimizationManager.h:46

◆ IsInCameraSight()

bool FOptimizationThread::IsInCameraSight ( const APlayerCameraManager * Camera,
const APawn * LocalPlayer,
IOptimizationProxy * Proxy,
float InFOV )
staticprivate
206{
207 if (IsValid(Camera) && Proxy != nullptr)
208 {
209 float Distance = 10000.f;
210
211 if (Proxy->GetOptimizationBasedType() == EOptimizationBaseType::PlayerCamera)
212 {
213 const FVector CameraLocation = Camera->GetCameraLocation();
214
215 Distance = FVector::Distance(CameraLocation, Proxy->GetOwnerActor()->GetActorLocation());
216 }
217 else if (Proxy->GetOptimizationBasedType() == EOptimizationBaseType::PlayerPawn && LocalPlayer)
218 {
219 Distance = FVector::Distance(LocalPlayer->GetActorLocation(), Proxy->GetOwnerActor()->GetActorLocation());
220 }
221
222 const float CameraDotProd = Camera->GetDotProductTo(Proxy->GetOwnerActor());
223 const float CamAngle = 1.f - (InFOV * 0.01f);
224
225 if (CameraDotProd < CamAngle || Distance > Proxy->GetMaxVisibleDistance())
226 {
227 return false;
228 }
229
230 return true;
231 }
232
233 return true;
234}
virtual float GetMaxVisibleDistance() const =0

◆ RegisterComponent()

void FOptimizationThread::RegisterComponent ( UOptimizationProxyComponent * Component)
154{
155 Mutex.Lock();
156 {
157 check(Component);
158
159 if (Component->GetOptimizationHandle() == INDEX_NONE)
160 {
161 Component->SetOptimizationHandle(Components.Num());
162
163 Components.Add(Component);
164 }
165 }
166 Mutex.Unlock();
167}

◆ RemoveComponentByHandle()

void FOptimizationThread::RemoveComponentByHandle ( int32 Handle)
private
289{
290 if (Components.IsValidIndex(Handle))
291 {
292 if (IsValid(Components[Handle]))
293 {
294 Components[Handle]->SetOptimizationHandle(INDEX_NONE);
295 }
296
297 Components.RemoveAtSwap(Handle, 1, false);
298
299 const int32 NumRemaining = Components.Num();
300 if (NumRemaining > 0 && Handle != NumRemaining)
301 {
302 if (IsValid(Components[Handle]))
303 {
304 Components[Handle]->SetOptimizationHandle(Handle);
305 }
306 }
307 }
308}

◆ Run()

uint32 FOptimizationThread::Run ( )
overridevirtual
49{
50 while (bIsRunning)
51 {
52 SCOPE_CYCLE_COUNTER(STAT_OptimizationThreadTick);
53 if(GameWorld == nullptr){return 0;}
54 APlayerCameraManager* PlayerCamera = UGameplayStatics::GetPlayerCameraManager(GameWorld, 0);
55 APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GameWorld, 0);
56 APawn* PlayerPawn = PlayerController ? PlayerController->GetPawn() : nullptr;
57
58 SET_DWORD_STAT(STAT_NPC_Count, 0);
59 SET_DWORD_STAT(STAT_InvisibleCount, 0);
60 SET_DWORD_STAT(STAT_NoOptimizedCount, 0);
61 SET_DWORD_STAT(Stat_FirstWaveCount, 0);
62 SET_DWORD_STAT(Stat_SecondWaveCount, 0);
63 SET_DWORD_STAT(Stat_ThirdWaveCount, 0);
64
65 const float FOV = CVarMaxFOV.GetValueOnAnyThread();
66
67 // Calculate visible & optimization waves for proxy components
68 Mutex.Lock();
69 {
70 SCOPE_CYCLE_COUNTER(STAT_OptimizationComponentsTick);
71
72 const uint32 MaxOptimizedInOneFrame = CVarMaxOptimizationOnOneFrame.GetValueOnAnyThread();
73 uint32 OptimizedCount = 0;
74
75 for (auto& it : Components)
76 {
77 if (!IsValid(it))
78 continue;
79
80 const EOptimizationWave CurrentWave = it->GetOptimizationWave();
81
82 INC_DWORD_STAT(STAT_NPC_Count);
83
84 // Stats counters
85 {
86 switch (CurrentWave)
87 {
88 case EOptimizationWave::Invisible:
89 INC_DWORD_STAT(STAT_InvisibleCount);
90 break;
91 case EOptimizationWave::NoOptimization:
92 INC_DWORD_STAT(STAT_NoOptimizedCount);
93 break;
94 case EOptimizationWave::FirstWave:
95 INC_DWORD_STAT(Stat_FirstWaveCount);
96 break;
97 case EOptimizationWave::SecondWave:
98 INC_DWORD_STAT(Stat_SecondWaveCount);
99 break;
100 case EOptimizationWave::ThirdWave:
101 INC_DWORD_STAT(Stat_ThirdWaveCount);
102 break;
103 }
104 }
105
106 if (it->IsNeedToBeOptimized())
107 continue;
108
109 if (OptimizedCount >= MaxOptimizedInOneFrame)
110 break;
111
112 const bool IsVisible = it->IgnoreCameraSight ? true : IsInCameraSight(PlayerCamera, PlayerPawn, it, FOV);
113 const EOptimizationWave NewWave = GetOptimizationWave(PlayerPawn, PlayerCamera, it, IsVisible);
114
115 if (CurrentWave != NewWave && !it->IsForceOptimizationWaveEnabled())
116 {
117 it->SetOptimizationWave(NewWave);
118 it->SetIsNeedToBeOptimized(true);
119
120 OptimizedCount++;
121 }
122 }
123 }
124 Mutex.Unlock();
125
126 FPlatformProcess::Sleep(0.01f);
127 }
128
129 return 0;
130}
EOptimizationWave
Definition NPC_Optimizator_Types.h:12
static TAutoConsoleVariable< float > CVarMaxFOV(TEXT("npc.optimizator.fov"), 90.f, TEXT("Camera FOV for checking NPCs in frame\n"), ECVF_Scalability)
static TAutoConsoleVariable< int32 > CVarMaxOptimizationOnOneFrame(TEXT("npc.optimizator.MaxOptimizedOnOneFrame"), 15, TEXT("How many NPC can be optimizated in one frame\n"), ECVF_Scalability)
static bool IsInCameraSight(const APlayerCameraManager *Camera, const APawn *LocalPlayer, IOptimizationProxy *Proxy, float InFOV)
Definition OptimizationManager.cpp:205
static EOptimizationWave GetOptimizationWave(const APawn *LocalPlayer, const APlayerCameraManager *Camera, IOptimizationProxy *Proxy, bool IsVisible)
Definition OptimizationManager.cpp:236

◆ UnregisterComponent()

void FOptimizationThread::UnregisterComponent ( const UOptimizationProxyComponent * Component)
170{
171 Mutex.Lock();
172 {
173 check(Component);
174
175 const int32 Handle = Component->GetOptimizationHandle();
176 if (Handle != INDEX_NONE)
177 {
179 }
180 }
181 Mutex.Unlock();
182}

Member Data Documentation

◆ bIsRunning

FThreadSafeBool FOptimizationThread::bIsRunning = true
protected

◆ Components

TArray<TObjectPtr<UOptimizationProxyComponent> > FOptimizationThread::Components
protected

◆ GameWorld

TObjectPtr<UWorld> FOptimizationThread::GameWorld = nullptr
protected

◆ Manager

TObjectPtr<FOptimizationManager> FOptimizationThread::Manager = nullptr
protected

◆ Mutex

FCriticalSection FOptimizationThread::Mutex
mutableprotected

◆ ProxyMutex

FCriticalSection FOptimizationThread::ProxyMutex
mutableprotected

◆ Thread

TUniquePtr<FRunnableThread> FOptimizationThread::Thread
protected

The documentation for this class was generated from the following files: