No hit event when RootComponent is USceneComponent and no physics simulation

Create a project Blank from blank template, place PlayerStart at (0,0,91.5) and override the game mode below.

Game mode:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyGameModeBase.generated.h"


UCLASS()
class BLANK_API AMyGameModeBase : public AGameModeBase
{
	GENERATED_BODY()
	void BeginPlay() override;
};

//=======================================
#include "MyGameModeBase.h"
#include "MyActor.h"
#include "Kismet/GameplayStatics.h"


void AMyGameModeBase::BeginPlay()
{
	Super::BeginPlay();

	GetWorld()->SpawnActor<AMyActor>(FVector(500, -500, 100), FRotator(0));
	GetWorld()->SpawnActor<AMyActor>(FVector(500, 500, 100), FRotator(0))->bToPositiveInfinity = false;
}

Actor:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

class UBoxComponent;

UCLASS()
class BLANK_API AMyActor : public AActor
{
	GENERATED_BODY()

public:
	AMyActor();
	bool bToPositiveInfinity = true;

protected:
	void BeginPlay() override;
	void Tick(float DeltaTime) override;

	UPROPERTY(VisibleAnywhere)
	USceneComponent* Scene;

	UPROPERTY(VisibleAnywhere)
	UBoxComponent* Box;

	UFUNCTION()
	void OnBoxComponentHit(
		UPrimitiveComponent* HitComp,
		AActor* OtherActor,
		UPrimitiveComponent* OtherComp,
		FVector Norm,
		const FHitResult& Hit);
};

// =============================================
#include "MyActor.h"
#include "Components/BoxComponent.h"



AMyActor::AMyActor()
{
	PrimaryActorTick.bCanEverTick = true;


	bool bUseSceneAsRoot = false; // Change this manually! Using live coding is fine too! 

	Box = CreateDefaultSubobject<UBoxComponent>("BoxComponent");
	Box->SetCollisionProfileName(UCollisionProfile::BlockAll_ProfileName);
	Box->SetHiddenInGame(false);
	Box->SetLineThickness(10.f);
	Box->SetRelativeScale3D(FVector(2.f));

	//Box->SetSimulatePhysics(true);
	//Box->SetNotifyRigidBodyCollision(true);


	if (bUseSceneAsRoot)
	{
		Scene = CreateDefaultSubobject<USceneComponent>("SceneComponent");
		SetRootComponent(Scene);
		Box->SetupAttachment(Scene);
	}
	else
	{
		SetRootComponent(Box);
	}
}


void AMyActor::BeginPlay()
{
	Super::BeginPlay();
	Box->OnComponentHit.AddDynamic(this, &ThisClass::OnBoxComponentHit);
}

void AMyActor::OnBoxComponentHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector Norm, const FHitResult& Hit)
{
	UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__));
}


void AMyActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if (bToPositiveInfinity)
	{
		AddActorLocalOffset(FVector(0, 5, 0), true);
	}
	else
	{
		AddActorLocalOffset(FVector(0, -5, 0), true);
	}
}

Why can’t we use USceneComponent as RootComponent here?

Due to how AddActorLocalOffset is implemented. It uses the root component. The key part is the call to

MoveComponentImpl, with the SceneComponent as the root it will call USceneComponent::MoveComponentImpl which doesn’t check for collision, with the Box as the root it calls UPrimitiveComponent:MoveComponentImpl which does.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms