diff --git a/Content/PointingRay/Ray_Material.uasset b/Content/PointingRay/Ray_Material.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..4ae373bdf3e090fe996f4c48f4ccfc8ec9555b65
Binary files /dev/null and b/Content/PointingRay/Ray_Material.uasset differ
diff --git a/Content/PointingRay/Ray_Mesh.uasset b/Content/PointingRay/Ray_Mesh.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..8a35d2c88da8bde64b6e2fcff085658ec8561964
Binary files /dev/null and b/Content/PointingRay/Ray_Mesh.uasset differ
diff --git a/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp b/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp
index c0a06d49cb89fb87288b1246293ce0335f26764d..fe546cd44482d92ac317eba6d30ba68a60a3598b 100644
--- a/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp
+++ b/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp
@@ -10,6 +10,9 @@
 #include "Interaction/GrabbingBehaviorComponent.h"
 #include "Misc/Optional.h"
 #include "DrawDebugHelpers.h"
+#include "Components/WidgetComponent.h"
+
+DEFINE_LOG_CATEGORY(LogVRInteractionComponent);
 
 // Sets default values for this component's properties
 UBasicVRInteractionComponent::UBasicVRInteractionComponent()
@@ -18,7 +21,28 @@ UBasicVRInteractionComponent::UBasicVRInteractionComponent()
 	// off to improve performance if you don't need them.
 	PrimaryComponentTick.bCanEverTick = true;
 
-	// ...
+	// Setup the interaction ray.
+	InteractionRay = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Interaction Ray"));
+	//this ray model has an inlayed cross with flipped normals so it can be seen as a cross in desktop mode where the right hand is attached to the head
+	ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/nDisplayExtensions/PointingRay/Ray_Mesh"));
+	if (MeshAsset.Object != nullptr)
+	{
+		InteractionRay->SetStaticMesh(MeshAsset.Object);
+	}
+	// turns off collisions as the InteractionRay is only meant to visualize the ray
+	InteractionRay->SetCollisionProfileName(TEXT("NoCollision"));
+	bShowDebug = false; //otherwise the WidgetInteractionComponent debug vis is shown
+	InteractionSource = EWidgetInteractionSource::Custom; //can also be kept at default (World), this way, however, we efficiently reuse the line traces
+	
+}
+
+void UBasicVRInteractionComponent::BeginPlay()
+{
+	Super::BeginPlay();
+	
+	//WidgetInteractionComponent
+	InteractionDistance = MaxClickDistance;
+	SetInteractionRayVisibility(InteractionRayVisibility);
 }
 
 void UBasicVRInteractionComponent::BeginInteraction()
@@ -32,6 +56,12 @@ void UBasicVRInteractionComponent::BeginInteraction()
 		return;
 
 	AActor* HitActor = Hit->GetActor();
+
+	//trigger interaction of WidgetInteractionComponent
+	SetCustomHitResult(Hit.GetValue());
+	//if !bCanRaytraceEveryTick, you have to click twice, since the first tick it only highlights and can't directly click
+	PressPointerKey(EKeys::LeftMouseButton);
+	
 	
 	if (HitActor->Implements<UGrabable>() && Hit->Distance < MaxGrabDistance)
 	{
@@ -55,6 +85,9 @@ void UBasicVRInteractionComponent::BeginInteraction()
 void UBasicVRInteractionComponent::EndInteraction()
 {
 	if(!InteractionRayEmitter) return;
+
+	//end interaction of WidgetInteractionComponent
+	ReleasePointerKey(EKeys::LeftMouseButton);
 	
 	// if we didnt grab anyone there is no need to release
 	if (GrabbedActor == nullptr)
@@ -105,7 +138,13 @@ void UBasicVRInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tic
 	const FTwoVectors StartEnd = GetHandRay(MaxClickDistance);
 	TOptional<FHitResult> Hit = RaytraceForFirstHit(StartEnd);
 	if (!Hit.IsSet())
+	{
+		if(InteractionRayVisibility==EInteractionRayVisibility::VisibleOnHoverOnly)
+		{
+			InteractionRay->SetVisibility(false);
+		}
 		return;
+	}
 	AActor* HitActor = Hit->GetActor();
 
 	// for now uses the same distance as clicking
@@ -113,6 +152,20 @@ void UBasicVRInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tic
 	{
 		ITargetable::Execute_OnTargeted(HitActor, Hit->Location);
 	}
+
+	// widget interaction
+	SetCustomHitResult(Hit.GetValue());
+	if(InteractionRayVisibility==EInteractionRayVisibility::VisibleOnHoverOnly)
+	{
+		if(HitActor->Implements<UTargetable>() || HitActor->Implements<UClickable>() || IsOverInteractableWidget())
+		{
+			InteractionRay->SetVisibility(true);
+		}
+		else
+		{
+			InteractionRay->SetVisibility(false);
+		}
+	}
 }
 
 void UBasicVRInteractionComponent::Initialize(USceneComponent* RayEmitter, float InMaxGrabDistance, float InMaxClickDistance)
@@ -122,6 +175,37 @@ void UBasicVRInteractionComponent::Initialize(USceneComponent* RayEmitter, float
 	InteractionRayEmitter = RayEmitter;
 	MaxGrabDistance = InMaxGrabDistance;
 	MaxClickDistance = InMaxClickDistance;
+
+	InteractionRay->AttachToComponent(RayEmitter, FAttachmentTransformRules::KeepRelativeTransform);
+	this->AttachToComponent(RayEmitter, FAttachmentTransformRules::KeepRelativeTransform);
+}
+
+void UBasicVRInteractionComponent::SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility)
+{
+	InteractionRayVisibility = NewVisibility;
+	if(InteractionRay)
+	{
+		switch (InteractionRayVisibility)
+		{
+		case Visible:
+			InteractionRay->SetVisibility(true);
+			break;
+		case VisibleOnHoverOnly:
+		case Invisible:
+			InteractionRay->SetVisibility(false);
+			break;
+		}
+	}
+
+	if(InteractionRayVisibility==EInteractionRayVisibility::VisibleOnHoverOnly && !bCanRaytraceEveryTick)
+	{
+		UE_LOG(LogVRInteractionComponent, Warning, TEXT("VisibleOnHoverOnly needs bCanRaytraceEveryTick=true, so this is set!"));
+		bCanRaytraceEveryTick=true;
+	}
+	if(InteractionRayVisibility==EInteractionRayVisibility::Visible && !bCanRaytraceEveryTick)
+	{
+		UE_LOG(LogVRInteractionComponent, Warning, TEXT("VisibleOnHoverOnly will need two clicks to interact with widgets if bCanRaytraceEveryTick is not set!"));
+	}
 }
 
 void UBasicVRInteractionComponent::HandlePhysicsAndAttachActor(AActor* HitActor)
@@ -156,10 +240,9 @@ TOptional<FHitResult> UBasicVRInteractionComponent::RaytraceForFirstHit(const FT
 	// will be filled by the Line Trace Function
 	FHitResult Hit;
 
-	const FCollisionObjectQueryParams Params;	
-	FCollisionQueryParams Params2; 
-	Params2.AddIgnoredActor(GetOwner()->GetUniqueID()); // prevents actor hitting itself
-	if (GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, Params, Params2))
+	FCollisionQueryParams Params; 
+	Params.AddIgnoredActor(GetOwner()->GetUniqueID()); // prevents actor hitting itself
+	if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECollisionChannel::ECC_Visibility,Params))
 		return {Hit};
 	else
 		return {};
diff --git a/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h b/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h
index 6e86c208e971ad141a34c489bc1d6d3aca123d5c..29ec7c9acaa169ff9017067eace54983470519be 100644
--- a/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h
+++ b/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h
@@ -3,14 +3,24 @@
 #pragma once
 
 #include "CoreMinimal.h"
-#include "Components/ActorComponent.h"
+#include "Components/WidgetInteractionComponent.h"
 #include "BasicVRInteractionComponent.generated.h"
 
+DECLARE_LOG_CATEGORY_EXTERN(LogVRInteractionComponent, Log, All);
+
 class UGrabbingBehaviorComponent;
 
+UENUM()
+enum EInteractionRayVisibility
+{
+	Visible,
+	VisibleOnHoverOnly,
+	Invisible
+};
+
 
 UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
-class DISPLAYCLUSTEREXTENSIONS_API UBasicVRInteractionComponent : public UActorComponent
+class DISPLAYCLUSTEREXTENSIONS_API UBasicVRInteractionComponent : public UWidgetInteractionComponent
 {
 	GENERATED_BODY()
 
@@ -18,6 +28,8 @@ public:
 	// Sets default values for this component's properties
 	UBasicVRInteractionComponent();
 
+	void BeginPlay() override;
+
 	UFUNCTION(BlueprintCallable) void BeginInteraction(); 
 	UFUNCTION(BlueprintCallable) void EndInteraction();   	
 	
@@ -26,13 +38,16 @@ public:
 
 	UPROPERTY(BlueprintReadWrite) float MaxGrabDistance = 50;
 	UPROPERTY(BlueprintReadWrite) float MaxClickDistance = 500;
-	// Enable this if you want to interact with Targetable classes
-	UPROPERTY(EditAnywhere) bool bCanRaytraceEveryTick = false;
+	// Enable this if you want to interact with Targetable classes or use EInteractionRayVisibility::VisibleOnHoverOnly
+	UPROPERTY(EditAnywhere) bool bCanRaytraceEveryTick = true;
+	UPROPERTY(EditAnywhere) TEnumAsByte<EInteractionRayVisibility> InteractionRayVisibility = EInteractionRayVisibility::VisibleOnHoverOnly;
 
 	UFUNCTION(BlueprintCallable) void Initialize(USceneComponent* RayEmitter, float InMaxGrabDistance = 50, float InMaxClickDistance = 500);
 	
 	UFUNCTION(BlueprintCallable, BlueprintPure) AActor* GetGrabbedActor() const { return GrabbedActor;}
 	UFUNCTION(BlueprintCallable, BlueprintPure) USceneComponent* GetInteractionRayEmitter() const { return InteractionRayEmitter;	}
+
+	UFUNCTION(BlueprintCallable) void SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility);
 private:
 	/* Holding a reference to the actor that is currently being grabbed */
 	UPROPERTY() AActor* GrabbedActor;
@@ -40,6 +55,7 @@ private:
 	UPROPERTY() UPrimitiveComponent* ComponentSimulatingPhysics = nullptr;
 	UPROPERTY() UGrabbingBehaviorComponent* Behavior = nullptr;
 	UPROPERTY() USceneComponent* InteractionRayEmitter = nullptr;
+	UPROPERTY() UStaticMeshComponent* InteractionRay = nullptr;
 	
 	void HandlePhysicsAndAttachActor(AActor* HitActor);
 	FTwoVectors GetHandRay(float Length) const;