I need to render a tile grid where each tile is a different color, along a spectrum between, say, red and green. This is in-the game, not the UI.
There doesn’t seem to be a painless way to do this.
Any suggestions? I’m planning to just use a blueprint with a properly-sized plane primitive inside it.
Do I need to create a new UMaterialInstanceDynamic at runtime? Or is there anything I can do more directly in C++ or Blueprint to just tweak the color?
OK, this turned out to be amazingly easy once I started looking in the right place.
It is, of course, kind of a noob question, but I figured I’d post the answer here in case anyone would like to make a tutorial for it (Rama?).
All that code was really unnecessary, though I do appreciate the help. Here are the instructions to do what I was trying to do:
- Make a new class derived from AActor for the tiles (I called this AOCOverlayTile for my game).
- Add a new UFUNCTION to the header; make sure it is a BlueprintImplementableEvent. Call it “OverrideColorEvent” (or something like that) and have it take an FVector for the RGB values as a parameter (non-const, pass by value).
- Make a new material whose BaseColor is a VectorParameter. Make it any color you like, and call it “Color.”
- Make a new blueprint object for the tiles (mine is called OverlayBlueprint). Put a static mesh inside it (underneath a Scene object) and stretch it to the appropriate size and apply the material you specified in the last step to the static mesh component. Make sure you re-parent this blueprint to the class you created (AOCOverlayTile)
- Give the blueprint a graph that creates a Dynamic Material Instance in its EventReceiveBeginPlay, and then sets the value of the Color in response to the event you created, like so:
Finally, you can trivially spawn a new tile and then set the color on it at runtime like so:
AOCOverlayTile * tile = CastChecked(m_pWorld->SpawnActor(OverlayBlueprintClass, &rLocation, &rRotation, spawn_params), ECastCheckedType::NullAllowed);
tile->OverrideColorEvent(FVector(0.1f,0.6f,0.24f));
Or better yet, change OverrideColorEvent() to take an FLinearColor instead of an FVector, so no conversion is required.
Dear Mothership,
It’s really not hard to do, especially if you are generating the tiles themselves at run time.
I have tutorial on interpolating color
http://forums.epicgames.com/threads/973803-Tutorials-Entry-Level-UE4-C-Overview-Q-amp-A-gt-Convert-FString-to-Numbers-FNames?p=31695425&viewfull=1#post31695425
and material instances dynamic
http://forums.epicgames.com/threads/972861-Tutorial-Compile-C-for-UE4-Code-Samples-For-You-(New-Create-Your-Own-C-HUD)?p=31653223&viewfull=1#post31653223
what you want is a material instance dynamic
and then you can go between colors by using a Lerp function!
Entire thing can be programmatic as a result 
.h
UPROPERTY()
UMaterialInstanceDynamic* TheMatInst;
FLinearColor Red;
FLinearColor Green; //could also pass these into the initialize function
void InitializeTile(float TheColorAlpha);
.cpp
//constructor
{
Red = FLinearColor(1,0,0,1);
Green = FLinearColor(0,1,0,1);
}
//Create
void class::InitializeTile(float TheColorAlpha)
{
TheMatInst = UMaterialInstanceDynamic::Create(BaseMat, this); //BaseMat must have material parameter called "Color"
//Lerp Color
FLinearColor InterpedColor = FMath::Lerp(Red,Green,TheColorAlpha);
//set Material Param
TheMatInst->SetVectorParameterValue(FName("Color"), InterpedColor);
//Set Material
StaticMeshComponent.SetMaterial(0, TheMatInst);
//Done!
}

Rama
Thanks, Rama – I’d seen this before, and this is helpful, but I am trying to figure out how best to get the static mesh component and the base material.
Currently, my overlay tile is an actor blueprint with a plane primitive inside it. Is that the right way to do it? And if so, I am not seeing a good way to get the static mesh for the plane primitive. I am iterating over the individual components of the blueprint (TArray AActor::Components) but don’t see a good way to get anything with a SetMaterial() call from those … What am I missing?
well it would definitely be easiest to spawn the tiles and set their color at runtime
because even if you iterate over your tiles, pre-made in editor
how are you going to programmatically get exactly the right order to lerp the color over each tile in the right order?
whereas
#if you create the tiles at runtime
you pick a start location, and you start spawning in a line, and with each new tile you create a material instance dynamic and set the lerped color value
thus order is done for you since you set color as you spawn
Is there anyway you can spawn stuff at runtime given your project context?
#Non Runtime Alternative
You could just create a bunch of material instance constants (rather than dynamics) in the editor
and set the various shades of your color spectrum that way
it depends how many tiles you have
than you can just click around in the world setting the various color values just right
Rama
Well … Yeah, of course I am trying to create them at runtime. That’s what I’ve been saying all along.
I am using a blueprint class to define the UClass to pass in to SpawnActor() for each tile I create.
That works fine – I have no problem spawning the new tile objects. Again, the problem is accessing the actual static mesh components inside and finding a place where I can call SetMaterial() on them.
My question is, how to apply your code to a newly-spawned blueprint object? Again, I’m not seeing the way to get pointers to the base material and the static mesh inside the blueprint.
I’d think I could just call AActor::GetRootPrimitiveComponent() to get the root primitive component and call SetMaterial() on that, but GetRootPrimitiveComponent() seems to return NULL …
My apologies since I’m sure it’s a noob question; I’m still learning the ins and outs of the engine.
If you create the static mesh component via the c++
then you will have a pointer to it
Instead of my asset path below, replace with the full path of your plane static mesh
StaticMesh'/Game/chestwdrapes.chestwdrapes'
right click and select “get full path”
#C++ Code
Here’s what I use for static mesh components that I add to my character via c++
Important: Make sure to recompile your blueprint in the editor after adding the plane primitive component via the C++
.h
public:
/** Chest Armor */
TSubobjectPtr ChestArmor;
UStaticMesh* RoyalChestArmorAsset;
.cpp
//Chest
static ConstructorHelpers::FObjectFinder StaticMeshOb(TEXT("StaticMesh'/Game/chestwdrapes.chestwdrapes'"));
RoyalChestArmorAsset = StaticMeshOb.Object;
//Was Asset Found?
if (RoyalChestArmorAsset != NULL)
{
//create new object
ChestArmor = PCIP.CreateDefaultSubobject < UStaticMeshComponent > (this, TEXT("RoyalChestMesh"));
Components.Add(ChestArmor);
ChestArmor->SetStaticMesh(RoyalChestArmorAsset);
ChestArmor->bOwnerNoSee = false;
ChestArmor->bCastDynamicShadow = false;
ChestArmor->CastShadow = false;
ChestArmor->BodyInstance.SetObjectType(ECC_WorldDynamic);
ChestArmor->BodyInstance.SetCollisionEnabled(ECollisionEnabled::NoCollision);
ChestArmor->SetHiddenInGame(false);
} //asset not null
#Attaching
not sure if you have to attach but if you do you can use
ChestArmor->AttachTo(GetRootComponent());
#Setting Material
if(ChestArmor) ChestArmor->SetMaterial(0, TheMaterial);
Thanks for the help, Rama … I am trying to do it your way and not seeing anything showing up at all. Not sure why.