When I put TakeDamage(damage) in update like this; enemiesToDamage*.GetComponent<Enemy_behaviour>().TakeDamage(damage)* I get NullReference, It works like this but then I can’t destroy enemies all the time. Any way to work this out?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttack : MonoBehaviour
{
private float timeBtwAttack;
public float startTimeBtwAttack;
public Transform attackPos;
public LayerMask whatIsEnemies;
public Animator camAnim;
public Rigidbody2D myrigidbody;
public Animator playerAnim;
public float attackRange;
public int damage;
void Update()
{
if(timeBtwAttack <= 0){
if(Input.GetKey(KeyCode.J)){
camAnim.SetTrigger("shake");
playerAnim.SetTrigger("attack");
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange,whatIsEnemies);
for(int i = 0; i < enemiesToDamage.Length; i++){
enemiesToDamage.GetComponent<Enemy_behaviour>();
}
}
timeBtwAttack=startTimeBtwAttack;
}
else{timeBtwAttack -= Time.deltaTime;}
}
public void OnCollisionEnter2D(Collision2D collision)
{
if(Input.GetKey(KeyCode.J)){
if(collision.transform.tag == "Enemy"){
collision.transform.GetComponent<Enemy\_behaviour>().TakeDamage(damage);
}
}
}
void OnDrawGizmosSelected(){
Gizmos.color = [Color.red](https://Color.red);
Gizmos.DrawWireSphere(attackPos.position,attackRange);
}
}
enemiesToDamage is the array, you wanna refer to enemiesToDamage*.*gameobject You probably also should use TryGetComponent instead of GetComponent since the gameobject may have not the Component you’re asked for.
I get this on the console Assets\PlayerAttack.cs(32,35): error CS7036: There is no argument given that corresponds to the required formal parameter ‘component’ of ‘GameObject.TryGetComponent(out T)’
Try 1st to read the documentation about TryGetComponent, instead of just post each error your compiler drops.
Documentation has an example about how it works
You get NullReference because you’re not checking the tag anymore.
// This doesn't work because you're accessing an
// array instead of the thing in the array:
//~ for(int i = 0; i < enemiesToDamage.Length; i++){
//~ enemiesToDamage.GetComponent<Enemy_behaviour>();
//~ }
// Try a foreach loop instead so you don't need to deal with the index:
foreach (var foe in enemiesToDamage)
{
if (!foe.transform.CompareTag("Enemy"))
continue;
var behaviour = foe.GetComponent<Enemy_behaviour>();
behaviour.TakeDamage();
}
You could rework your logic to use Update to determine if you want to attack and use OnCollisionEnter2D to determine whether you make contact. Something roughly like this:
public class PlayerAttack : MonoBehaviour
{
public float startTimeBtwAttack;
public float attackDuration;
public Animator camAnim;
public Animator playerAnim;
public int damage;
bool _IsAttacking = false;
float _AttackCooldownEndTime = 0;
float _AttackEndTime = float.MaxValue;
void Update()
{
if (_IsAttacking && _AttackEndTime < Time.time)
{
_IsAttacking = false;
}
if (Input.GetKey(KeyCode.J) && _AttackCooldownEndTime < Time.time)
{
_IsAttacking = true;
_AttackEndTime = Time.time + attackDuration;
_AttackCooldownEndTime = Time.time + startTimeBtwAttack;
playerAnim.SetTrigger("attack");
}
}
public void OnCollisionEnter2D(Collision2D collision)
{
if(_IsAttacking){
if(collision.transform.tag == "Enemy"){
camAnim.SetTrigger("shake");
collision.transform.GetComponent<Enemy_behaviour>().TakeDamage(damage);
}
}
}
void OnDrawGizmosSelected(){
Gizmos.color = _IsAttacking ? Color.red : Color.blue;
Gizmos.DrawWireSphere(transform.position, 1f);
}
}