Assign custom collision profile to Actor

Hello forums,

I’m very new to the Unreal Engine and game programming. I have an AActor class in my project called GameItem, which I’m using for items that the player can interact with (pick up, store in inventory, use, etc.) and I’m having trouble getting it to assign my custom collision channel. I created a new Object Channel called “GameItem” and have it set to Block by default. I then modified my character pawn to always overlap this object channel. So in theory, these game items should collide with everything in the world except my player.

Here is my code in the constructor of my GameItem class:



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

	StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RootComponent"));

	StaticMeshComponent->BodyInstance.SetCollisionProfileName("GameItem"); // This part doesn't seem to be working. It should apply the GameItem object channel when the item is created, right?
	StaticMeshComponent->SetWalkableSlopeOverride(FWalkableSlopeOverride(WalkableSlope_Unwalkable, 0.f));
	StaticMeshComponent->CanCharacterStepUpOn = ECB_No;

	RootComponent = StaticMeshComponent;
}


What am I missing here?



StaticMeshComponent->BodyInstance.SetCollisionProfileName("GameItem"); // This part doesn't seem to be working. It should apply the GameItem object channel when the item is created, right?


This sets the collision profile of the body instance of the static mesh component to the profile “GameItem”. Usually static meshes are automatically assigned the profile “WorldStatic” or “WorldDynamic”. Other profiles are “Pawn”, “Ragdoll” etc. You can find them all in ProjectSettings->Collision.

You have to setup a custom collision profile named “GameItem” in order for this to work.
Here you set any object with the GameItem Profile’s collision response to other profile. For example, you can set it to collide with the world (WorldStatic) but ignore Pawns.

Also, not 100% sure setting BodyInstance’s collision actually works. Set the whole StaticMeshComponent instead.

I did this though, I created a custom object channel called “GameItem”, as I stated in the opening post, which is set to overlap my character. It just doesn’t seem to be getting properly applied with this code. I also tried applying it directly to the StaticMeshComponent rather than BodyInstance but it still doesn’t seem to have any effect.

Apart from creating a profile - did you give it a custom object channel as well? Otherwise it’s assigned another object channel (“Pawn”, “WorldStatic”) etc. You have to setup the collision responses on both channels.
If you’re playing this online, make sure the collision channel is set on both server and client. Otherwise you’ll have a discrepancy which won’t work.

I believe I’ve done all that needs to be done, but maybe I’m mistaken. I have a custom Object Channel defined in Project Settings -> Engine -> Collision -> Object Channels called “GameItem”. I also made a collision preset of the same name which blocks everything except a Pawn class. I even tested it in-game by placing a prop in the world and assigning it the “GameItem” collision preset, and it worked just fine. But the game items are still being spawned with the default actor collision profile.

I even tried setting the GameItem profile to ignore all by default, and even then it had no effect. So it’s pretty clear that the profile isn’t being applied at all to my game items when they are spawned.

Update:

I tried calling SetCollisionProfileName from BeginPlay instead of the constructor, and now it seems to be working. I just don’t understand why it can’t be set in the constructor…

Ah, can’t believe I missed that. No you can’t set it in the constructor, it’s “too early” since the components haven’t been initialized yet.
You can override PostInitializeComponents() though and set it there if you with to set it before BeginPlay()

Resurrecting this post so it can help anyone that comes across this.

Tested in Unreal Engine 5.1 and can see that it sets the CollisionProfileName perfectly fine in the constructor. So you can see the Blueprint of the class with the updated ProfileName before even spawning the Actor in the scene.

Code snippet:

AMyActor::AMyActor() : Super()
{
	CollisionComponent = CreateDefaultSubobject<UCapsuleComponent>("CollisionComponent");
	if (BodyHurtBoxComponent != nullptr)
	{
		CollisionComponent->SetupAttachment(MeshContainer);
		CollisionComponent->InitCapsuleSize(30.0f, 70.0f);
		CollisionComponent->SetCollisionProfileName("MyCustomCollision");
	}
}

Bear in mind you have to define this custom collision in:

Project Settings -> Engine -> Collision -> Presets.
1 Like