Collisions

Different types of collisions.

There are two types of collisions we can use. We can either check if two components are  overlapping each other or we can check the physical blocking hit. What collision overlaps and what collision has physical hit can be defined inside mesh properties. You can read more about collisions in official document. This tutorial is about how to use them in practical case.


Overlapping components

Usually overlapping components are invisible collision boxes that has no physical impact, but they know if they are overlapping each other. Let’s create this kind of collision first. So off we go to create a C++ class based on Actor. Inside header file, we are going to create a SceneComponent for Root and BoxComponent for collision.

UPROPERTY(VisibleAnywhere, BlueprintReadOnly,  meta = (AllowPrivateAccess = "true"))
UBoxComponent* CollisionBox;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly,  meta = (AllowPrivateAccess = "true"))
USceneComponent* RootScene;

Next We create functions that runs when overlap begins. Don’t be afraid of the parameters. You can easily check them out in Unreal Documents, if you don’t remember them. Remember, we can set any name we like to our function.

// Overlap function.
UFUNCTION()
virtual void IamOverLapped(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

// End overlap function
UFUNCTION()
virtual void IamEndOverLapped(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

In .CPP. We create our components inside class constructor. RootScene will be RootComponent of the class and collision box is attached to root.

RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
RootComponent = RootScene;
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
CollisionBox->SetupAttachment(RootComponent);

Next. Let’s create declarations for our functions. Inside functions, we are simply get the name of the actor who is overlapping.

void AC_EmptyActor::IamOverLapped(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
UE_LOG(LogTemp, Warning, TEXT("%s started overlap"), *OtherActor->GetName());
}

void AC_EmptyActor::IamEndOverLapped(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
UE_LOG(LogTemp, Warning, TEXT("%s end overlap"), *OtherActor->GetName());
}

Finally, We need to use something called binding. Binding allows us to bind the overlap event to a function. The event will monitor collisions and launch function when collision happens.  Usually bindings are done in BeginPlay() or inside Initializion functions. We do it in BeginPlay() in this case. In binding we specify the object and the function that is inside that specific object. Thismeans, we don’t need to run function inside this particular class. We can run it in any class if we have object created from it.

Super::BeginPlay();
// Overlap Events
// We create binding.
CollisionBox->OnComponentBeginOverlap.AddDynamic(this, &AC_EmptyActor::IamOverLapped);
CollisionBox->OnComponentEndOverlap.AddDynamic(this, &AC_EmptyActor::IamEndOverLapped);

Inside game, when we overlap the collision Box, we get the name
a1


Colliding components

Next, we create a class, that will have a static mesh component that will register hit events when colliding with something. So let’s create a C++ class based on Actor. Then we will create a Root and a StaticmeshComponent.

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* MainMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
USceneComponent* RootScene;

Then we create a function for HitEvent, we can choose any name we want for the function. We set that in Private section. Again, check the documents if you don’t know / remember parameters!

private:
UFUNCTION()
virtual void OnHitHappen(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit);

Thats all we need to do in header file! Let’s create a declaration for our function first. We are just printing if we detect hit.

void AC_EmptyActor::OnHitHappen(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit)
{
UE_LOG(LogTemp, Warning, TEXT("Component Hit!"));
}

In constuctor we create our components,

RootScene = CreateDefaultSubobject(TEXT("Root"));
RootComponent = RootScene;

MainMesh = CreateDefaultSubobject(TEXT("MainMesh"));
MainMesh->SetupAttachment(RootScene);

All that is left to do inside code is to set our function to be dynamically loaded. Lets do it Inside our BeginPlay(). We set is exactly same as in overlapping component.

Super::BeginPlay();
// OnComponentHit
MainMesh->OnComponentHit.AddDynamic(this, &AC_EmptyActor::OnHitHappen);

That’s all for the code, but we aren’t done yet. We could do next steps inside C++, but lets not. Instead, create a Blueprint based on C++ class we created. Inside Blueprint you should see our components:
a1

Go ahead and click our MainMesh. In Details panel on the right, you need to do three things. First, set some mesh for the MainMesh, second is to tick the ”Simulate Physics” and third, Tick the ”Simulation Generater Hit Events”
a1

Thats it! Now inside our game, place the actor to level, above the ground. When the mesh hits the ground. You should get the message! Notice that it fires constantly, so it may be performance heavy. That is why it is not enabled by default!
a1

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *