Advantages of Mutating a value rather than returning the value

Hi all,
Is there a performance advantage of mutating a reference to a value rather than returning the mutated type directly from the method? I.e instead of bool GetSightRayHitLocation(FVector& OutHitLocation) then do FVector GetSightRayHitLocation() and return FVector.ZeroVector for an invalid location?

Cheers, Nik

It seems to be Unreal’s standard to use mutating. In this case a zero vector could still be a legitimate location, perhaps the odds are low but it is possible to sight trace on to the origin, so you cannot return it as indicating a failed trace.

Interesting, does that mean that an uninitialised vector is different from a ‘ZeroVector’? If so, what you said makes perfect sense, thanks!

No, FVector’s constructor doesn’t initialise it’s members.

The reason that was done is because we want success/fail return. An alternative way (and one that would probably be used in the remaster) would be to use an optional type (std::optional /TOptional)

So instead

TOptional<FVector> GetSightRayHitLocation() const;
////////////////
auto Value = GetSightRayHitLocation();
if(Value.IsSet())
{
    //Do something with Value.Get()
}

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

the thread closed before I could ask…
https://community.gamedev.tv/t/advantages-of-mutating-a-value-rather-than-returning-the-value/99927/4

wanted to say that if it doesn’t return zero vector it would return a null? so not safe to use which the optional would wrap in something to protect against calls to undefined?

You would return an empty optional (default constructed optional). Here’s the function (though the functions merged because having this as 3 functions always bothered me)

TOptional<FVector> ATankPlayerController::GetSightRayHitLocation() const
{
	// Find the crosshair position in pixel coordinates
	int32 ViewportSizeX, ViewportSizeY;
	GetViewportSize(ViewportSizeX, ViewportSizeY);
	FVector2D ScreenLocation(ViewportSizeX * CrosshairXLocation, ViewportSizeY * CrosshairYLocation);
	FVector LookDirection;
	FVector StartLocation;
	// "De-project" the screen position of the crosshair to a world direction
	bool Projected =  DeprojectScreenPositionToWorld(
		ScreenLocation.X,
		ScreenLocation.Y,
		StartLocation,
		LookDirection
	);
	if (Projected)
	{
		FHitResult HitResult;
		FVector EndLocation = StartLocation + (LookDirection * LineTraceRange);
		if (GetWorld()->LineTraceSingleByChannel(
			HitResult,
			StartLocation,
			EndLocation,
			ECollisionChannel::ECC_Camera)
			)
		{
			return HitResult.Location;
		}
	}
	return {};
}

Then at the call site:

auto HitLocation = GetSightRayHitLocation();// Has "side-effect", is going to line trace
if (HitLocation.IsSet()) 
{
	AimingComponent->AimAt(HitLocation.GetValue());
}

This topic was automatically closed after 6 days. New replies are no longer allowed.

Privacy & Terms