The default projection only works for objects that are in front of the camera’s direction vector, and unfortunately there’s no way to alter that in Blueprint.
I wrote a snippet of C++ which can handle reverse projections, which I use for screen-edge arrows, here’s the code. I’m going to put a Wiki tutorial up soon. ‘TargetWorldLocation’ is the position you want to transform.
FVector Projected;
bool bTargetBehindCamera = false;
// Custom Projection Function
ULocalPlayer* const LP = OwningGESPlayer->GetLocalPlayer();
if (LP && LP->ViewportClient)
{
FSceneViewProjectionData NewProjectionData;
if (LP->GetProjectionData(LP->ViewportClient->Viewport, EStereoscopicPass::eSSP_FULL, NewProjectionData))
{
const FMatrix ViewProjectionMatrix = NewProjectionData.ComputeViewProjectionMatrix();
const FIntRect ViewRectangle = NewProjectionData.GetConstrainedViewRect();
FPlane Result = ViewProjectionMatrix.TransformFVector4(FVector4(TargetWorldLocation, 1.f));
if (Result.W < 0.f) { bTargetBehindCamera = true; }
if (Result.W == 0.f) { Result.W = 1.f; } // Prevent Divide By Zero
const float RHW = 1.f / FMath::Abs(Result.W);
Projected = FVector(Result.X, Result.Y, Result.Z) * RHW;
// Normalize to 0..1 UI Space
const float NormX = (Projected.X / 2.f) + 0.5f;
const float NormY = 1.f - (Projected.Y / 2.f) - 0.5f;
Projected.X = (float)ViewRectangle.Min.X + (NormX * (float)ViewRectangle.Width());
Projected.Y = (float)ViewRectangle.Min.Y + (NormY * (float)ViewRectangle.Height());
}
}
FVector2D ScreenPos = FVector2D(Projected.X, Projected.Y);