Damage text on hit - Best practice ?

Hi there, my approach is something like below, it is quite performant.

  1. NS: Have a Niagara System that spawns a mesh (quad) with dynamic material instance and variables exposed. I spawn for up to 3 digits spawn single particle, however it can be per digit particle too. All digits together easier to control and nicer effects in terms of physics, drags, size changes etc.

  2. Metarial : Build your material, something that is light weight. There is a node ready for converting numbers, however if you want a custom one for artistic and other reason, you better create your node or function. You can have a simple 0-9 flip book and select frame at index and assemble your digits or you can seperate images if you wish. I am using a sprite sheet classic with UV drags.

  3. OnDamage receive, after whatever the steps you have in your systems when true damage calculated we pass that digit to a function. That spawns the niagara and gives variables. At this stage it is better to keep niagara and material instance active per user/actor, so we can just spawn the particle and reset system instead of killing, that would be much more nicer for limited hardware. For these I generally use an encapsulated actor component UDamageFeedbackComponent that does many things, flash enemy outline, set an icon overhead for status also a CombatTextFlow (damage etc that we are talking)

For materials masked domain think can be a better mobile fit. Since we use a single quad you don’t have to worry about polycount. Unlit shaders are fine for material and niagara. I didn’t test these on mobile but should be fine.

If you want to avoid Niagara, you can simply go oldschool, put a quad on top of your characters, animate the material with direction + fade and you will even have more optimised system. It really depends on the end results desired with in the current sandbox of constraints.

void UMGDamageFeedbackComponent::ReplayFloatingText(UNiagaraComponent* NiagaraComp, float DamageAmount, const FVector& ImpactLocation)
{
	if (!IsValid(NiagaraComp))
	{
		return;
	}

	// I use a location and this one checks material and sets then activate.
	// However it wont look very nice if there is dps more than the length of niagara
	// You can spawn or pool couple of systems and re use them.
	FVector SpawnLoc = ImpactLocation;
	SpawnLoc.Z += 50.f;
	NiagaraComp->SetWorldLocation(SpawnLoc);

	NiagaraComp->SetVariableFloat(DamageVariableName, DamageAmount);

	if (FloatingTextMaterial)
	{
		if (!IsValid(CachedFloatingTextMID))
		{
			CachedFloatingTextMID = UMaterialInstanceDynamic::Create(FloatingTextMaterial, this);
		}

		if (CachedFloatingTextMID)
		{
			NiagaraComp->SetVariableMaterial(FName("Material Interface"), CachedFloatingTextMID);
			CachedFloatingTextMID->SetScalarParameterValue(DamageVariableName, DamageAmount);
		}
	}

	NiagaraComp->DeactivateImmediate();
	NiagaraComp->Activate(true);
}

Material Function to convert 3 digit numbers into sprite sheet digits

Material used in floating text for niagara, I also fixed zero digits selected as prefix now it works nice.

Niagara

Untested in mobile