- Home /
Function doesn't always work during collision
Hello,
this is my code on a prefab that is being instantiated during an attack
[SerializeField] private float damageToGive;
public GameObject Player;
private void Update()
{
damageToGive = Player.GetComponent<PlayerDamageManager>().playerDamage;
}
private void OnTriggerEnter2D(Collider2D other){
if(other.gameObject.tag == "Enemy")
{
other.gameObject.GetComponent<EnemyHealthManager>().HurtEnemy(damageToGive);
Debug.Log("It collides");
}
}
And this is the health manager script on the enemy
public float enemyCurrentHealth;
public float enemyMaxHealth;
//Functions
public void HurtEnemy(float damageToGive){
enemyCurrentHealth -= damageToGive;
Debug.Log("Damage Done");
}
private void LateUpdate()
{
if(enemyCurrentHealth == 0f){
Destroy(gameObject);
}
}
Debug.Log shows me that each collision is registered and HurtEnemy function is ran on each collision but it doesn't always subtract health and I can't understand why. :/ Any help on the subject would be appreciated.
Answer by rhapen · Dec 15, 2020 at 11:08 PM
it look alright except one thing you really should not do this in the update
private void Update()
{
damageToGive = Player.GetComponent<PlayerDamageManager>().playerDamage;
}
put it in the Start or Awake
It might ,it might not be cause. collision is happening in physics fixedupdate so it is out of sync with update. plus getting component in every update is of course very expensive.
I've tried changing it to Start() and Awake instead of Update. Weirdly enough it didn't work at first but reloading Unity made it work like intended.
Thank you so much! It means a lot to get help like that as a hobby weekend developer for fun. :)
Answer by tategarringer · Dec 15, 2020 at 11:30 PM
I imagine you've stumbled upon Unity's Order of Execution for Event Functions! Your problem likely lies right here:
As you can see, OnTrigger
events are called well before Update
, so if you're making contact as soon as the object is instantiated you'll be calling your OnTrigger
event before you've had a chance to define a value for damageToGive
. I would recommend moving that line to a Start
function or making it into a property instead!
public GameObject Player;
[SerializeField] private float damageToGive;
private float damageToGiveProperty { get { return Player.GetComponent<PlayerDamageManager>().playerDamage; } }
//You can do it this way
private void Start()
{
damageToGive = Player.GetComponent<PlayerDamageManager>().playerDamage;
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Enemy")
{
other.gameObject.GetComponent<EnemyHealthManager>().HurtEnemy(damageToGive);
//OR this way with a property
other.gameObject.GetComponent<EnemyHealthManager>().HurtEnemy(damageToGiveProperty);
Debug.Log("It collides");
}
}
Thank you! This explains my problem so well. Big thank you, I've wasted at least 3h tinkering before asking.
Your answer
