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();
Answer by andrew-lukasik · Sep 29, 2020 at 07:23 PM
[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();
Would you like to want know MORE?
Hi, @andrew-lukasik (Andrzej right?:) I haven't noticed that you already replied. Thank you!
In the meantime, I figured out that I need to use the components and $$anonymous$$aterialProperty attribute instead of trying to use $$anonymous$$aterialPropertyBlock. 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 'myEntity$$anonymous$$anager'.AddComponentData(...). Not always 'brute force' mode as I did, trying to learn how things working and achieve goals is the best ;)
I will try your proposal on how to fill the value, thanks for your reply one more time!
[GenerateAuthoringComponent]
[$$anonymous$$aterialProperty("_Fill", $$anonymous$$aterialPropertyFormat.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 = Entity$$anonymous$$anager.GetComponentData<Parent>(e);
var hp = Entity$$anonymous$$anager.GetComponentData<Health>(parent.Value);
healthBarFill.Value = hp.value;
}).WithoutBurst().Run();
}
Your answer
Follow this Question
Related Questions
Composite Pattern in Pure ECS,Composite Pattern in Unity ECS 0 Answers
Simple ECS/DOTS collision system not working 1 Answer
DOTS / ECS: Burst error BC1022: Accessing a managed array is not supported 0 Answers
ECS World Space Canvas Children Not Displaying 0 Answers
How to Destroy a PhysicsJoint Object in new Unity.Physics? 0 Answers