Paper2D How to handle drop through platforms?

So basically for a week I’ve been trying to get this simple thing to work, only for the engine to vex me at every turn.

First I wanted to mark the tile number and then I could get a WillCollide event and then reject it if the tile number was in a range of drop through and the collision point was anything other than below me. This is the logical and best solution, however from what I can tell this is not possible in the engine, you get notified of a collision but you can’t then reject it and choose to ignore it, as it has already happened.

So I then set about making channels, you can’t change the channel of a box on a tile map, so I split my tile map into 2 tile maps, one for solid and one for the new “dropdown” channel. From here it was a simple case if I’m going up then I make the player actor not be blocked by “dropdown” so I will pass through it, and otherwise I am, thus I will land upon them. This mostly works however it has a flaw. Namley if you are walking into a “dropdown” platform from the side you will be stopped by it, you have to be able to walk thorugh it. You can’t just make it so you don’t collide against a “dropdown” when you are on the ground as you might be standing on one, and hence need to remain “blocked” by one. To solve this I would cast a Trace down under the player. If I did it for “dropdown” it would find nothing, even when I was atop of one. If I did it for Static it would generate a hit object, but only if I was moving. If you stand still no hit. Odd but I could just cache the last value. This then lead to how do I know that I have a “dropdown” since I can’t just take a hit against that channel as a yes/no. I have to filter it out.
After faffing about I came across Landed which gives me the info I mostly need, and a Hit without having a randomly failing Trace.
But the issue of what am I standing on still stands.
I then figured I could set the two maps as params on my actor in the editor, although this might not work because for some reason ( seems to be something with UE 5.02? ) the objects are lost, so I have to open, compile, reload the level for it to get my actor class. This means a few params that are set get lost each time, and I have to set them each time again. This has led me to set everything in C++ as the editor values get lost, a lot. But still setting two maps in the editor not so bad.
So I exposed them like so

UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
	class APaperTileMapActor* MainTileMap;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
	class APaperTileMapActor* DropThroughTileMap;

and while they appear in the editor
image
they are greyed out and can not be selected, dragged to or changed in anyway. A search found the same issue with 4.1X and the solution was right click on actor and select reload. This option doesn’t appear to be valid in 5 anymore. I have re compiled and reopened the level etc all to no avail. Oh well it probably was going to get lost anyway… so lets do it in code. I know I can use the name, i.e if the name has Drop in it, its the drop one.
Nope, the name is not what you see in the editor but is something along the lines of “Paper2D_TileMap_1” which is useless.
There is a get GetActorLabel but that is Editor only, so useless for this application.
So get each one, then look up the collision then look up the channel and see if its “dropdown” this just seems really convoluted and “not the way to do a really simple thing every game of this type will need to do”. Does explain why no tutorial has ever covered it though :wink:

Also you run into the issue where if you are standing on a “Dropdown” and walk into another “Dropdown” you still want to walk through the other one. Thus I need to make 3 maps, 1 for normal, 1 for even dropdown and 1 for odd dropdown so you never walk into a dropdown while on a dropdown because one is dropdown1 and the other is dropdown2.

What is the proper way to solve this problem?

What is the proper way to find and link a specific per level item to the player actor?

I’m not going lie, I’m having are hard time following the mechanic. With that being said, is this at all related to a “jump through” platform? There are plenty of tutorials out there for that so maybe there’s some techniques presented that could be useful.

Tutorial Classic Pass Through Platform Using Paper2D in Unreal Engine 4 - YouTube

Jumping Through One-Way Platforms! | How To Make YOUR OWN SSB Game | Unreal & C++ Tutorial, Part 24 - YouTube

Jumping Through Platforms in UE4 Blueprints (Super Mario mechanic!) - YouTube

Thank you for the videos, yes drop through is jump through or fall though or pass through.

The first one, makes a separate object, and does a ray cast. Which I guess not using a tile map, and an another object, maybe the ray cast will work when not moving, and maybe it will detect the fallThrough type as it did in 4.x as per the video?. It still doesn’t solve the horizontal problem, in that it relies upon the platform being thin and not stacked on top of each other.

The second one again uses the ray cast which fails, and again relies upon the platforms being sparse from each other. Also says c++ but actually uses a blueprints :wink: The tutorial experience.

Third one also uses a ray cast.


so when I walk to the right I should walk through the platform, this is easy enough as it can be set to not collide with it. That works. However if I jump up on to the first platform, so now the platform must collide with the player I then should also be able to walk through the next one on the level above. But you won’t because you are colliding with those channels so you can stand on the one you are on.
However this also needs Trace to work, which is only works when you are moving. And it needs for me to be able to tell which type of object I’m standing on, if its the solid or dropThrough type which needs a way for me to be able to find or specify them.

I added a test sprite to test to see if the trace works with it and just fails on the TileMap. It fails on it as well.


The set up

I tested with both ignore and overlap. Both settings fails to generate a valid Actor pointer.

	//Hit contains information about what the raycast hit.
	FHitResult Hit;

	//The length of the ray in units.
	//For more flexibility you can expose a public variable in the editor
	float RayLength = 10;

	//The Origin of the raycast
	FVector StartLocation = GetActorLocation() + FVector(0.0, 0.0, -HalfHeight*1.1);

	//The EndLocation of the raycast
	FVector EndLocation = StartLocation + FVector(0.0, 0.0, -HalfHeight);

	//Collision parameters. The following syntax means that we don't want the trace to be complex
	FCollisionQueryParams CollisionParameters;
	CollisionParameters.bIgnoreTouches = false;
	//CollisionParameters.AddIgnoredActor(this);

	//Perform the line trace
	//The ECollisionChannel parameter is used in order to determine what we are looking for when performing the raycast
	//ActorLineTraceSingle(Hit, StartLocation, EndLocation, ECollisionChannel::ECC_WorldStatic, CollisionParameters);
	ActorLineTraceSingle(Hit, StartLocation, EndLocation, DropDownChannel, CollisionParameters);

	//DrawDebugLine is used in order to see the raycast we performed
	//The boolean parameter used here means that we want the lines to be persistent so we can see the actual raycast
	//The last parameter is the width of the lines.

	GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, FString::Printf(TEXT("component %X Actor %X"),Hit.GetComponent(), Hit.GetActor()));
	if (Hit.GetActor())
	{
		DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, false, 0.5, 0, 1.f);
	}
	else
	{
		DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Green, false, 0.5, 0, 1.f);
	}

If I make the Trace ActorLineTraceSingle(Hit, StartLocation, EndLocation, ECollisionChannel::ECC_WorldStatic, CollisionParameters); then I will get red lines, but only when moving.

For those that come after

the issue is

ActorLineTraceSingle(Hit, StartLocation, EndLocation, DropDownChannel, CollisionParameters);

On 5 this will return something which is the actor for the map, however it doesn’t see to handle collision types correctly. On 4 this will return nothing. I could only get it to return the character when I adjust its position to collide with the character ( even if I put the character in the ingoreActors list ).
What you need to do instead for this case is use

GetWorld()->LineTraceSingleByChannel(TraceHit, StartLocation, EndLocation, DropDownChannel, CollisionParameters);

which will work as expected.