Micro-tutorial: Per instance foliage logic/effects using per instance custom data

This is an extension of the methods covered here:
Individual Foliage Logic using Per-Instance Custom Data [UE4/UE5] - YouTube

Problem:
You want to do something to your foliage instances, but how do you get access to the individual instances?

Demonstration:
In this example I will show how I am fading trees that are between the camera and the player character in a top down game.
treesfade

Setup:

  • On material that I want to fade, I add PerInstanceCustomData node


    Note the assigned number (0). This identifies the CustomData - same idea as naming a variable.

  • Make new blueprint of the following class:
    image

  • In the new blueprint, on begin play, assign to event OnInstanceTakePointDamage. For now just set a print string.

  • On PlayerCharacter make a Multisphere trace. Also make a new trace channel for trees in project settings. Have the sphere trace search for that trace channel.

  • Set your foliage instances to OVERLAP (not block!) the Trees trace channel. Why overlap, not block? Block will prevent the sphere trace from penetrating more than 1 instance.

  • Back on the sphere trace on the character, have it loop through hit results and call for Apply Point Damage to the hit target. You don’t need to filter for class or tags or anything - the trace channel is only looking for trees so that is all the filter you need.

  • Now if you play, the sphere trace hitting foliage instances should call that print string. Now we will focus on doing something with the custom per instance data. First, set these prerequisites in the class defaults of the custom instance blueprint:
    image

  • Then, pass the hit index into Set Custom Data node:

  • This will turn the fade effect on that I made in the material. But how to turn it back off? And also, we want to ONLY turn it off if the instance is not currently still blocking view between camera and player character.
    To accomplish this , we need two arrays. One is “new indexes” the other is “old indexes.” When we first identify an index from the point damage event, we will put it into the array “new indexes”.

  • On a timer with a few seconds looping, we will reset the fade effect. The ResetFade event will ask the question, “what are all the indexes that need to be reset?”, and “are any of them still currently blocking the view? so they should be excluded.”



    To answer that question, pass the new indexes into the old indexes array, and then clear it.
    Then run a for each loop to check if indexes in the old array match the new array. Because the new array is getting updated very rapidly and the old array is only cleared every so often, this will be an accurate way to check what indexes are still current in the line of fire of our sphere trace.
    After that, if we did not find that the instance was still getting hit from the trace, we turn off the custom data parameter and remove it from the old array.

How to discriminate between different types of foliage?

  • Assign a different component for any foliage types you want to operate separate logic:
    image
    image
    image

How to record data for each instance?

  • In the video linked at beginning the author shows how to make a struct array that mirrors the instance count so that you can record data for each instance.

More info:
UE4 Tutorial - Per Instance Custom Data - YouTube
WTF Is? Multi Sphere Trace By Channel in Unreal Engine 4 ( UE4 ) - YouTube

Notes on style:

There is of course many ways to fade things, either based on render passes, distance from camera, etc. I worked out this method because I wanted the entire individual trees to fade, purely for artistic taste. Setting up some materials for a sphere mask is a bit easier to setup, but I didn’t like that it makes it hard to know whats actually around the character.

Anyway, once you have the setup figured out, you can theoretically do almost anything with each instance.

1 Like