Download

Proper way to move an Actor / Collision Not Working

So I created my own custom “physics” based Bullet which is comprised of a collision component with a mesh attached to it basically. However, I can’t get Collision (events or actor blocking) to work.

I’m attempting to design a bullet that I have full control over how it is handled by creating all the custom movement and “physics” simulation inside the Bullet class its self, without using a Movement Component since I didn’t like it, nor the ProjectileMovementComponent really. However. Getting the bullet to actually move has been a big hassle for some reason. I couldn’t figure out how you are suppose to properly move an actor with collision detection. I’ve been using SetActorLocation() per tick, with bsweep = true which alone took a while to do, however the bullet just flies through everything regardless of its Collision profile, I’ve tried OverlapAll, BlockAll, Custom Ones, etc. The projectile will not stop at objects nor will the overlap/hit events call when it goes through an object. BUT if the object goes through IT, it will.

Example: Bullet is fired (very slow movement) and me, the player with my pawn, walk into its path and let it hit me (no detection). But, if I fire the bullet, and run into it (meaning I’m moving this time) it fires off the hit/overlap events.

So, anytime I fire my bullet things that don’t move into it (idling pawn, world, staticmeshes) don’t call any collision. I’m taking it that I’m basically just setting the location of the actor without any collision checks using SetActorLocation() but I can’t seem to find the old UDK/uScript versions of MoveTo/MoveToward() that attempted a move rather than just set the location. Am I just missing something major?

Code!




#include "ROT.h"
#include "ROTPlayerSoldier.h"
#include "ROTProjectileMovementComponent.h"
#include "ROTBullet.h"

DEFINE_LOG_CATEGORY_STATIC(BulletLog, All, All)

AROTBullet::AROTBullet(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	PrimaryActorTick.bCanEverTick = true; //Enables ticking

	SceneComponent = PCIP.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneComp"));
	RootComponent = SceneComponent;
	OnActorBeginOverlap.AddDynamic(this, &AROTBullet::ReceiveActorOverlap);

	
	Mesh = PCIP.CreateOptionalDefaultSubobject<UStaticMeshComponent>(this, TEXT("MeshComp"));
	Mesh->AttachParent = SceneComponent;
	Mesh->SetCollisionProfileName("NoCollision");
	Mesh->SetRelativeRotation(FRotator(0, -90, 0));
	
	
	//Components 
	CollisionComponent = PCIP.CreateOptionalDefaultSubobject<UCapsuleComponent>(this, TEXT("CollisionComp"));
	CollisionComponent->AttachParent = SceneComponent;
	CollisionComponent->SetCapsuleSize(1.0f, 2.0f, true);
	CollisionComponent->SetRelativeRotation(FRotator(-90,0,0));
	CollisionComponent->BodyInstance.SetCollisionProfileName("OverlapAll");
	CollisionComponent->bTraceComplexOnMove = false;
	CollisionComponent->bGenerateOverlapEvents = true;
	CollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &AROTBullet::ReceiveOverlap);

	
	ArrowComp = PCIP.CreateOptionalDefaultSubobject<UArrowComponent>(this, TEXT("ArrowComp"));
	ArrowComp->AttachParent = SceneComponent;
	ArrowComp->RelativeLocation = FVector(0,0,0.75);
	ArrowComp->ArrowSize = 0.075;
}


void AROTBullet::BeginPlay()
{
	UE_LOG(BulletLog, All, TEXT("===AROTBullet::BeginPlay()==="));
}

void AROTBullet::InitSimulation(FVector DirectionInput,AROTPlayerSoldier* InstigatorInput)
{
	if (InstigatorInput)
		Instigator = InstigatorInput;
	Direction = DirectionInput; //Sets the direction of our projectile
	DrawDebugLine(GetWorld(), GetActorLocation(), GetActorLocation() + (Direction * 4096), FColor::Blue, true);	

	
	bSimulating = true;
}

void AROTBullet::Tick(float DeltaSeconds)
{
	DrawDebugSphere(GetWorld(), GetActorLocation(), 4, 8, FColor::Red, false); //Draws a sphere so we can see our bullet travel
	
	//Draws our forward rotation so we can see where we're heading
	FVector ForwardDir;	
	ForwardDir = FRotationMatrix(GetActorRotation()).GetUnitAxis(EAxis::X);

	DrawDebugLine(GetWorld(), GetActorLocation(), GetActorLocation() + (ForwardDir * 256), FColor::Red, true,3.5);

 
 //Only simulate when ready
 if (bSimulating)
	  ProcessMove();
}

void AROTBullet::ProcessMove()
{
	if (Velocity <= 0)
	{
		UE_LOG(BulletLog, Warning, TEXT("===AROTBullet::ProcessMove()==="));
		UE_LOG(BulletLog, Warning, TEXT("Velocity for bullet is 0!!!!!"));
	}
	FVector FinalDir = GetActorLocation() + (Direction * Velocity);
	
     SetActorLocation(FinalDir, true); 
}


void AROTBullet::ReceiveActorOverlap(AActor* OtherActor)
{
	GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Blue, TEXT("ACTOR OVERLAP!!!!"));
}

void AROTBullet::ReceiveOverlap(AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Blue, TEXT("Component OVERLAP!!!!"));
}

//A HIT is any object that STOPS the bullet (probably won't be many)
void AROTBullet::ReceiveHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	GEngine->AddOnScreenDebugMessage(-1, 9.5f, FColor::Green, TEXT("HIT!"));
	bSimulating = false;
}

void AROTBullet::ReceiveActorBeginOverlap(class AActor* OtherActor)
{
	GEngine->AddOnScreenDebugMessage(-1, 9.5, FColor::Green, TEXT("ReceiveActorBeginOverlap (UE Function)"));
}




AM assuming you want to catch the event when the projectile hits the player?
To detect a blocking hit you need to override AActor::OnActorHit also i asked a qustion about collision a while back you can check that out here
Hope it helps.

The issue here is that the CollisionComponent is not the RootComponent. When you use SetActorLocation(…), that sweeps the RootComponent, and teleports attached components, so they don’t get hit events (only overlaps). You need to set the collision component as the root instead.

Zak,

I ran across your post in this thread when I was having problems with the same issue. I tried to fix my basic debugging project but it didn’t work. At some point I decided to start completely over after I suspected my project was corrupted (most likely from a series of forced blueprint deletes or renaming).

I created a new project armed with the information from your post and the collision worked. I’m responding here because I thought you might be interested in looking at the bad project to see if there was a different issue. Here is my question and answer to myself. I attached the original debugging project and the solution project.

UE4 Cube Mesh Not Colliding using SetRelativeLoc