diff --git a/Content/Components/Grabbing/BP_GrabbableTestObject.uasset b/Content/Components/Grabbing/BP_GrabbableTestObject.uasset
deleted file mode 100644
index 9ee3c8f375ef05e90f3c3f8300b6a13f94def5c6..0000000000000000000000000000000000000000
Binary files a/Content/Components/Grabbing/BP_GrabbableTestObject.uasset and /dev/null differ
diff --git a/Content/Input/Default_IMC/IMC_General.uasset b/Content/Input/Default_IMC/IMC_General.uasset
index eda268398333a091619597aacd0c1dcf9c968807..dabec22388c3ef3047d45c15e89d474731f1174e 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/Input/Default_IMC/IMC_MovementRightHand.uasset b/Content/Input/Default_IMC/IMC_MovementRightHand.uasset
index 44f4a88ed6719fb9bce0d3df925eb10fb58257d0..5058e44e0052ca7da16ffc411113ac08683698e9 100644
Binary files a/Content/Input/Default_IMC/IMC_MovementRightHand.uasset and b/Content/Input/Default_IMC/IMC_MovementRightHand.uasset differ
diff --git a/Content/Pawn/BP_RWTHVRPawn_Default.uasset b/Content/Pawn/BP_RWTHVRPawn_Default.uasset
index 7bcca686b189d765bd7476bf9ffb1ee4bd0ade71..9531919e30f6d97207deeb2364f67332592dafce 100644
Binary files a/Content/Pawn/BP_RWTHVRPawn_Default.uasset and b/Content/Pawn/BP_RWTHVRPawn_Default.uasset differ
diff --git a/Content/TestContent/BP_GrabbableTestObject.uasset b/Content/TestContent/BP_GrabbableTestObject.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..380295d3caa15f50cc4cdc7928bc7a57bbffd9c3
Binary files /dev/null and b/Content/TestContent/BP_GrabbableTestObject.uasset differ
diff --git a/Content/TestContent/TestMap.umap b/Content/TestContent/TestMap.umap
new file mode 100644
index 0000000000000000000000000000000000000000..4beb781c7d3920ab556c0e0cd61231a3dfc2e383
Binary files /dev/null and b/Content/TestContent/TestMap.umap differ
diff --git a/Content/TestMap.umap b/Content/TestMap.umap
deleted file mode 100644
index d06f89d892794ba53dbaca472d6fb990297b0dae..0000000000000000000000000000000000000000
Binary files a/Content/TestMap.umap and /dev/null differ
diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactables/GrabBehavior.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactables/GrabBehavior.cpp
index 0ff95d0c6fc823faef1016badc7fb8330beb9679..1537243da0b6c92a901decadce793bc8bd819bbb 100644
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactables/GrabBehavior.cpp
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactables/GrabBehavior.cpp
@@ -3,8 +3,9 @@
 
 #include "Interaction/Interactables/GrabBehavior.h"
 #include "Interaction/Interactables/InteractableComponent.h"
-#include "Kismet/GameplayStatics.h"
+#include "Logging/StructuredLog.h"
 #include "Serialization/JsonTypes.h"
+#include "Utility/RWTHVRUtilities.h"
 
 UPrimitiveComponent* UGrabBehavior::GetFirstComponentSimulatingPhysics(const AActor* TargetActor)
 {
@@ -29,34 +30,42 @@ UPrimitiveComponent* UGrabBehavior::GetHighestParentSimulatingPhysics(UPrimitive
 	{
 		return GetHighestParentSimulatingPhysics(Cast<UPrimitiveComponent>(Comp->GetAttachParent()));
 	}
-	else
-	{
-		return Comp;
-	}
+
+	return Comp;
 }
 
 void UGrabBehavior::OnActionStart(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
 								  const FInputActionValue& Value)
 {
-	const APawn* Player = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
-
-	USceneComponent* Hand = Cast<USceneComponent>(TriggeredComponent->GetAttachParent());
+	if (bObjectGrabbed)
+	{
+		return;
+	}
 
+	USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggeredComponent->GetAttachParent());
 	const FAttachmentTransformRules Rules = FAttachmentTransformRules(EAttachmentRule::KeepWorld, false);
 
-	MyPhysicsComponent = GetFirstComponentSimulatingPhysics(GetOwner());
-
-	if (MyPhysicsComponent)
+	if (MyPhysicsComponent = GetFirstComponentSimulatingPhysics(GetOwner()); MyPhysicsComponent != nullptr)
 	{
+		bWasSimulatingPhysics = MyPhysicsComponent->IsSimulatingPhysics();
 		MyPhysicsComponent->SetSimulatePhysics(false);
-		MyPhysicsComponent->AttachToComponent(Hand, Rules);
+		bObjectGrabbed = MyPhysicsComponent->AttachToComponent(CurrentAttachParent, Rules);
 	}
 	else
 	{
-		GetOwner()->GetRootComponent()->AttachToComponent(Hand, Rules);
+		bObjectGrabbed = GetOwner()->GetRootComponent()->AttachToComponent(CurrentAttachParent, Rules);
 	}
 
+	if (!bObjectGrabbed)
+	{
+		UE_LOGFMT(Toolkit, Warning, "Grab failed! Cannot attach grabbed component to attach parent ({Parent})",
+				  CurrentAttachParent->GetName());
+		return;
+	}
 
+	// If we want to restrict other interactions while this component is grabbed we add the component
+	// that triggered the interaction to the whitelist of all interactables that are attached to the
+	// affected actor
 	if (bBlockOtherInteractionsWhileGrabbed)
 	{
 		TArray<UInteractableComponent*> Interactables;
@@ -66,21 +75,28 @@ void UGrabBehavior::OnActionStart(USceneComponent* TriggeredComponent, const UIn
 			Interactable->RestrictInteractionToComponent(TriggeredComponent);
 		}
 	}
+
+	OnGrabStartEvent.Broadcast(CurrentAttachParent, MyPhysicsComponent);
 }
 
 void UGrabBehavior::OnActionEnd(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
 								const FInputActionValue& Value)
 {
-	if (MyPhysicsComponent)
-	{
-		MyPhysicsComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
-		MyPhysicsComponent->SetSimulatePhysics(true);
-	}
-	else
+
+	USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggeredComponent->GetAttachParent());
+
+	// We try to release the attached component. If it is not succesful we log and return. Otherwise, we continue.
+	if (!TryRelease())
 	{
-		GetOwner()->GetRootComponent()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
+		UE_LOGFMT(Toolkit, Display,
+				  "UGrabBehavior::OnActionEnd: TryRelease failed to release with AttachParent {Parent}",
+				  CurrentAttachParent->GetName());
+		return;
 	}
 
+	OnGrabEndEvent.Broadcast(CurrentAttachParent, MyPhysicsComponent);
+
+	// Release the interation restriction on all component
 	if (bBlockOtherInteractionsWhileGrabbed)
 	{
 		TArray<UInteractableComponent*> Interactables;
@@ -91,3 +107,23 @@ void UGrabBehavior::OnActionEnd(USceneComponent* TriggeredComponent, const UInpu
 		}
 	}
 }
+
+bool UGrabBehavior::TryRelease()
+{
+	if (!bObjectGrabbed)
+	{
+		return false;
+	}
+
+	if (MyPhysicsComponent)
+	{
+		MyPhysicsComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
+		MyPhysicsComponent->SetSimulatePhysics(bWasSimulatingPhysics);
+	}
+	else
+	{
+		GetOwner()->GetRootComponent()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
+	}
+	bObjectGrabbed = false;
+	return true;
+}
diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp
index 5dcc020c60082f9055c810c05ad74f968bf78dbb..7429a615013b4fa35b77171cb82e58ff9e738075 100644
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/GrabComponent.cpp
@@ -8,6 +8,8 @@
 #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()
@@ -15,7 +17,6 @@ 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;
-
 	// ...
 }
 
@@ -23,10 +24,8 @@ void UGrabComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorC
 {
 	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
 
-
 	TArray<UInteractableComponent*> CurrentGrabCompsInRange;
 
-	TArray<AActor*> ActorsToIgnore;
 	TArray<FHitResult> OutHits;
 	const ETraceTypeQuery TraceType = UEngineTypes::ConvertToTraceType(ECollisionChannel::ECC_PhysicsBody);
 
@@ -41,42 +40,42 @@ void UGrabComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorC
 		AActor* HitActor = Hit.GetActor();
 		if (HitActor)
 		{
-			UInteractableComponent* Grabbable = HitActor->FindComponentByClass<UInteractableComponent>();
+			UInteractableComponent* Grabbable = SearchForInteractable(HitActor);
 			if (Grabbable && Grabbable->HasInteractionTypeFlag(EInteractorType::Grab) && Grabbable->IsInteractable)
 			{
 				Grabbable->HitResult = Hit;
-				CurrentGrabCompsInRange.Add(Grabbable);
+				CurrentGrabCompsInRange.AddUnique(Grabbable);
 			}
 		}
 	}
 
-	CurrentGrabbableInRange = CurrentGrabCompsInRange;
+	CurrentGrabBehavioursInRange = CurrentGrabCompsInRange;
 
 	// Call hover start events on all components that were not in range before
-	for (UInteractableComponent* CurrentGrabbale : CurrentGrabCompsInRange)
+	for (UInteractableComponent* CurrentGrabbable : CurrentGrabCompsInRange)
 	{
-		if (!PreviousGrabbablesInRange.Contains(CurrentGrabbale))
+		if (!PreviousGrabBehavioursInRange.Contains(CurrentGrabbable))
 		{
-			PreviousGrabbablesInRange.Add(CurrentGrabbale);
-			CurrentGrabbale->HandleOnHoverStartEvents(this, EInteractorType::Grab);
+			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 : PreviousGrabbablesInRange)
+	for (UInteractableComponent* PrevGrabbale : PreviousGrabBehavioursInRange)
 	{
 		if (!CurrentGrabCompsInRange.Contains(PrevGrabbale))
 		{
-			ComponentsToRemove.Add(PrevGrabbale);
+			ComponentsToRemove.AddUnique(PrevGrabbale);
 			PrevGrabbale->HandleOnHoverEndEvents(this, EInteractorType::Grab);
 		}
 	}
 
 	for (UInteractableComponent* CompToRemove : ComponentsToRemove)
 	{
-		PreviousGrabbablesInRange.Remove(CompToRemove);
+		PreviousGrabBehavioursInRange.Remove(CompToRemove);
 	}
 }
 
@@ -88,6 +87,9 @@ void UGrabComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
 	if (!Pawn)
 		return;
 
+	// Probably not the best place to add this.
+	ActorsToIgnore.AddUnique(GetOwner());
+
 	UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(Pawn->InputComponent);
 	if (EI == nullptr)
 		return;
@@ -98,16 +100,79 @@ void UGrabComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
 
 void UGrabComponent::OnBeginGrab(const FInputActionValue& Value)
 {
-	for (UInteractableComponent* Grabbale : CurrentGrabbableInRange)
+	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
 	{
-		Grabbale->HandleOnActionStartEvents(this, GrabInputAction, Value, EInteractorType::Grab);
+		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 (UInteractableComponent* Grabbale : CurrentGrabbableInRange)
+	for (auto& Component : CurrentlyGrabbedComponents)
 	{
-		Grabbale->HandleOnActionEndEvents(this, GrabInputAction, Value, EInteractorType::Grab);
+		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/Public/Interaction/Interactables/GrabBehavior.h b/Source/RWTHVRToolkit/Public/Interaction/Interactables/GrabBehavior.h
index 9978823ad96b612d920c6135886d333717a90d7a..d10affdff4aa25e2e4c22818219375580f342c8f 100644
--- a/Source/RWTHVRToolkit/Public/Interaction/Interactables/GrabBehavior.h
+++ b/Source/RWTHVRToolkit/Public/Interaction/Interactables/GrabBehavior.h
@@ -8,6 +8,12 @@
 #include "GrabBehavior.generated.h"
 
 
+DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGrabStart, USceneComponent*, NewAttachParent, UPrimitiveComponent*,
+											 HeldComponent);
+
+DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGrabEnd, USceneComponent*, PreviousAttachParent, UPrimitiveComponent*,
+											 HeldComponent);
+
 UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
 class RWTHVRTOOLKIT_API UGrabBehavior : public UActionBehaviour
 {
@@ -22,6 +28,19 @@ public:
 	virtual void OnActionEnd(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
 							 const FInputActionValue& Value) override;
 
+
+	/**
+	 * Called after the object was successfully attached to the hand
+	 */
+	UPROPERTY(BlueprintAssignable)
+	FOnGrabStart OnGrabStartEvent;
+
+	/**
+	 * Called after the object was successfully detached from the hand
+	 */
+	UPROPERTY(BlueprintAssignable)
+	FOnGrabEnd OnGrabEndEvent;
+
 	UPrimitiveComponent* GetFirstComponentSimulatingPhysics(const AActor* TargetActor);
 
 	// recursively goes up the hierarchy and returns the highest parent simulating physics
@@ -29,4 +48,20 @@ public:
 
 	UPROPERTY()
 	UPrimitiveComponent* MyPhysicsComponent;
+
+	UFUNCTION(BlueprintPure)
+	bool IsObjectGrabbed() const { return bObjectGrabbed; }
+
+private:
+	/**
+	 * Try to detach the object from the hand. Keep this private for now as this does not broadcast the GrabEnd Event
+	 * correctly.
+	 * @return true if object was successfully detached. If detachment failed or if object was not grabbed before,
+	 * return false.
+	 */
+	bool TryRelease();
+
+	bool bObjectGrabbed = false;
+
+	bool bWasSimulatingPhysics;
 };
diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractableComponent.h b/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractableComponent.h
index 8332a897126c46ccb62418b04da0808b6a1bd2b0..da85ad8b003814098fc21e112de423a097a80535 100644
--- a/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractableComponent.h
+++ b/Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractableComponent.h
@@ -46,6 +46,12 @@ public:
 	UPROPERTY(EditAnywhere, BlueprintReadWrite)
 	TArray<UActionBehaviour*> OnActionBehaviours;
 
+	/**
+	 * If true, allow a grab to be triggered by the geometry of a child actor.
+	 */
+	UPROPERTY(EditAnywhere, BlueprintReadWrite)
+	bool bAllowInteractionFromChildGeometry = true;
+
 	UFUNCTION(BlueprintCallable)
 	FORCEINLINE bool HasInteractionTypeFlag(EInteractorType type) { return type & InteractorFilter; }
 
@@ -76,7 +82,7 @@ public:
 								 const FInputActionValue& Value, const EInteractorType Interactor);
 
 	/**
-	 * @brief If click and grab behaviors are not explicitly specified, load all existing ones
+	 * @brief If hover and action behaviors are not explicitly specified, load all existing ones
 	 */
 	void InitDefaultBehaviourReferences();
 
@@ -91,7 +97,4 @@ public:
 	TArray<USceneComponent*> AllowedComponents;
 
 	bool IsComponentAllowed(USceneComponent* Component) const;
-
-private:
-	bool bInitOnce = true;
 };
diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h b/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h
index f2ef437a3c2ec1b11809c61b8716075ac8f673ea..4e18d911a41ad79fbcb4cf4d6d1e914d11f74b5f 100644
--- a/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h
+++ b/Source/RWTHVRToolkit/Public/Interaction/Interactors/GrabComponent.h
@@ -31,6 +31,12 @@ public:
 	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:
@@ -41,8 +47,14 @@ private:
 	void OnEndGrab(const FInputActionValue& Value);
 
 	UPROPERTY()
-	TArray<UInteractableComponent*> PreviousGrabbablesInRange;
+	TArray<UInteractableComponent*> PreviousGrabBehavioursInRange;
 
 	UPROPERTY()
-	TArray<UInteractableComponent*> CurrentGrabbableInRange;
+	TArray<UInteractableComponent*> CurrentGrabBehavioursInRange;
+
+	TArray<TWeakObjectPtr<UInteractableComponent>> CurrentlyGrabbedComponents;
+
+	UInteractableComponent* SearchForInteractable(AActor* HitActor);
+
+	bool bSearchAtParent = false;
 };