diff --git a/Config/DefaultRWTHVRToolkit.ini b/Config/DefaultRWTHVRToolkit.ini
index 29ee91a7aaabc28feebf6357b1672bdd652ff613..13066ebe26e8ab454486f97bbb982275d9b2587c 100644
--- a/Config/DefaultRWTHVRToolkit.ini
+++ b/Config/DefaultRWTHVRToolkit.ini
@@ -4,4 +4,18 @@
 +StructRedirects = (OldName="/Script/RWTHVRToolkit.VRTransformRep",NewName="/Script/RWTHVRToolkit.ReplicatedTransform")
 +ClassRedirects = (OldName="/Script/RWTHVRToolkit.VRWidgetInteractionComponent",NewName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent")
 +PropertyRedirects = (OldName="/Script/RWTHVRToolkit.RWTHVRPawn.PawnMovement",NewName="/Script/RWTHVRToolkit.RWTHVRPawn.CollisionHandlingMovement")
-+PropertyRedirects = (OldName="/Script/RWTHVRToolkit.RWTHVRPawn.PawnMovement",NewName="/Script/RWTHVRToolkit.RWTHVRPawn.CollisionHandlingMovement")
\ No newline at end of file
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.RWTHVRPawn.PawnMovement",NewName="/Script/RWTHVRToolkit.RWTHVRPawn.CollisionHandlingMovement")
++ClassRedirects = (OldName="/Script/RWTHVRToolkit.RaycastSelectionComponent",NewName="/Script/RWTHVRToolkit.RaycastInteractionComponent")
++ClassRedirects = (OldName="/Script/RWTHVRToolkit.GrabComponent",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent")
++FunctionRedirects = (OldName="/Script/RWTHVRToolkit.RaycastInteractionComponent.OnBeginSelect",NewName="/Script/RWTHVRToolkit.RaycastInteractionComponent.OnBeginInteraction")
++FunctionRedirects = (OldName="/Script/RWTHVRToolkit.RaycastInteractionComponent.OnEndSelect",NewName="/Script/RWTHVRToolkit.RaycastInteractionComponent.OnEndInteraction")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.RaycastInteractionComponent.RayCastSelectInputAction",NewName="/Script/RWTHVRToolkit.RaycastInteractionComponent.RayCastInteractionInputAction")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.RaycastInteractionComponent.RayCastInteractionInputAction",NewName="/Script/RWTHVRToolkit.RaycastInteractionComponent.InteractionInputAction")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.PreviousGrabbablesInRange",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.PreviousInteractableComponentsInRange")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.GrabInputAction",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.InteractionInputAction")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.GrabSphereRadius",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.InteractionSphereRadius")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.bOnlyGrabClosestActor",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.bOnlyInteractWithClosestActor")
++FunctionRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.OnBeginGrab",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.OnBeginInteraction")
++FunctionRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.OnEndGrab",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.OnEndInteraction")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.PreviousGrabBehavioursInRange",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.PreviousInteractableComponentsInRange")
++PropertyRedirects = (OldName="/Script/RWTHVRToolkit.DirectInteractionComponent.CurrentGrabBehavioursInRange",NewName="/Script/RWTHVRToolkit.DirectInteractionComponent.CurrentInteractableComponentsInRange")
\ No newline at end of file
diff --git a/Content/Components/DirectInteraction/BP_DirectInteractionComponent.uasset b/Content/Components/DirectInteraction/BP_DirectInteractionComponent.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..420322a7da6732a5a5112d5341778debeceff2ef
Binary files /dev/null and b/Content/Components/DirectInteraction/BP_DirectInteractionComponent.uasset differ
diff --git a/Content/Components/DirectInteraction/IA_DirectInteractionLeft.uasset b/Content/Components/DirectInteraction/IA_DirectInteractionLeft.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..05597e706243b8138bcea4da36fcc87849b6ba51
Binary files /dev/null and b/Content/Components/DirectInteraction/IA_DirectInteractionLeft.uasset differ
diff --git a/Content/Components/DirectInteraction/IA_DirectInteractionRight.uasset b/Content/Components/DirectInteraction/IA_DirectInteractionRight.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..76128dfe613f4825b57d9a27ac9c93e1829554de
Binary files /dev/null and b/Content/Components/DirectInteraction/IA_DirectInteractionRight.uasset differ
diff --git a/Content/Components/Grabbing/BP_GrabComponent.uasset b/Content/Components/Grabbing/BP_GrabComponent.uasset
deleted file mode 100644
index 40c5437d25b66fce44d8073ff8f40103941f70bd..0000000000000000000000000000000000000000
Binary files a/Content/Components/Grabbing/BP_GrabComponent.uasset and /dev/null differ
diff --git a/Content/Components/Grabbing/IA_GrabLeft.uasset b/Content/Components/Grabbing/IA_GrabLeft.uasset
deleted file mode 100644
index bcc873bcdbf823add969db4e7528603617badb84..0000000000000000000000000000000000000000
Binary files a/Content/Components/Grabbing/IA_GrabLeft.uasset and /dev/null differ
diff --git a/Content/Components/Grabbing/IA_GrabRight.uasset b/Content/Components/Grabbing/IA_GrabRight.uasset
deleted file mode 100644
index 9df17caed4d5b4f6e8da91e219ffde3fdb72c21e..0000000000000000000000000000000000000000
Binary files a/Content/Components/Grabbing/IA_GrabRight.uasset and /dev/null differ
diff --git a/Content/Components/Raycast/BP_RaycastSelectionComponent.uasset b/Content/Components/Raycast/BP_RaycastSelectionComponent.uasset
deleted file mode 100644
index 8b06b970f91a7b78d47d15123f69c62cfaab798f..0000000000000000000000000000000000000000
Binary files a/Content/Components/Raycast/BP_RaycastSelectionComponent.uasset and /dev/null differ
diff --git a/Content/Components/Raycast/IA_RaycastSelectLeft.uasset b/Content/Components/Raycast/IA_RaycastSelectLeft.uasset
deleted file mode 100644
index 16139611e6a786a71823592bd78c1feb2518862d..0000000000000000000000000000000000000000
Binary files a/Content/Components/Raycast/IA_RaycastSelectLeft.uasset and /dev/null differ
diff --git a/Content/Components/Raycast/IA_RaycastSelectRight.uasset b/Content/Components/Raycast/IA_RaycastSelectRight.uasset
deleted file mode 100644
index 201c652c77e03a56b9c67e9fcfce356d16e10f3c..0000000000000000000000000000000000000000
Binary files a/Content/Components/Raycast/IA_RaycastSelectRight.uasset and /dev/null differ
diff --git a/Content/Components/RaycastInteraction/BP_RaycastInteractionComponent.uasset b/Content/Components/RaycastInteraction/BP_RaycastInteractionComponent.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..2416ad8fba677355d3d0f1fc8a1708b90bc8fb12
Binary files /dev/null and b/Content/Components/RaycastInteraction/BP_RaycastInteractionComponent.uasset differ
diff --git a/Content/Components/RaycastInteraction/IA_RaycastInteractionLeft.uasset b/Content/Components/RaycastInteraction/IA_RaycastInteractionLeft.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..13494f735ac48c8c86551b18695f3a0cd064d524
Binary files /dev/null and b/Content/Components/RaycastInteraction/IA_RaycastInteractionLeft.uasset differ
diff --git a/Content/Components/RaycastInteraction/IA_RaycastInteractionRight.uasset b/Content/Components/RaycastInteraction/IA_RaycastInteractionRight.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..f6ffa30dcc98699d57b19eacfa02bd0701e076e0
Binary files /dev/null and b/Content/Components/RaycastInteraction/IA_RaycastInteractionRight.uasset differ
diff --git a/Content/Input/Default_IMC/IMC_General.uasset b/Content/Input/Default_IMC/IMC_General.uasset
index a7b024c34a921c006210c9e64c268f05237c21cd..22686d822ccd6f948acca7c5bef8168d983eef4f 100644
Binary files a/Content/Input/Default_IMC/IMC_General.uasset and b/Content/Input/Default_IMC/IMC_General.uasset differ
diff --git a/Content/Pawn/BP_RWTHVRPawn_Default.uasset b/Content/Pawn/BP_RWTHVRPawn_Default.uasset
index 9531919e30f6d97207deeb2364f67332592dafce..d23d6e88539254ea147fd7a57122d74208f84f86 100644
Binary files a/Content/Pawn/BP_RWTHVRPawn_Default.uasset and b/Content/Pawn/BP_RWTHVRPawn_Default.uasset differ
diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c8cf9ce35e45d0bc107cd73da08333ef5ba5b2d9
--- /dev/null
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
@@ -0,0 +1,185 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Interaction/Interactors/DirectInteractionComponent.h"
+
+#include "EnhancedInputComponent.h"
+#include "Interaction/Interactables/InteractableComponent.h"
+#include "Interaction/Interactables/InteractionBitSet.h"
+
+#include "Kismet/GameplayStatics.h"
+#include "Logging/StructuredLog.h"
+#include "Utility/RWTHVRUtilities.h"
+
+// Sets default values for this component's properties
+UDirectInteractionComponent::UDirectInteractionComponent()
+{
+	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these
+	// features off to improve performance if you don't need them.
+	PrimaryComponentTick.bCanEverTick = true;
+	// ...
+}
+
+void UDirectInteractionComponent::TickComponent(float DeltaTime, ELevelTick TickType,
+												FActorComponentTickFunction* ThisTickFunction)
+{
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+
+	TArray<UInteractableComponent*> CurrentInteractableCompsInRange;
+
+	TArray<FHitResult> OutHits;
+	const ETraceTypeQuery TraceType = UEngineTypes::ConvertToTraceType(ECollisionChannel::ECC_PhysicsBody);
+
+	auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
+
+	UKismetSystemLibrary::SphereTraceMulti(GetWorld(), GetAttachParent()->GetComponentLocation(),
+										   GetAttachParent()->GetComponentLocation(), InteractionSphereRadius,
+										   TraceType, true, ActorsToIgnore, DebugTrace, OutHits, true, FColor::Green);
+
+	for (FHitResult Hit : OutHits)
+	{
+		AActor* HitActor = Hit.GetActor();
+		if (HitActor)
+		{
+			UInteractableComponent* InteractableComp = SearchForInteractable(HitActor);
+			if (InteractableComp && InteractableComp->HasInteractionTypeFlag(EInteractorType::Direct) &&
+				InteractableComp->IsInteractable)
+			{
+				InteractableComp->HitResult = Hit;
+				CurrentInteractableCompsInRange.AddUnique(InteractableComp);
+			}
+		}
+	}
+
+	CurrentInteractableComponentsInRange = CurrentInteractableCompsInRange;
+
+	// Call hover start events on all components that were not in range before
+	for (UInteractableComponent* CurrentInteractableComp : CurrentInteractableCompsInRange)
+	{
+		if (!PreviousInteractableComponentsInRange.Contains(CurrentInteractableComp))
+		{
+			PreviousInteractableComponentsInRange.AddUnique(CurrentInteractableComp);
+			CurrentInteractableComp->HandleOnHoverStartEvents(this, EInteractorType::Direct);
+		}
+	}
+
+	TArray<UInteractableComponent*> ComponentsToRemove;
+
+	// Call hover end events on all components that were previously in range, but not anymore
+	for (UInteractableComponent* PrevInteractableComp : PreviousInteractableComponentsInRange)
+	{
+		if (!CurrentInteractableCompsInRange.Contains(PrevInteractableComp))
+		{
+			ComponentsToRemove.AddUnique(PrevInteractableComp);
+			PrevInteractableComp->HandleOnHoverEndEvents(this, EInteractorType::Direct);
+		}
+	}
+
+	for (UInteractableComponent* CompToRemove : ComponentsToRemove)
+	{
+		PreviousInteractableComponentsInRange.Remove(CompToRemove);
+	}
+}
+
+void UDirectInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
+{
+	IInputExtensionInterface::SetupPlayerInput(PlayerInputComponent);
+
+	const APawn* Pawn = Cast<APawn>(GetOwner());
+	if (!Pawn)
+		return;
+
+	// Probably not the best place to add this.
+	ActorsToIgnore.AddUnique(GetOwner());
+
+	UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(Pawn->InputComponent);
+	if (EI == nullptr)
+		return;
+
+	EI->BindAction(InteractionInputAction, ETriggerEvent::Started, this,
+				   &UDirectInteractionComponent::OnBeginInteraction);
+	EI->BindAction(InteractionInputAction, ETriggerEvent::Completed, this,
+				   &UDirectInteractionComponent::OnEndInteraction);
+}
+
+void UDirectInteractionComponent::OnBeginInteraction(const FInputActionValue& Value)
+{
+	const FVector InteractionLocation = GetAttachParent()->GetComponentLocation();
+
+	if (CurrentInteractableComponentsInRange.IsEmpty())
+		return;
+
+	if (bOnlyInteractWithClosestActor)
+	{
+		auto MinElement = *Algo::MinElementBy(
+			CurrentInteractableComponentsInRange,
+			[&](auto Element)
+			{ return FVector(Element->GetOwner()->GetActorLocation() - InteractionLocation).Size(); });
+		MinElement->HandleOnActionStartEvents(this, InteractionInputAction, Value, EInteractorType::Direct);
+		CurrentlyInteractedComponents = {MinElement};
+	}
+	else
+	{
+		CurrentlyInteractedComponents.Reserve(CurrentlyInteractedComponents.Num() +
+											  CurrentInteractableComponentsInRange.Num());
+		for (UInteractableComponent* InteractableComp : CurrentInteractableComponentsInRange)
+		{
+			InteractableComp->HandleOnActionStartEvents(this, InteractionInputAction, Value, EInteractorType::Direct);
+			CurrentlyInteractedComponents.Add(InteractableComp);
+		}
+	}
+}
+
+void UDirectInteractionComponent::OnEndInteraction(const FInputActionValue& Value)
+{
+	for (auto& Component : CurrentlyInteractedComponents)
+	{
+		if (Component.IsValid())
+		{
+			Component->HandleOnActionEndEvents(this, InteractionInputAction, Value, EInteractorType::Direct);
+		}
+	}
+}
+
+UInteractableComponent* UDirectInteractionComponent::SearchForInteractable(AActor* HitActor)
+{
+	UInteractableComponent* InteractableComponent = nullptr;
+	if (!HitActor)
+	{
+		UE_LOGFMT(Toolkit, Warning,
+				  "UDirectInteractionComponent::SearchForInteractable: HitActor was nullptr, returning nullptr");
+		return nullptr;
+	}
+
+	if (HitActor->IsChildActor())
+	{
+		// search for UInteractable upwards from hit geometry and return first one found
+		InteractableComponent = HitActor->FindComponentByClass<UInteractableComponent>();
+		// if InteractableComponen is not valid search at parent
+		if (!InteractableComponent)
+		{
+			HitActor = HitActor->GetParentActor();
+			if (HitActor)
+			{
+				bSearchAtParent = true;
+				return SearchForInteractable(HitActor);
+			}
+		}
+	}
+	else if (!HitActor->IsChildActor())
+	{
+		InteractableComponent = HitActor->FindComponentByClass<UInteractableComponent>();
+	}
+
+	if (InteractableComponent)
+	{
+		// in the case, were we had to iterate up the hierarchy, check if we are allowed
+		// to interact with the parent via child geometry
+		if (bSearchAtParent && !InteractableComponent->bAllowInteractionFromChildGeometry)
+		{
+			InteractableComponent = nullptr;
+		}
+	}
+	bSearchAtParent = false;
+	return InteractableComponent;
+}
diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp
deleted file mode 100644
index 7429a615013b4fa35b77171cb82e58ff9e738075..0000000000000000000000000000000000000000
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "Interaction/Interactors/GrabComponent.h"
-
-#include "EnhancedInputComponent.h"
-#include "Interaction/Interactables/InteractableComponent.h"
-#include "Interaction/Interactables/InteractionBitSet.h"
-
-#include "Kismet/GameplayStatics.h"
-#include "Logging/StructuredLog.h"
-#include "Utility/RWTHVRUtilities.h"
-
-// Sets default values for this component's properties
-UGrabComponent::UGrabComponent()
-{
-	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these
-	// features off to improve performance if you don't need them.
-	PrimaryComponentTick.bCanEverTick = true;
-	// ...
-}
-
-void UGrabComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
-{
-	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
-
-	TArray<UInteractableComponent*> CurrentGrabCompsInRange;
-
-	TArray<FHitResult> OutHits;
-	const ETraceTypeQuery TraceType = UEngineTypes::ConvertToTraceType(ECollisionChannel::ECC_PhysicsBody);
-
-	auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
-
-	UKismetSystemLibrary::SphereTraceMulti(GetWorld(), GetAttachParent()->GetComponentLocation(),
-										   GetAttachParent()->GetComponentLocation(), GrabSphereRadius, TraceType, true,
-										   ActorsToIgnore, DebugTrace, OutHits, true, FColor::Green);
-
-	for (FHitResult Hit : OutHits)
-	{
-		AActor* HitActor = Hit.GetActor();
-		if (HitActor)
-		{
-			UInteractableComponent* Grabbable = SearchForInteractable(HitActor);
-			if (Grabbable && Grabbable->HasInteractionTypeFlag(EInteractorType::Grab) && Grabbable->IsInteractable)
-			{
-				Grabbable->HitResult = Hit;
-				CurrentGrabCompsInRange.AddUnique(Grabbable);
-			}
-		}
-	}
-
-	CurrentGrabBehavioursInRange = CurrentGrabCompsInRange;
-
-	// Call hover start events on all components that were not in range before
-	for (UInteractableComponent* CurrentGrabbable : CurrentGrabCompsInRange)
-	{
-		if (!PreviousGrabBehavioursInRange.Contains(CurrentGrabbable))
-		{
-			PreviousGrabBehavioursInRange.AddUnique(CurrentGrabbable);
-			CurrentGrabbable->HandleOnHoverStartEvents(this, EInteractorType::Grab);
-		}
-	}
-
-	TArray<UInteractableComponent*> ComponentsToRemove;
-
-	// Call hover end events on all components that were previously in range, but not anymore
-	for (UInteractableComponent* PrevGrabbale : PreviousGrabBehavioursInRange)
-	{
-		if (!CurrentGrabCompsInRange.Contains(PrevGrabbale))
-		{
-			ComponentsToRemove.AddUnique(PrevGrabbale);
-			PrevGrabbale->HandleOnHoverEndEvents(this, EInteractorType::Grab);
-		}
-	}
-
-	for (UInteractableComponent* CompToRemove : ComponentsToRemove)
-	{
-		PreviousGrabBehavioursInRange.Remove(CompToRemove);
-	}
-}
-
-void UGrabComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
-{
-	IInputExtensionInterface::SetupPlayerInput(PlayerInputComponent);
-
-	const APawn* Pawn = Cast<APawn>(GetOwner());
-	if (!Pawn)
-		return;
-
-	// Probably not the best place to add this.
-	ActorsToIgnore.AddUnique(GetOwner());
-
-	UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(Pawn->InputComponent);
-	if (EI == nullptr)
-		return;
-
-	EI->BindAction(GrabInputAction, ETriggerEvent::Started, this, &UGrabComponent::OnBeginGrab);
-	EI->BindAction(GrabInputAction, ETriggerEvent::Completed, this, &UGrabComponent::OnEndGrab);
-}
-
-void UGrabComponent::OnBeginGrab(const FInputActionValue& Value)
-{
-	const FVector GrabLocation = GetAttachParent()->GetComponentLocation();
-
-	if (CurrentGrabBehavioursInRange.IsEmpty())
-		return;
-
-	if (bOnlyGrabClosestActor)
-	{
-		auto MinElement = *Algo::MinElementBy(
-			CurrentGrabBehavioursInRange,
-			[&](auto Element) { return FVector(Element->GetOwner()->GetActorLocation() - GrabLocation).Size(); });
-		MinElement->HandleOnActionStartEvents(this, GrabInputAction, Value, EInteractorType::Grab);
-		CurrentlyGrabbedComponents = {MinElement};
-	}
-	else
-	{
-		CurrentlyGrabbedComponents.Reserve(CurrentlyGrabbedComponents.Num() + CurrentGrabBehavioursInRange.Num());
-		for (UInteractableComponent* Grabbable : CurrentGrabBehavioursInRange)
-		{
-			Grabbable->HandleOnActionStartEvents(this, GrabInputAction, Value, EInteractorType::Grab);
-			CurrentlyGrabbedComponents.Add(Grabbable);
-		}
-	}
-}
-
-void UGrabComponent::OnEndGrab(const FInputActionValue& Value)
-{
-	for (auto& Component : CurrentlyGrabbedComponents)
-	{
-		if (Component.IsValid())
-		{
-			Component->HandleOnActionEndEvents(this, GrabInputAction, Value, EInteractorType::Grab);
-		}
-	}
-}
-
-UInteractableComponent* UGrabComponent::SearchForInteractable(AActor* HitActor)
-{
-	UInteractableComponent* Grabbable = nullptr;
-	if (!HitActor)
-	{
-		UE_LOGFMT(Toolkit, Warning, "UGrabComponent::SearchForInteractable: HitActor was nullptr, returning nullptr");
-		return nullptr;
-	}
-
-	if (HitActor->IsChildActor())
-	{
-		// search for UInteractable upwards from hit geometry and return first one found
-		Grabbable = HitActor->FindComponentByClass<UInteractableComponent>();
-		// if Grabbable is not valid search at parent
-		if (!Grabbable)
-		{
-			HitActor = HitActor->GetParentActor();
-			if (HitActor)
-			{
-				bSearchAtParent = true;
-				return SearchForInteractable(HitActor);
-			}
-		}
-	}
-	else if (!HitActor->IsChildActor())
-	{
-		Grabbable = HitActor->FindComponentByClass<UInteractableComponent>();
-	}
-
-	if (Grabbable)
-	{
-		// in the case, were we had to iterate up the hierarchy, check if we are allowed
-		// to grab the parent via child geometry
-		if (bSearchAtParent && !Grabbable->bAllowInteractionFromChildGeometry)
-		{
-			Grabbable = nullptr;
-		}
-	}
-	bSearchAtParent = false;
-	return Grabbable;
-}
diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/RWTHVRWidgetInteractionComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/RWTHVRWidgetInteractionComponent.cpp
index 020ae40bff8e17f164d2e7d895ae5860aab93de9..3a87de65d2cb52a5bce0dd0aa71af9dd3b2f69bb 100644
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactors/RWTHVRWidgetInteractionComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/RWTHVRWidgetInteractionComponent.cpp
@@ -4,7 +4,7 @@
 #include "Interaction/Interactors/RWTHVRWidgetInteractionComponent.h"
 
 #include "EnhancedInputComponent.h"
-#include "Interaction/Interactors/GrabComponent.h"
+#include "Interaction/Interactors/DirectInteractionComponent.h"
 #include "Logging/StructuredLog.h"
 #include "Misc/Optional.h"
 #include "Utility/RWTHVRUtilities.h"
diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/RaycastSelectionComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/RaycastInteractionComponent.cpp
similarity index 60%
rename from Source/RWTHVRToolkit/Private/Interaction/Interactors/RaycastSelectionComponent.cpp
rename to Source/RWTHVRToolkit/Private/Interaction/Interactors/RaycastInteractionComponent.cpp
index e10a44b0053726512f1ed80e98e853e411675377..94afba4b4426fe1b861d787826f0e1cc11d6583b 100644
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactors/RaycastSelectionComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/RaycastInteractionComponent.cpp
@@ -1,14 +1,14 @@
 // Fill out your copyright notice in the Description page of Project Settings.
 
 
-#include "Interaction/Interactors/RaycastSelectionComponent.h"
+#include "Interaction/Interactors/RaycastInteractionComponent.h"
 
 #include "EnhancedInputComponent.h"
 #include "Interaction/Interactables/InteractableComponent.h"
 #include "Kismet/KismetSystemLibrary.h"
 
 // Sets default values for this component's properties
-URaycastSelectionComponent::URaycastSelectionComponent()
+URaycastInteractionComponent::URaycastInteractionComponent()
 {
 	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these
 	// features off to improve performance if you don't need them.
@@ -18,12 +18,12 @@ URaycastSelectionComponent::URaycastSelectionComponent()
 }
 
 // Called every frame
-void URaycastSelectionComponent::TickComponent(float DeltaTime, ELevelTick TickType,
-											   FActorComponentTickFunction* ThisTickFunction)
+void URaycastInteractionComponent::TickComponent(float DeltaTime, ELevelTick TickType,
+												 FActorComponentTickFunction* ThisTickFunction)
 {
 	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
 
-	UInteractableComponent* CurrentSelectable = nullptr;
+	UInteractableComponent* NewInteractableComponent = nullptr;
 
 
 	TArray<AActor*> ActorsToIgnore;
@@ -40,15 +40,15 @@ void URaycastSelectionComponent::TickComponent(float DeltaTime, ELevelTick TickT
 	AActor* HitActor = Hit.GetActor();
 	if (HitActor)
 	{
-		UInteractableComponent* Selectable = HitActor->FindComponentByClass<UInteractableComponent>();
-		if (Selectable && Selectable->IsInteractable)
+		UInteractableComponent* InteractableComponent = HitActor->FindComponentByClass<UInteractableComponent>();
+		if (InteractableComponent && InteractableComponent->IsInteractable)
 		{
-			CurrentSelectable = Selectable;
-			Selectable->HitResult = Hit;
+			NewInteractableComponent = InteractableComponent;
+			InteractableComponent->HitResult = Hit;
 		}
 	}
 
-	CurrentInteractable = CurrentSelectable;
+	CurrentInteractable = NewInteractableComponent;
 
 	if (CurrentInteractable != PreviousInteractable)
 	{
@@ -61,19 +61,19 @@ void URaycastSelectionComponent::TickComponent(float DeltaTime, ELevelTick TickT
 	PreviousInteractable = CurrentInteractable;
 }
 
-void URaycastSelectionComponent::OnBeginSelect(const FInputActionValue& Value)
+void URaycastInteractionComponent::OnBeginInteraction(const FInputActionValue& Value)
 {
 	if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
-		CurrentInteractable->HandleOnActionStartEvents(this, RayCastSelectInputAction, Value, EInteractorType::Raycast);
+		CurrentInteractable->HandleOnActionStartEvents(this, InteractionInputAction, Value, EInteractorType::Raycast);
 }
 
-void URaycastSelectionComponent::OnEndSelect(const FInputActionValue& Value)
+void URaycastInteractionComponent::OnEndInteraction(const FInputActionValue& Value)
 {
 	if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
-		CurrentInteractable->HandleOnActionEndEvents(this, RayCastSelectInputAction, Value, EInteractorType::Raycast);
+		CurrentInteractable->HandleOnActionEndEvents(this, InteractionInputAction, Value, EInteractorType::Raycast);
 }
 
-void URaycastSelectionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
+void URaycastInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
 {
 	IInputExtensionInterface::SetupPlayerInput(PlayerInputComponent);
 
@@ -85,6 +85,8 @@ void URaycastSelectionComponent::SetupPlayerInput(UInputComponent* PlayerInputCo
 	if (!EI)
 		return;
 
-	EI->BindAction(RayCastSelectInputAction, ETriggerEvent::Started, this, &URaycastSelectionComponent::OnBeginSelect);
-	EI->BindAction(RayCastSelectInputAction, ETriggerEvent::Completed, this, &URaycastSelectionComponent::OnEndSelect);
+	EI->BindAction(InteractionInputAction, ETriggerEvent::Started, this,
+				   &URaycastInteractionComponent::OnBeginInteraction);
+	EI->BindAction(InteractionInputAction, ETriggerEvent::Completed, this,
+				   &URaycastInteractionComponent::OnEndInteraction);
 }
diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractionBitSet.h b/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractionBitSet.h
index a317318d9d4af78e1a640c76ce6e7629dbbefae7..f2faaebab1f5288633cf68fba9773a4cd076c952 100644
--- a/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractionBitSet.h
+++ b/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractionBitSet.h
@@ -6,7 +6,7 @@ enum EInteractorType : int
 	None = 0 UMETA(Hidden),
 	Raycast = 1 << 0,
 	Spherecast = 1 << 1,
-	Grab = 1 << 2,
+	Direct = 1 << 2,
 	Reserved2 = 1 << 3,
 	Reserved3 = 1 << 4,
 	Reserved4 = 1 << 5,
diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactors/DirectInteractionComponent.h b/Source/RWTHVRToolkit/Public/Interaction/Interactors/DirectInteractionComponent.h
new file mode 100644
index 0000000000000000000000000000000000000000..69ef74ff844a727c11a333047a7f011a12d01241
--- /dev/null
+++ b/Source/RWTHVRToolkit/Public/Interaction/Interactors/DirectInteractionComponent.h
@@ -0,0 +1,58 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Components/SceneComponent.h"
+#include "Interaction/Interactables/InteractableComponent.h"
+#include "Pawn/InputExtensionInterface.h"
+#include "DirectInteractionComponent.generated.h"
+
+UCLASS(Abstract, Blueprintable)
+class RWTHVRTOOLKIT_API UDirectInteractionComponent : public USceneComponent, public IInputExtensionInterface
+{
+	GENERATED_BODY()
+
+public:
+	// Sets default values for this component's properties
+	UDirectInteractionComponent();
+
+	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
+							   FActorComponentTickFunction* ThisTickFunction) override;
+
+	UPROPERTY(EditAnywhere, Category = "Input")
+	class UInputAction* InteractionInputAction;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
+	float InteractionSphereRadius = 15.0;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
+	bool bShowDebugTrace = false;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
+	bool bOnlyInteractWithClosestActor = false;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
+	TArray<AActor*> ActorsToIgnore;
+
+	virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override;
+
+private:
+	UFUNCTION()
+	void OnBeginInteraction(const FInputActionValue& Value);
+
+	UFUNCTION()
+	void OnEndInteraction(const FInputActionValue& Value);
+
+	UPROPERTY()
+	TArray<UInteractableComponent*> PreviousInteractableComponentsInRange;
+
+	UPROPERTY()
+	TArray<UInteractableComponent*> CurrentInteractableComponentsInRange;
+
+	TArray<TWeakObjectPtr<UInteractableComponent>> CurrentlyInteractedComponents;
+
+	UInteractableComponent* SearchForInteractable(AActor* HitActor);
+
+	bool bSearchAtParent = false;
+};
diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h b/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h
deleted file mode 100644
index 4e18d911a41ad79fbcb4cf4d6d1e914d11f74b5f..0000000000000000000000000000000000000000
--- a/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-#include "Components/SceneComponent.h"
-#include "Interaction/Interactables/InteractableComponent.h"
-#include "Pawn/InputExtensionInterface.h"
-#include "GrabComponent.generated.h"
-
-class UGrabbableComponent;
-
-UCLASS(Abstract, Blueprintable)
-class RWTHVRTOOLKIT_API UGrabComponent : public USceneComponent, public IInputExtensionInterface
-{
-	GENERATED_BODY()
-
-public:
-	// Sets default values for this component's properties
-	UGrabComponent();
-
-	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
-							   FActorComponentTickFunction* ThisTickFunction) override;
-
-	UPROPERTY(EditAnywhere, Category = "Input")
-	class UInputAction* GrabInputAction;
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grabbing")
-	float GrabSphereRadius = 15.0;
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grabbing")
-	bool bShowDebugTrace = false;
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grabbing")
-	bool bOnlyGrabClosestActor = false;
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grabbing")
-	TArray<AActor*> ActorsToIgnore;
-
-	virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override;
-
-private:
-	UFUNCTION()
-	void OnBeginGrab(const FInputActionValue& Value);
-
-	UFUNCTION()
-	void OnEndGrab(const FInputActionValue& Value);
-
-	UPROPERTY()
-	TArray<UInteractableComponent*> PreviousGrabBehavioursInRange;
-
-	UPROPERTY()
-	TArray<UInteractableComponent*> CurrentGrabBehavioursInRange;
-
-	TArray<TWeakObjectPtr<UInteractableComponent>> CurrentlyGrabbedComponents;
-
-	UInteractableComponent* SearchForInteractable(AActor* HitActor);
-
-	bool bSearchAtParent = false;
-};
diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactors/RaycastSelectionComponent.h b/Source/RWTHVRToolkit/Public/Interaction/Interactors/RaycastInteractionComponent.h
similarity index 73%
rename from Source/RWTHVRToolkit/Public/Interaction/Interactors/RaycastSelectionComponent.h
rename to Source/RWTHVRToolkit/Public/Interaction/Interactors/RaycastInteractionComponent.h
index b77f9ca80f6b66bdce3d47771bfab14d9daa39b8..7d9422c24c8df31cfb8b94008445a683113bc930 100644
--- a/Source/RWTHVRToolkit/Public/Interaction/Interactors/RaycastSelectionComponent.h
+++ b/Source/RWTHVRToolkit/Public/Interaction/Interactors/RaycastInteractionComponent.h
@@ -6,24 +6,24 @@
 
 #include "CoreMinimal.h"
 #include "Components/SceneComponent.h"
-#include "RaycastSelectionComponent.generated.h"
+#include "RaycastInteractionComponent.generated.h"
 
 
 UCLASS(Abstract, Blueprintable)
-class RWTHVRTOOLKIT_API URaycastSelectionComponent : public USceneComponent, public IInputExtensionInterface
+class RWTHVRTOOLKIT_API URaycastInteractionComponent : public USceneComponent, public IInputExtensionInterface
 {
 	GENERATED_BODY()
 
 public:
 	// Sets default values for this component's properties
-	URaycastSelectionComponent();
+	URaycastInteractionComponent();
 
 	// Called every frame
 	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
 							   FActorComponentTickFunction* ThisTickFunction) override;
 
 	UPROPERTY(EditAnywhere, Category = "Input")
-	class UInputAction* RayCastSelectInputAction;
+	class UInputAction* InteractionInputAction;
 
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Raycast")
 	float TraceLength = 3000.0;
@@ -32,10 +32,10 @@ public:
 
 private:
 	UFUNCTION()
-	void OnBeginSelect(const FInputActionValue& Value);
+	void OnBeginInteraction(const FInputActionValue& Value);
 
 	UFUNCTION()
-	void OnEndSelect(const FInputActionValue& Value);
+	void OnEndInteraction(const FInputActionValue& Value);
 
 public:
 	virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override;