Search Unity

Bug Projectile should damage force field before enemy

Discussion in 'Scripting' started by stefaxel, Dec 8, 2022.

  1. stefaxel

    stefaxel

    Joined:
    Oct 8, 2021
    Posts:
    47
    I have got an enemy with a force field as a child object, the force field is active when the enemy stops to get a new patrol point and when the player is in range of the enemy. The enemy should only take damage once the force field has been completely damaged. Instead the enemy is taking damage even with the force field being active. Is this because the parent tag takes priority over the child tag, or are there other issues with the scripts?

    This is my script for the bullet:
    Code (CSharp):
    1. public class StandardBullet : MonoBehaviour
    2. {
    3.     [Header("Bullet Settings")]
    4.     [SerializeField] protected float bulletSpeed;
    5.     [SerializeField] protected int bulletDamage;
    6.     [SerializeField] protected int bulletForceFieldDamage;
    7.     ForceFieldEnemy forceFieldEnemy;
    8.     [SerializeField] GameObject enemy;
    9.  
    10.     [HideInInspector]
    11.     public Vector3 hitPoint;
    12.  
    13.     // Start is called before the first frame update
    14.     virtual protected void Start()
    15.     {
    16.         this.GetComponent<Rigidbody>().AddForce((hitPoint - this.transform.position).normalized * bulletSpeed * Time.deltaTime);
    17.         forceFieldEnemy = enemy.GetComponent<ForceFieldEnemy>();
    18.     }
    19.     virtual protected void OnCollisionEnter(Collision collision)
    20.     {
    21.         if (collision.gameObject.tag == "Force Field" && forceFieldEnemy.isFfActive)
    22.         {
    23.             collision.gameObject.GetComponent<ForceField>().DamageForceField(bulletForceFieldDamage);
    24.             Debug.Log("Force Field is taking damage: " + bulletForceFieldDamage);
    25.             Destroy(this.gameObject);
    26.         }
    27.         if (collision.gameObject.tag == "Enemy" && !forceFieldEnemy.isFfActive)
    28.         {
    29.             collision.gameObject.GetComponent<EnemyHealth>().TakeDamage(bulletDamage);
    30.             Debug.Log("Enemy is taking damage: " + bulletDamage);
    31.             Destroy(this.gameObject);
    32.         }
    33.         Destroy(this.gameObject);
    34.     }
    35. }
    The script for the enemy:
    Code (CSharp):
    1. public class ForceFieldEnemy : Enemy
    2. {
    3.     [Header("Enemy Force Field")]
    4.     [SerializeField] protected GameObject forceField;
    5.     [SerializeField] protected ForceField enemyFF;
    6.  
    7.     [HideInInspector]
    8.     public bool isFfActive;
    9.  
    10.     protected override void AIChecks()
    11.     {
    12.         playerInSight = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
    13.         attackPlayer = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
    14.  
    15.         if (!playerInSight && !attackPlayer)
    16.         {
    17.             Patrolling();
    18.         }
    19.  
    20.         if (playerInSight && !attackPlayer)
    21.         {
    22.             if(enemyFF.forceFieldActive == true)
    23.             {
    24.                 isFfActive = true;
    25.                 forceField.SetActive(true);
    26.             }
    27.             if(enemyFF.forceFieldActive == false)
    28.             {
    29.                 isFfActive = false;
    30.                 forceField.SetActive(false);
    31.             }
    32.             ChasePlayer();
    33.         }
    34.  
    35.         if (playerInSight && attackPlayer)
    36.         {
    37.             if (enemyFF.forceFieldActive == true)
    38.             {
    39.                 isFfActive = true;
    40.                 forceField.SetActive(true);
    41.             }
    42.             if (enemyFF.forceFieldActive == false)
    43.             {
    44.                 isFfActive = false;
    45.                 forceField.SetActive(false);
    46.             }
    47.             AttackPlayer();
    48.         }
    49.  
    50.     }
    51. }
     
  2. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    as long as forceFieldEnemy.isFfActive is actually active you should have nothing to worry about.

    what about this tag request collision.gameObject.tag == "Force Field"; Does it? I don't see the part where you register the tag change
     
  3. stefaxel

    stefaxel

    Joined:
    Oct 8, 2021
    Posts:
    47
    I need to change the tag at runtime on the enemy script, and then change it again once the force field is completely damaged then?
     
  4. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Yeah that’s how you’ve written it. So you are only deducting from force field if the collisions objects tag says that it’s a force field according to the code above


    It’s not technically a bug either ^^
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    In OnCollisionEnter you should debug both the tag and the value of isFfActive to see what it is spitting out.

    However, my question is... in start, you are grabbing the ForceFieldEnemy component from an enemy reference. However, I see you are destroying your bullets, which means you are likely instantiating those bullets somewhere. So my next question is... what is the value of enemy?

    Is the enemy your bullets are hitting actually the same enemy whose ForceFieldEnemy script you have grabbed?

    Instead, you should probably have your OnCollisionEnter grab the ForceFieldEnemy component from the target it hits, check if it's null and handle it there. Unless you set it up where you only have one enemy and your bullets enemy variable targets that enemy, then I think your issue is a mismatch.
     
  6. stefaxel

    stefaxel

    Joined:
    Oct 8, 2021
    Posts:
    47
    The bullets are being instantiated in the player script. I have a regular enemy type which dosen't have a force field, but has got the tag Enemy. The bullet can still damage a regular enemy as I have now removed isFfActive, and I don't actually need it. I was overcomplicating that part.

    This is what I have now for the bullet:
    Code (CSharp):
    1. public class StandardBullet : MonoBehaviour
    2. {
    3.     [Header("Bullet Settings")]
    4.     [SerializeField] protected float bulletSpeed;
    5.     [SerializeField] protected int bulletDamage;
    6.     [SerializeField] protected int bulletForceFieldDamage;
    7.     [HideInInspector]
    8.     public Vector3 hitPoint;
    9.  
    10.     // Start is called before the first frame update
    11.     virtual protected void Start()
    12.     {
    13.         this.GetComponent<Rigidbody>().AddForce((hitPoint - this.transform.position).normalized * bulletSpeed * Time.deltaTime);
    14.     }
    15.  
    16.  
    17.     virtual protected void OnCollisionEnter(Collision collision)
    18.     {
    19.         if (collision.gameObject.tag == "Force Field")
    20.         {
    21.             collision.gameObject.GetComponent<ForceField>().DamageForceField(bulletForceFieldDamage);
    22.             Debug.Log("Force Field is taking damage: " + bulletForceFieldDamage);
    23.             Destroy(this.gameObject);
    24.         }
    25.         if (collision.gameObject.tag == "Enemy")
    26.         {
    27.             collision.gameObject.GetComponent<EnemyHealth>().TakeDamage(bulletDamage);
    28.             Debug.Log("Enemy is taking damage: " + bulletDamage);
    29.             Destroy(this.gameObject);
    30.  
    31.         }
    32.         Destroy(this.gameObject);
    33.     }
    34. }
    And this is what I'm doing with the enemy that can use a force field:
    Code (CSharp):
    1. public class ForceFieldEnemy : Enemy
    2. {
    3.     [Header("Enemy Force Field")]
    4.     [SerializeField] protected GameObject forceField;
    5.     [SerializeField] protected ForceField forceFieldEnemy;
    6.  
    7.     protected override void Awake()
    8.     {
    9.         base.Awake();
    10.     }
    11.     // Update is called once per frame
    12.     void Update()
    13.     {
    14.         AIChecks();
    15.     }
    16.  
    17.     protected override void AIChecks()
    18.     {
    19.         playerInSight = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
    20.         attackPlayer = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
    21.  
    22.         if (!playerInSight && !attackPlayer)
    23.         {
    24.             Patrolling();
    25.         }
    26.  
    27.         if (playerInSight && !attackPlayer)
    28.         {
    29.             if(forceFieldEnemy.forceFieldActive == true)
    30.             {
    31.                 gameObject.tag = "Force Field";
    32.                 forceField.SetActive(true);
    33.             }
    34.             if(forceFieldEnemy.forceFieldActive == false)
    35.             {
    36.                 gameObject.tag = "Enemy";
    37.                 forceField.SetActive(false);
    38.             }
    39.             ChasePlayer();
    40.         }
    41.  
    42.         if (playerInSight && attackPlayer)
    43.         {
    44.             if (forceFieldEnemy.forceFieldActive == true)
    45.             {
    46.                 gameObject.tag = "Force Field";
    47.                 forceField.SetActive(true);
    48.             }
    49.             if (forceFieldEnemy.forceFieldActive == false)
    50.             {
    51.                 gameObject.tag = "Enemy";
    52.                 forceField.SetActive(false);
    53.             }
    54.             AttackPlayer();
    55.         }
    56.     }
    57. }
    So I can now shoot both enemy types, however a Null Reference Exception sometimes happens when the bullet hits the force field. It gives Object reference not set to an instance of an object, but this dosen't happen everytime. I have a rigidbody with interpolate set to interpolate and collision detection to continuous on the force field object.

    The force field script is similar to the health script, with the only difference being the force field is not being destoryed once the power is 0