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..0da58a602c186aa1ac8d65ba57d2d966a78419b5
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 0f3441165724e615f4fc7f2ca47416c29cf93c1b..bd2bc48ec7039890767e60ba9a3c618f7849198b 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)
@@ -107,6 +140,10 @@ void UBasicVRInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tic
 
 	if (!Hit.IsSet())
 	{
+		if(InteractionRayVisibility==EInteractionRayVisibility::VisibleOnHoverOnly)
+		{
+			InteractionRay->SetVisibility(false);
+		}
 
 		// Execute leave event on the actor that lost the focus if there was one
 		if (LastActorHit && LastActorHit->Implements<UTargetable>())
@@ -141,6 +178,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);
+		}
+	}
 	LastActorHit = HitActor; // Store the actor that was hit to have access to it in the next frame as well
 }
 
@@ -151,6 +202,38 @@ void UBasicVRInteractionComponent::Initialize(USceneComponent* RayEmitter, float
 	InteractionRayEmitter = RayEmitter;
 	MaxGrabDistance = InMaxGrabDistance;
 	MaxClickDistance = InMaxClickDistance;
+
+	InteractionRay->AttachToComponent(RayEmitter, FAttachmentTransformRules::KeepRelativeTransform);
+	InteractionRay->SetRelativeScale3D(FVector(MaxClickDistance/100.0f, 1.0f, 1.0f)); //the ray model has a length of 100cm
+	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)
@@ -185,10 +268,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 92bb238716cc9f86366c4a9fd8bf90c76b9a556e..b096d5f74a1583dee359d4ba1c607fed97463e79 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 UMETA(DisplayName = "Interaction ray visible"),
+	VisibleOnHoverOnly UMETA(DisplayName = "Interaction ray only visible when hovering over Clickable or Targetable objects, or interactable widgets"),
+	Invisible UMETA(DisplayName = "Interaction ray 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
+	// Enable this if you want to interact with Targetable classes or use EInteractionRayVisibility::VisibleOnHoverOnly
 	UPROPERTY(EditAnywhere) bool bCanRaytraceEveryTick = false;
+	UPROPERTY(EditAnywhere) TEnumAsByte<EInteractionRayVisibility> InteractionRayVisibility = EInteractionRayVisibility::Invisible;
 
 	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,8 @@ private:
 	UPROPERTY() UPrimitiveComponent* ComponentSimulatingPhysics = nullptr;
 	UPROPERTY() UGrabbingBehaviorComponent* Behavior = nullptr;
 	UPROPERTY() USceneComponent* InteractionRayEmitter = nullptr;
+	UPROPERTY() UStaticMeshComponent* InteractionRay = nullptr;
+	
 	/* Stores the reference of the Actor that was hit in the last frame*/
 	UPROPERTY() AActor* LastActorHit = nullptr;
 	void HandlePhysicsAndAttachActor(AActor* HitActor);