Devlin Willis

UE4 Gameplay Engineer
Independent Contractor for 3 years

Tutorial: Interactable Foliage in BP only [4.15]

Unless you’ve been living under a rock for the past 5 or so years, you’ll know that the survival genre has absolutely flooded the market. In fact, this news is so old at this point – the genre is no longer the big trend in games. This is a repost from my old blog, nonetheless, which will guide you towards having resource nodes that start their life as foliage. I’ve rewritten the entire post as I suck at migrating sites and have left my posts irrecoverable.

Well, if for some reason you’re starting to make an ARK clone, you might have noticed something. Placing 100s of resource actors is tedious. Perhaps you’ve noticed that placing 1000s of actors has resulted in your game running terribly. FEAR NOT!!! The solution to both of the problems is to place foliage rather than actors. I hear you ask:

B- b- but Devlin!!! If I have foliage I cannot interact with it! 

I have a simple setup which will demonstrate one way to interact with your foliage. You won’t need very many classes, and two of them should already exist in your game. If you prefer, I’ve a video version of this post – here.

Here are all of my .uassets

BP_Collector is my pawn class, this one can just be your own pawn. I also have a basic actor type for my resource node – again you can replace it with your own. I’ve made a mesh, but your mesh will be better and should be used instead of mine – note that you can’t rotate the mesh in the actor for this to work out of the box. The classes aren’t the important thing here.

For those of you unaware how to conduct a line trace, here is a basic example. Notice that I’m using a literal input event – these should be replaced with InputActions. Never use a literal input for anything other than a quick test. Because I don’t have a unique setup for where I want the trace to be located or directed from, I’m going to just use the camera rotation and the pawn’s location. Notice that I scale the camera X vector by 1500. This gives me an offset of 1500 units in the direction the the camera was looking. I can add that the location of the pawn to give me a location that is 1500 units from the pawn in the direction the camera is looking.

Here we get a bit more complicated. This is the resulting HitResult structure, which tells us many things about the trace we just did. We’re mainly going to be interested in the component, actor, and the hit item. Understanding the underlying engine here will allow us to exploit the HitResult to gain access to the foliage where we otherwise may not have it. We’d want to trace anyway, but since our trace can hit the foliage this will provide us with a direct reference to the foliage component.

A quick dive into source code was enough to hint to me that this was possible (and the specific type to cast to), so if we hit the foliage component we can cast to HierarchicalInstancedStaticMeshComponent, allowing us to get the transform of the specific foliage instance that we hit. We spawn our custom resource node actor – here we might want to do a comparison to spawn a specific KIND of resource – and remove the instance that we just traced to. Note, the instance ID is most likely invalid at this point. If another node after this needed the transform of the previously present instance, we’d have to cache it or use the spawned actor’s transform.

One last clever trick here is that we immediately call Interact on our new actor. We want the game to feel responsive, so, calling Interact here allows the player to think they just hit a tree rather than merely causing it to be intractable from then on. Also, if we didn’t hit a foliage component we need to handle that case. So we attempt to cast the hit actor as a BP_Resource. If that’s worked then we hit a resource node and should call Interact on it. But what does that do for us? Well. In my case, not much. In your case, it might decrement an integer, or provide some payout. Maybe it starts a bonafide timer. Who knows. Anyway, you need to make sure that you set up your foliage to block the right channel and use the right mesh. I’m just going to do BlockAll, but you could also do a specific trace channel. 

Does this actually work, Devlin? Have I wasted about 5 minutes of my life?

Why yes, argumentative stranger. Yes it DOES.