How to set MaterialPropertyBlock in Entities.ForEach

Hi,
I would like to change the shader property “_Fill” but seems I need to have access to Renderer. I’m new in this, please help:)

    Entities
   .WithAll<HealthBar, Parent>()
   .ForEach((Entity e, RenderMesh renderMesh) =>
   {
       var parent = EntityManager.GetComponentData<Parent>(e);
       var hp = EntityManager.GetComponentData<Health>(parent.Value);
       var valueHP = hp.value / 100;

       //1. I would like to change shader property
       MaterialPropertyBlock mpb = new MaterialPropertyBlock();
       //Renderer renderer = new Renderer();
       //renderer.GetPropertyBlock(mpb);
       mpb.SetFloat("_Fill", valueHP);
       //renderer.SetPropertyBlock(mpb);

       //2. below setFloat works but it's on material, need to do the same on shader level
       //renderMesh.material.SetFloat("_Fill", valueHP );
   }).WithoutBurst().Run();

https://docs.unity3d.com/Packages/com.unity.entities.graphics@1.0/manual/material-overrides-code.html


[MaterialProperty( "_Fill" , MaterialPropertyFormat.Float )]
public struct FillMaterialProperty : IComponentData
{
	public float Value;
}
var healthData = GetComponentDataFromEntity<Health>();
uint systemVersion = LastSystemVersion;
Entities
	.WithName("update_fill_property_job")
	.WithAll<HealthBar>()
	.WithReadOnly( healthData )
	.ForEach( ( ref FillMaterialProperty fill , in Parent parent ) =>
	{
		if( healthData.DidChange(parent.Value,systemVersion) )
		{
		    var hp = healthData[ parent.Value ];
		    fill.Value = hp.value / 100f;
		}
	} )
	.WithBurst().ScheduleParallel();

Hi, @andrew-lukasik (Andrzej right?:slight_smile:
I haven’t noticed that you already replied. Thank you!

In the meantime, I figured out that I need to use the components and MaterialProperty attribute instead of trying to use MaterialPropertyBlock. So the same as you wrote but I couldn’t get it how I can assign my component data to entity and query it in the .ForEach without adding it explicitly to the Entity in the editor, that’s why I added [GenerateAuthoringComponent] as well. I guess I should do it in the Authoring class by ‘myEntityManager’.AddComponentData(…). Not always ‘brute force’ mode as I did, trying to learn how things working and achieve goals is the best :wink:

I will try your proposal on how to fill the value, thanks for your reply one more time!

[GenerateAuthoringComponent]
[MaterialProperty("_Fill", MaterialPropertyFormat.Float)]
public struct HealthBarFill : IComponentData
{
    public float Value;
}

public class HealthBarSystem : SystemBase
{
    protected override void OnUpdate()
    {
 Entities
            .WithAll<HealthBar, Parent>()
            .ForEach((Entity e, ref HealthBarFill healthBarFill) =>
            {
                var parent = EntityManager.GetComponentData<Parent>(e);
                var hp = EntityManager.GetComponentData<Health>(parent.Value);
                healthBarFill.Value = hp.value;

            }).WithoutBurst().Run();
}