get rid of SGPawn::Tick, introduce SGPawn::HandVelocitySamplerFramerate, and make hand velocity sampler timer-based instead of tick-based

This commit is contained in:
Mamadou Babaei
2025-11-18 03:18:47 +01:00
parent aa9c5b206f
commit ce1b9f2f98
3 changed files with 57 additions and 10 deletions
+3
View File
@@ -21,6 +21,7 @@ This minor release focuses on delivering performance improvements, made possible
- Added third-party module `SGLogThirdPartyLibs`.
- Added third-party module `SGLoguruThirdPartyLibs`.
- Added third-party module `SGWjwwoodSerialThirdPartyLibs` to replace `SGSerialThirdPartyLibs` while retaining `SGSerialThirdPartyLibs` for a different purpose. See the relevant comment in the Changed section below.
- Added UPROPERTY `SGPawn::HandVelocitySamplerFramerate` to control the hand velocity sampler's timer interval. This allows getting rid of `SGPawn::Tick()` for improved performance and reliability, which also improves chopiness on low frame-rates.
### Fixed
@@ -33,6 +34,7 @@ This minor release focuses on delivering performance improvements, made possible
- As a result of SenseGlove libraries >= `v2.300.0` changing it's directory structure, the `ThirdParty` folder's directory structure has been revamped.
- Renamed third-party module `SGSerialThirdPartyLibs` to `SGWjwwoodSerialThirdPartyLibs` since SenseGlove libraries >= `v2.300.0` ships a new static library named `sgserial`. Thus, to avoid confusion and naming conflicts the third-party `serial` static library is now provided by the `SGWjwwoodSerialThirdPartyLibs` module and `sgserial` is provided by the `SGSerialThirdPartyLibs` module.
- `FSGGloveTrackingSettings::GloveConnectivityCheckInterval` settings have been renamed to `FSGGloveTrackingSettings::DataRetrievalRefreshRate` for adoption other than glove connectivity use cases.
- The hand velocity sampler is now timer-based instead of being tick-based and the update interval is controlled via `SGPawn::HandVelocitySamplerFramerate`.
### Removed
@@ -41,6 +43,7 @@ This minor release focuses on delivering performance improvements, made possible
- Cleaned up remnants of the long-removed Unreal Engine `5.2` from third-party module `*.Build.cs` files.
- Cleaned up remnants of the long-removed Unreal Engine `5.2` from `SenseGlove.Build.cs`, `SenseGloveKismet.Build.cs`, `SenseGloveTracking.Build.cs`, files.
- Cleaned up remnants of the long-removed Unreal Engine `5.2` from `SenseGloveTracking` module.
- `SGPawn::Tick()` is no longer handled in order to improve performance and reliability. The hand velocity sampler is now timer-based instead of being tick-based and the update interval is controlled via `SGPawn::HandVelocitySamplerFramerate`.
### Documentation
@@ -40,6 +40,7 @@
#include "Components/SphereComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "Runtime/Launch/Resources/Version.h"
#include "TimerManager.h"
#include "UObject/UObjectGlobals.h"
#include "XRDeviceVisualizationComponent.h"
@@ -47,8 +48,9 @@
#include "SenseGlove/Components/SGTouchComponent.h"
#include "SenseGlove/Components/SGVirtualHandComponent.h"
#include "SenseGlove/Components/SGWristTrackerComponent.h"
#include "SGSettings/SGSettings.h"
#include "SGBuildHacks/SGPlatform.h"
#include "SGLog/SGLog.h"
#include "SGSettings/SGSettings.h"
struct ASGPawn::FImpl
{
@@ -56,6 +58,12 @@ struct ASGPawn::FImpl
* Static methods
************************/
/************************
* Member variables
************************/
FTimerHandle HandVelocitySamplerTimer;
/************************
* Owner object
************************/
@@ -146,6 +154,7 @@ struct ASGPawn::FImpl
void SetRightHandGrabbedActor(AActor* Actor) const;
void RecordHandVelocity(FSGGrabState& GrabState, const float DeltaSeconds) const;
void StartHandVelocitySamplerTimer();
void Release(FSGGrabState& GrabState) const;
@@ -491,6 +500,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
RightPinkyFingertipTouchCollider->SetCollisionObjectType(ECC_Pawn);
Pimpl->SetFingerColliderCollisionEnabled(RightPinkyFingertipTouchCollider, true);
HandVelocitySamplerFramerate = 60.0f;
MaxNumberOfHandVelocitySamples = 10;
LeftHandGrabState = FSGGrabState{
@@ -577,6 +587,8 @@ void ASGPawn::BeginPlay()
Pimpl->BindFingerGrabOverlapEvents();
Pimpl->BindFingerTouchOverlapEvents();
Pimpl->StartHandVelocitySamplerTimer();
}
void ASGPawn::EndPlay(const EEndPlayReason::Type EndPlayReason)
@@ -589,14 +601,6 @@ void ASGPawn::EndPlay(const EEndPlayReason::Type EndPlayReason)
Pimpl->UnbindFingerTouchOverlapEvents();
}
void ASGPawn::Tick(const float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
Pimpl->RecordHandVelocity(LeftHandGrabState, DeltaSeconds);
Pimpl->RecordHandVelocity(RightHandGrabState, DeltaSeconds);
}
void ASGPawn::PreInitializeComponents()
{
Super::PreInitializeComponents();
@@ -2211,6 +2215,44 @@ void ASGPawn::FImpl::RecordHandVelocity(FSGGrabState& GrabState, const float Del
GrabState.PreviousHandLocation = GrabState.Hand->GetComponentLocation();
}
void ASGPawn::FImpl::StartHandVelocitySamplerTimer()
{
const UWorld* World{Owner->GetWorld()};
if (!ensureAlwaysMsgf(World, TEXT("Invalid world!")))
{
SGLOG_ERROR("The SGPawn hand velocity sampler timer has failed to start!");
return;
}
SGLOG("Starting SGPawn's hand-velocity sampler timer...");
FTimerDelegate Handler;
Handler.BindLambda([= SG_CAPTURE_THIS]()-> void
{
const float DeltaSeconds = World->GetDeltaSeconds();
RecordHandVelocity(Owner->LeftHandGrabState, DeltaSeconds);
RecordHandVelocity(Owner->RightHandGrabState, DeltaSeconds);
});
const float Interval = 1.0f / Owner->HandVelocitySamplerFramerate;
FTimerManager& TimerManager = World->GetTimerManager();
TimerManager.SetTimer(
HandVelocitySamplerTimer, Handler, Interval,
true, -1.0f);
if (ensureAlwaysMsgf(TimerManager.IsTimerActive(HandVelocitySamplerTimer),
TEXT("HandVelocitySamplerTimer is not active")))
{
SGLOG("The SGPawn hand velocity sampler timer has been started successfully!");
SGLOG("The SGPawn hand velocity sampler interval is: ", Interval);
}
else
{
SGLOG_ERROR("The SGPawn hand velocity sampler timer has failed to start!");
}
}
void ASGPawn::FImpl::Release(FSGGrabState& GrabState) const
{
if (!IsValid(GrabState.GrabbedActor))
@@ -199,6 +199,9 @@ private:
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
USphereComponent* RightPinkyFingertipTouchCollider;
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
float HandVelocitySamplerFramerate;
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
int32 MaxNumberOfHandVelocitySamples;
@@ -379,7 +382,6 @@ public:
public:
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void Tick(float DeltaSeconds) override;
virtual void PreInitializeComponents() override;
virtual void PostInitializeComponents() override;