Changing Material Shader Value in Run time.

Hello All,

Here is the enemy health script. When Enemy health gets zero, I want to change some values in material shader. So I changed the material shader value. The current enemy whose health is zero, script changes the value of material shader. But there is a problem, another enemy whose health is 100 also sharing the same material and their material value also gets changed which should changed when enemy health become zero. So, what should I do? And after facing this problem I came to know that if we change the value of material shader in run time, its never gets back to its default value. And its beyond my level.:frowning:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;


public class EnemyHealth : Enemy, Idamageble
{
    //public new Animator anim;
    // public Rigidbody enemyRigidBody;
    public BoxCollider boxCollider;
    public SphereCollider sphereCollider;
    public NavMeshAgent navMeshAgent;
    public GameObject money;
    public Image healthBar;
    private float startHealth;
    AudioSource enemyAudio;
    public GameObject enemyShadow;
    public Gun_Controller mainGunScript;

    public Canvas healthBarObject;
    public GameObject deathexplosion;
   
    public  Material  DisolveMaterial;
  
    float disolvevalue = 0.1f; // controlling disolve shader value
    float DisolveSpeed = 0.3f; // refrence to disolve shader value speed
   
    void Awake()
    {
       // Renderer rend = GetComponent<Renderer>();
        enemyAudio = GetComponent<AudioSource>();
        // enemyShadow = GetComponentInChildren<GameObject>(); // enemy shadow
        healthBarObject = GetComponentInChildren<Canvas>();
        // = GetComponent<Renderer>().material;
       
     //DisolveMaterial =   GetComponentInChildren<Material>();
         DisolveMaterial.SetFloat("_DissolveAmount", 0);
    }

    private void Update()
    {
        disolveMethod();

    }



    public float Health { get; set; }

    public override void Init()
    {
        base.Init();
        startHealth = base.health; // transfer Enemy class health value to startHealth
        Health = startHealth;

    }


    public void ActivateRugdoll()
    {
        anim.enabled = false;
    }

    public void TakeDamage(float amount)
    {
        if (Health <= 0)
        {
            // StartCoroutine(giveVAlue()); 
            //  disolveValueLoop();
           // enemyMOV.NavMeshDisable();
            return;

        }
        else if (Health >= 0)
        {
            Health -= amount;

            StartCoroutine(EnableDisableHealthBar());
            enemyAudio.Play();
            Debug.Log("you can play animation of hit");
            healthBar.fillAmount = Health / startHealth;

            StartCoroutine(Screaming());
            if (Health <= 0f)
            {
                enemyMOV.NavMeshDisable();
                Debug.Log(name + " Enemy DEAD");
                navMeshAgent.speed = 0f;

                DestroyEnemyShadow();

                ActivateRugdoll();

                //DisolveMaterial.SetFloat("_DissolveAmount", disolvevalue + addValue );
                //StartCoroutine(giveVAlue()); // phele couroutine chailge
                disolveMethod();
                Destroy();
            }
            if (Health <= 50f)
            {
                StartCoroutine(mainGunScript.AfterShootImage()); //  CRITICAL IMAGE ANIMATION

            }

        }


    }

    private IEnumerator Screaming()
    {
        anim.SetBool("Scream", true);
        enemyMOV.NavMeshDisable();
        // Wait for 1 second
        yield return new WaitForSeconds(0.5f);
        anim.SetBool("Scream", false);
        enemyMOV.NavMeshEnable();
    }
    void disableAllCollider()
    {
        boxCollider.enabled = false;
        sphereCollider.enabled = false;

    }
    void Destroy()
    {
        Destroy(this.gameObject,2.5f);
        Instantiate(money, transform.position, Quaternion.identity);
      
    }
    void DestroyEnemyShadow()
    {
        Destroy(enemyShadow);
    }
    // enable or disable health bar what shoot start or in technical when health decrease
    IEnumerator EnableDisableHealthBar() 
    {
        healthBarObject.enabled = true;
        yield return new WaitForSeconds(0.4f);
        healthBarObject.enabled = false;

    }
    private void disolveMethod() // this method is create to make changes of value over time in dissolve shader , 
    {

        if (Health <= 0)
        {
         
           
          DisolveMaterial.SetFloat("_DissolveAmount", disolvevalue += Time.deltaTime * DisolveSpeed);
        }
    }
}

Copy the material for each enemy (which will work but result in additional draw calls) or better still, use a MaterialPropertyBlock.

See here:
https://thomasmountainborn.com/2016/05/25/materialpropertyblocks/

1 Like

Thanks for the reply.:slight_smile: But I am preparing code for mobile platform so extra drawcall will definitely the problem. And I’m still learning so the method you have suggested, I’m unable to use that in my script. Can you edit my script for me?
Somewhere I have read in these kind of situations where multiple mashes share one material, people use some kind of material batch in run time. But I have no idea about that. That’s why I’m asking. :frowning:

Take a look on both links that grizzly posted, they are the solution for your situation.

oky ! yes its working thanks for the reply :slight_smile:

Hail " Grizzly" ! Hail " Grizzly" ! Hail " Grizzly" !

its working ! thank you for your valuable time it great now it works separately , i can’t believe it its working :smile::smile::):):smile:

2 Likes