0

I have a very strange issue where class B and C both inherits from class A.

Basically, class A handles life points and damage taking when B handles enemy and C handles destroyable objects.

I have my player that uses a Raycast to check if it hit one of these B or C classes by checking if GetComponent<A>() does return null or not. Then, it can use the A class to apply damage.

It works well, until class B (the enemy) throws an attack. Then GetComponent<A>() starts returning null.

My script is pretty messy and complex so I wanted to know if it doesn't come from the GetComponent<A>(). I mean, doesn't C# has polymorphism?


Added Code

So here's the method TakeDamage() in my main class (class A):

public void TakeDamage(float dmg, RaycastHit hit)
{
    Hit(hit);
    currentHp -= dmg;
    if (currentHp <= 0)
    {
        currentHp = 0;
        Die();
    }
}

Here's the attack mechanism of my Enemy class (class B):

void Update()
{
    attackCounter -= Time.deltaTime;

    if ((Vector3.Distance(player.transform.position, transform.position) <= detectionDiam) && (isAlive == true))
    {
        _navAgent.SetDestination(player.transform.position);
        _anim.SetFloat("speed", 1f);

        if (Vector3.Distance(player.transform.position, transform.position) <= attackDiam && attackCounter <= 0)
        {
            audiosrc.PlayOneShot(attackSound);
            _anim.SetTrigger("attack");
            attackCounter = attackDelay;
            Invoke("attackRoutine",attackDelay);
        }
    }
    else
    {
        _anim.SetFloat("speed", 0);
    }
}

private void attackRoutine()
{
    if (Vector3.Distance(player.transform.position, transform.position) <= attackDiam && alive==true)
    {
        Player pl = player.GetComponent<Player>();
        pl.TakeDamage(damagePerHit);
    }
}

Here's the script attached to the weapon that tries to get access to the parent method:

void Fire()
{
    if(_actualBulletCount > 0 && _shotCounter < 0 && !isRunning && !isReloading)
    {
        flash.Play();
        _audioSource.Play();
        _anim.SetTrigger("fire");
        _actualBulletCount--;
        _shotCounter = _delayBetweenTwoShots;

        RaycastHit hit;
        Debug.DrawRay(_bulletSpawn.position, _bulletSpawn.TransformDirection(Vector3.forward) * 50f, Color.yellow);
        if (Physics.Raycast(_bulletSpawn.position, _bulletSpawn.TransformDirection(Vector3.forward), out hit, Mathf.Infinity))
        {
            Debug.Log("Did Hit");
            HandleHit(hit);
        }
    }
    printUI();
}

void HandleHit(RaycastHit hit)
{
    Debug.Log(hit.transform.GetComponent<HittableEntity>());
    hit.transform.GetComponent<HittableEntity>().TakeDamage(_damagePerHit,hit);
}
  • C# has polymorphism – canton7 Feb 21 '19 at 11:32
  • I know. That was rethorical – Philémon Roubaud Feb 21 '19 at 11:33
  • That was the only actual question I could find in your post. The rest was just abstractly describing some code you haven't posted. If the only bit with a question mark was rhetorical, I'm afraid I don't think there's anything anyone can actually answer. – canton7 Feb 21 '19 at 11:35
  • Sorry about that. I'm asking if using GetComponent< A >() is the good way to do what i want – Philémon Roubaud Feb 21 '19 at 11:37
  • What happens in the inspector with the object you are trying to get the componenent of? Does the component still exist? Also, can you please give some code as others have suggested. There is no reason why a component will start returning null for no reason, so you must have done something but we can't see because you have nothing to show. – Vitulus Feb 21 '19 at 11:58
  • Well... Nothing visible from the inspector... – Philémon Roubaud Feb 21 '19 at 12:08
  • I would like to see some code to see what you've attempted so far. Please see [this help section for creating a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) – Eliasar Feb 21 '19 at 14:36
  • What do you mean by nothing visible from the inspector? Does the component you are trying to get exist or not? And when does it disappear? – Vitulus Feb 22 '19 at 07:18
  • I mean that nothing changes when the ennemy switches from "A accessible" to "A not accessible" – Philémon Roubaud Feb 22 '19 at 09:31
  • Actually the component that i'm trying to access is the same that manages movement and attack of the ennemy, and it still can move and attack after becomming "invincible" – Philémon Roubaud Feb 22 '19 at 09:36
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Eliasar Feb 22 '19 at 15:37

2 Answers2

2

C# inheritance does not constitute a Unity Component. If you want to access your inherited class, you will need to have the overridden method to be virtual.

C# Polymorphism

public class A
{
    public virtual int TakeDamage(int damageTaken) { ... }
}

public class B : A
{
    public override int TakeDamage(int damageTaken)
    {
        // Non-base stuff

        // Base stuff
        base(damageTaken);
    }
}

Unity Component

If you would rather use Unity's built-in Component system, see the following.

Given: there are multiple scripts on a single, same GameObject

public class A
{
    public int TakeDamage(int damageTaken) { ... }
}

public class B
{
    public int AnotherMethod(int damage)
    {
        gameObject.GetComponent<A>().TakeDamage(damage);
    }
}
Eliasar
  • 1,023
  • 1
  • 8
  • 18
  • Well i'm currently using the second method, wich works well until the enemy attacks me. I'm posting some code – Philémon Roubaud Feb 21 '19 at 16:50
  • You should be using the `Component` system, as it's a strength of the system instead of having to shoe horn your code into inheritance. – Eliasar Feb 21 '19 at 16:51
0

I'm just thinking why you need to call A to execute the TakeDamage method, you can call B or C and call the TakeDamage method because it is inherited by B and C.

hit.transform.GetComponent<B>().TakeDamage(_damagePerHit, hit);
  • Yeah but as you can see in my HandleHit, it has to work with B or C, that's why i need to cast the hit as A. I might even create other classes D, E inheriting from a as well... – Philémon Roubaud Feb 21 '19 at 18:06
  • as someone already answered before, you can just use polymorphism in this situation. It's easier to do than choose every single object to instantiate a component on it. – Rafael Ocariz May 08 '19 at 13:34