Dedicated Server Bug with Interactive Foliage

If you are using regular Listen servers, then this does not apply to you!

It has come to my attention that running the Foliage System on Dedicated Servers causes the server to crash.

Assertion failed: Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:Runtime/Core/Public\Containers/Array.h] [Line: 634]
Array index out of bounds: 3530 from an array of size 0

I have a simple solution for this, all you need to do is change a few lines of Engine code to fix it, this is because the Dedicated Server doesn’t consider the Instance array valid since they are not being rendered on the server.

Open up “C:\UnrealEngine\Engine\Source\Runtime\Engine\Private\HierarchicalInstancedStaticMesh.cpp”

Go to line 2394 (UE Source 4.17.2)

Inside the function UHierarchicalInstancedStaticMeshComponent::BuildTreeAsync()

 

Old code

const bool bMeshIsValid =
// make sure we have instances
PerInstanceSMData.Num() > 0 &&
// make sure we have an actual staticmesh
GetStaticMesh() &&
GetStaticMesh()->HasValidRenderData() &&
// You really can’t use hardware instancing on the consoles with multiple elements because they share the same index buffer.
// @todo: Level error or something to let LDs know this
1;//GetStaticMesh()->LODModels(0).Elements.Num() == 1;
}

New code

// Verify that the mesh is valid before using it.
bool bMeshIsValid =
// make sure we have instances
PerInstanceSMData.Num() > 0 &&
// make sure we have an actual staticmesh
GetStaticMesh() &&
GetStaticMesh()->HasValidRenderData() &&
// You really can’t use hardware instancing on the consoles with multiple elements because they share the same index buffer.
// @todo: Level error or something to let LDs know this
1;//GetStaticMesh()->LODModels(0).Elements.Num() == 1;

if (GetNetMode() == NM_DedicatedServer)
{
bMeshIsValid =
// make sure we have instances
PerInstanceSMData.Num() > 0 &&
// make sure we have an actual staticmesh
GetStaticMesh() &&
// You really can’t use hardware instancing on the consoles with multiple elements because they share the same index buffer.
// @todo: Level error or something to let LDs know this
1;
}

Adding new resources to the Foliage System 1.2

In the latest version of the Foliage System, I’ve made it super simple to add new Resources!

All you have to do now is open up DT_Resources data table and sets the mesh(es) for your resource, and you’re done!

 

 

You can now have an array of meshes for the same resource, if they have the same rewards & uses, you no longer have to have multiple entries and blueprints for each actor/resource!

Adding new resources to the Foliage System

THIS GUIDE IS FOR THE OLD 1.0 VERSION, IF YOU ARE USING THE FOLIAGE SYSTEM 1.2 THEN USE THIS GUIDE:

Adding new resources to the Foliage System 1.2

 

 

 

 

 

Create a Child Blueprint Class of the BP_MasterResource

Open DT_Resources Data Table and add a New Row, set “ResourceToSpawn” to your new Child Blueprint Class that you just created.

Inside DT_Resources, make sure you set ResourceMesh to EXACTLY the same as your foliage mesh.

Open up your Child Blueprint Class, change it’s FoliageSettings to “MyNewTree”.

IMPORTANT! When painting your terrain with foliage, MAKE SURE that you set the foliage to Block All.

And that’s it!

Integrating the Foliage System with the Survival Template (MSGT)

Begin by migrating the FoliageSystem to your MSGT Content folder

 

 

Add the C-Foliage component to your SurvivalController

 

 

SurvivalController > GetActionType() function

 

 

Copy all the Events and variables from GS_FoliageGameState Blueprint
Paste them into the SurvivalGameState Blueprint.

 

 

You'll also have to re-create the 2 missing
functions inside the SurvivalGameState

 

 

Open the Str_Resources struct file inside /FoliageSystem
change the RewardWhenHarvested struct type to "Str_SGT_Inventory_Entry"

 

 

Change the Struct type inside BPI_Foliage, see image below.

 

 

Open the BP_MasterResource Blueprint, re-connect the
missing link inside GetRewardFromFoliageActor() function.

 

 

Replace the old Blueprint nodes with the 
ones you see below inside C-Foliage Component

 

 

 

Open the function ReplaceInstanceWithActor inside C-Foliage Component
replace GS_FoliageGameState with SurvivalGameState.

 

 

Edit DT_Resources, change the Reward settings to whatever you
 want this Tree to reward the player with.

 

 

Make sure the ResourceMesh is EXACTLY the same as
the Mesh you are "planting" with your Foliage Placement tool.

 

 

SurvivalController > BeginPlay, it should look like this: