DepthPriorityGroups for 3D widgets

Following up on this. I made the jump to 4.13 and now I’m using Widget Interaction Components to do all of my interaction. New WidgetPassThrough material option worked great. Thanks for that tip.

The problem I ran into with the Widget Interaction Components is that they do their own line tracing.

I had already set up a custom collision channel, and placed my Widget Component in that channel, per your suggestion.

DefaultEngine.ini:

+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,Name="Menu",DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False)

Then I simply made a new c++ class from WidgetInteractionComponent.cpp and overrided its PerformTrace function with my own.

MyWidgetInteractionComponent.cpp
#include “UnifiedPlatform.h”
#include “MyWidgetInteractionComponent.h”

bool UMyWidgetInteractionComponent::PerformTrace(FHitResult& HitResult)
{
	switch (InteractionSource)
	{
	case EWidgetInteractionSource::World:
	{
		const FVector WorldLocation = GetComponentLocation();
		const FTransform WorldTransform = GetComponentTransform();
		const FVector Direction = WorldTransform.GetUnitAxis(EAxis::X);

		TArray<UPrimitiveComponent*> PrimitiveChildren;
		GetRelatedComponentsToIgnoreInAutomaticHitTesting(PrimitiveChildren);

		FCollisionQueryParams Params = FCollisionQueryParams::DefaultQueryParam;
		Params.AddIgnoredComponents(PrimitiveChildren);

		FCollisionObjectQueryParams Everything(FCollisionObjectQueryParams::AllObjects);
		return GetWorld()->LineTraceSingleByObjectType(HitResult, WorldLocation, WorldLocation + (Direction * InteractionDistance), FCollisionObjectQueryParams(ECollisionChannel::ECC_GameTraceChannel2), Params);
	}
	case EWidgetInteractionSource::Mouse:
	case EWidgetInteractionSource::CenterScreen:
	{
		TArray<UPrimitiveComponent*> PrimitiveChildren;
		GetRelatedComponentsToIgnoreInAutomaticHitTesting(PrimitiveChildren);

		FCollisionQueryParams Params = FCollisionQueryParams::DefaultQueryParam;
		Params.AddIgnoredComponents(PrimitiveChildren);

		APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();

		ULocalPlayer* LocalPlayer = PlayerController->GetLocalPlayer();
		bool bHit = false;
		if (LocalPlayer && LocalPlayer->ViewportClient)
		{
			if (InteractionSource == EWidgetInteractionSource::Mouse)
			{
				FVector2D MousePosition;
				if (LocalPlayer->ViewportClient->GetMousePosition(MousePosition))
				{
					bHit = PlayerController->GetHitResultAtScreenPosition(MousePosition, ECC_Visibility, Params, HitResult);
				}
			}
			else if (InteractionSource == EWidgetInteractionSource::CenterScreen)
			{
				FVector2D ViewportSize;
				LocalPlayer->ViewportClient->GetViewportSize(ViewportSize);

				bHit = PlayerController->GetHitResultAtScreenPosition(ViewportSize * 0.5f, ECC_Visibility, Params, HitResult);
			}

			// Don't allow infinite distance hit testing.
			if (bHit)
			{
				if (HitResult.Distance > InteractionDistance)
				{
					HitResult = FHitResult();
					bHit = false;
				}
			}
		}

		return bHit;
	}
	case EWidgetInteractionSource::Custom:
	{
		HitResult = CustomHitResult;
		return HitResult.bBlockingHit;
	}
	}

	return false;
}

MyWidgetInteractionComponent.h
#pragma once

#include "Components/WidgetInteractionComponent.h"
#include "MyWidgetInteractionComponent.generated.h"

/**
 * 
 */
UCLASS(ClassGroup = Experimental, meta = (BlueprintSpawnableComponent, DevelopmentStatus = Experimental))
class UNIFIEDPLATFORM_API UMyWidgetInteractionComponent : public UWidgetInteractionComponent
{
	GENERATED_BODY()

protected:
	/** Performs the trace and gets the hit result under the specified InteractionSource */
	virtual bool PerformTrace(FHitResult& HitResult);
	
	
};

Now everything works perfectly. My depth perception goes haywire when I get within inches of a wall and open up the menu, that’s floating 6 feet away, but I can live with that.

][1]