Search Unity

Problem using interface

Discussion in 'Scripting' started by Macioteros, May 6, 2020.

  1. Macioteros

    Macioteros

    Joined:
    Jan 6, 2020
    Posts:
    5
    Tried searching for something related but just found answers of 2-7 years ago about this saying to not use interfaces but then I discovered that they implemented the support for interface in Unity 5 , but when I tried following the tutorial from Code Monkey about interface and use it on my game it still can't find the IDamageable when I use
    GetComponent<IDamageable>()
    , currently I'm using Unity 2019.3.3f1.

    About the support:
    https://unity3d.com/fr/unity/whats-new/unity-5.0
    found this from here:
    https://stackoverflow.com/questions/52459094/unity-using-components-as-interface)

    Code (CSharp):
    1. public interface IDamageable
    2. {  
    3.     void ReceiveDamage(float damageValue, StatsManager.DamageType damageType);
    4. }
    Code (CSharp):
    1.  private void OnTriggerEnter(Collider other)
    2.     {      
    3.         if (other.GetComponent<StatsManager>())
    4.         {
    5.          
    6.             IDamageable damageable = other.gameObject.GetComponent<IDamageable>();
    7.             // Tried using:  other.GetComponent<IDamageable>();
    8.             // Tried using directly here: damageable.ReceiveDamage(parameters);
    9.  
    10.             damageManager.DamageTarget(
    11.                 damageable,
    12.                 statTarget.CalculateDamageDeal(),
    13.                 statTarget.currentDamageType);
    14.         }
    15.     }
    This code below is being used in another script called DamageManager

    Code (CSharp):
    1. public void DamageTarget(IDamageable target, float damageValue,StatsManager.DamageType damageType)
    2.     {
    3.        
    4.         if (target != null)
    5.         {
    6.             target.ReceiveDamage(damageValue, damageType);
    7.         }
    8.         else
    9.         {
    10.             Debug.Log("IS NULL");
    11.         }
    12.     }
    And this is the error that appears if I remove the IF statement from above:


    NullReferenceException: Object reference not set to an instance of an object
    DamageManager.DamageTarget (IDamageable target, System.Single damageValue, StatsManager+DamageType damageType) (at Assets/_Scripts/System/Characters/DamageManager.cs:42)
    DoDamage.OnTriggerEnter (UnityEngine.Collider other) (at Assets/_Scripts/System/Characters/DoDamage.cs:27)


    I Can't find the solution for this problem why is this happening? Can this be related to the parameters I had put in the interface?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    This absolutely works for sure. You didn't post the code for the class declaration header for the MonoBehavior that implements this interface. Are you sure that you put that MonoBehavior on the GameObject where you're doing the
    GetComponent<IDamageable>()
    ?
     
  3. Macioteros

    Macioteros

    Joined:
    Jan 6, 2020
    Posts:
    5
    Sorry for my lack of knowledge by 'class declaration header' do you mean this:

    public class PlayerStats : MonoBehaviour, IDamageable


    if so here's the other code:

    Code (CSharp):
    1.  
    2. public class PlayerStats : MonoBehaviour, IDamageable
    3. {
    4.   public void ReceiveDamage(float damageValue, StatsManager.DamageType damageType)
    5.     {
    6.         float defType = 0;
    7.         float finalDamage = 0;
    8.  
    9.         if (damageType == StatsManager.DamageType.physical)
    10.         {
    11.             defType = physicalDef;
    12.         }
    13.         else
    14.         {
    15.             defType = magicalDef;
    16.         }
    17.         finalDamage = damageValue - defType;
    18.         if (finalDamage < 0)
    19.         {
    20.             finalDamage *= -1;
    21.         }
    22.         currentHP -= finalDamage;
    23.     }
    24. }
    I'm using this same code on the Enemy script and confirmed that the script PlayerStats are inside the GameObject

    for some reason the image is not showing I will try to post a link below:
    https://imgur.com/a/ALQE1BJ
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    In your middle code blurb in the first post, I see you getting a StatsManager object off the same place (
    other
    ) where you're getting the IDamageable object. Is that correct? A manager implies one thing shared across the game, whereas an IDamageable implies an actor.

    Are you sure you don't mean to just do a GetComponent right there on yourself, you being the one that stepped into the trigger and received this OnTrigger call??
     
  5. Macioteros

    Macioteros

    Joined:
    Jan 6, 2020
    Posts:
    5
    OMG can't believe it was that condition stopping everything:
    if (other.GetComponent<StatsManager>())

    Because the script StatsManager is on a child GameObject and the condition seems to can't reach or find this script, but strangely enough I verified the code inside this IF statement with the Debug.Log inside like this:
    Code (CSharp):
    1.    private void OnTriggerEnter(Collider other)
    2.     {      
    3.         if (other.GetComponent<StatsManager>())
    4.         {
    5.             IDamageable damageable = other.gameObject.GetComponent<IDamageable>();
    6.             Debug.Log(damageable);
    7.         }
    8.     }
    and the console still printed NULL showing that this condition passed and went inside the { } (forgot the name of this type of brackets) below the IF condition for some reason.

    But for now it seems that it solved a 'part' of the problem and the damage is being applied now, because testing here sometimes shows that the IDamageable function is null here:
    Code (CSharp):
    1. public void DamageTarget(IDamageable target, float damageValue,StatsManager.DamageType damageType)
    2.     {      
    3.         if (target != null)
    4.         {
    5.             target.ReceiveDamage(damageValue, damageType);
    6.         }
    7.         else
    8.         {
    9.             Debug.Log("NULL");
    10.         }
    11.     }
    Anyway thanks for the help.