Hi guys,
I recently added dynamic material instances for my weapons in my game and figured i would make a little tutorial to help people get started if they wish to do this in the shooter sample code project, as with any tutorial this may not be the correct or only way to do this, but here we go. Its pretty simple, its a
lazy sunday and i felt like sharing. I will try and share this in a readable way, this is the first tutorial i have written, so bare with me
In this example i am adjusting the brightness of a Scalar called “EmissiveBrightness” in the matieral used for my weapons. There are three bools, if enabled one will enable or disable the use of the MID, enable or disable server replication, and enable or disable the actual effect we have created here.
First off we need to add the following into ShooterWeapon.h, under protected.
/** material instances*/
UFUNCTION(BlueprintCallable, Category = Pawn)
void UpdateWeaponMaterialEffects(float NewParam);
/** material instances server call*/
UFUNCTION(BlueprintCallable, reliable, server, WithValidation, Category = Pawn)
void ServerUpdateWeaponMaterialEffects(float NewParam);
/** enable dynamic mat effects */
UPROPERTY(EditDefaultsOnly, Category = Effects)
bool UseDynamicMatEffects;
/** replicate dynamic mat effects */
UPROPERTY(EditDefaultsOnly, Category = Effects)
bool UseReplicatedDynamicMatEffects;
/** dynamic mat effects based on ammo use */
UPROPERTY(EditDefaultsOnly, Category = Effects)
bool UseRemainingAmmoMatEffect;
Now we can move onto ShooterWeapon.cpp:
First off, for the prupose of this tutorial, i will set all the bools to true.
in:
AShooterWeapon::AShooterWeapon(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
set the bools to true.
UseDynamicMatEffects = true;
UseReplicatedDynamicMatEffects = true;
UseRemainingAmmoMatEffect = true;
Now, when the weapon actor is created we want to setup the MIDs so that we have some to access later. We do this for both weapon meshes.
in:
void AShooterWeapon::PostInitializeComponents()
// create material instance 1st person mesh
for (int32 iMat = 0; iMat < Mesh1P->GetNumMaterials(); iMat++)
{
MeshMIDs.Add(Mesh1P->CreateAndSetMaterialInstanceDynamic(iMat));
}
// create material instance 3rd person mesh
for (int32 iMat = 0; iMat < Mesh3P->GetNumMaterials(); iMat++)
{
MeshMIDs.Add(Mesh3P->CreateAndSetMaterialInstanceDynamic(iMat));
}
Now we need to create our actual functions that we can call, to make changes to the MID, this can just be put at the bottom of all of the existing code.
// Material dynamic effects
void AShooterWeapon::UpdateWeaponMaterialEffects(float NewParam)
{
if (UseDynamicMatEffects)
{
for (int32 i = 0; i < MeshMIDs.Num(); ++i)
{
float MaterialParam = NewParam;
MeshMIDs*->SetScalarParameterValue(TEXT("EmissiveBrightness"), MaterialParam);
}
if (UseReplicatedDynamicMatEffects)
{
if (Role < ROLE_Authority)
{
ServerUpdateWeaponMaterialEffects(NewParam);
}
}
}
}
// Replication of Material dynamic effects
void AShooterWeapon::ServerUpdateWeaponMaterialEffects_Implementation(float NewParam)
{
UpdateWeaponMaterialEffects(NewParam);
}
// Replication validate of Material dynamic effects
bool AShooterWeapon::ServerUpdateWeaponMaterialEffects_Validate(float NewParam)
{
return true;
}
FINALLY, we call the effect to be applied, when the weapon is equiped. And when the ammo is used.
in:
void AShooterWeapon::OnEquip()
under:
if (MyPawn && MyPawn->IsLocallyControlled())
{
if (UseRemainingAmmoMatEffect)
{
UpdateWeaponMaterialEffects(CurrentAmmo);
}
}
now, when ammo is used we want to adjust the brightness of the emissive.
at the end of the following section:
void AShooterWeapon::UseAmmo()
put this:
// Material emissive based on ammo
if (UseRemainingAmmoMatEffect)
{
if (MyPawn && MyPawn->IsLocallyControlled())
{
UpdateWeaponMaterialEffects(CurrentAmmo);
}
}
And that is it! Now when ammo is consumed, the value of our “EmissiveBrightness” scalar will decrease, and turn the lights off, so to speak, when we run out of ammo.
Perhaps more tutorials to come
Have fun and take care!
-Gozu