Home > database >  why does interface return null instead of true/false
why does interface return null instead of true/false

Time:09-05

i have been searching for an answer on the internet for a while and cant really find a good explanation so sorry if this is a repeat question. i dont exactly understand how interfaces work. i am trying to use an interface to return a true bool condition. any help would be appreciated. thanks in advance. here is what i think is all relevant code:


 using System.Collections.Generic;
 using UnityEngine;
 
 public interface IDamageable
 {
     BaseStats Stats { get; }
     List<GameObject> HitTargets { get; }
     GameObject Target { get; set; }
 
     void TakeDamage(float amount);
     
 } 
 
 using UnityEngine;
 using UnityEngine.UI;
 
 [System.Serializable]
 public class BaseStats
 {
 [SerializeField]
     private SphereCollider detectionObject;
 [SerializeField]
 private GameConstants.OBJECT_TYPE objectType;
 [SerializeField]
 private GameConstants.OBJECT_ATTACKABLE objectAttackable;

 public GameConstants.OBJECT_ATTACKABLE ObjectAttackable
 {
     get { return objectAttackable; }
 }
 public GameConstants.OBJECT_TYPE ObjectType
 {
     get { return objectType; }
 }
 public SphereCollider DetectionObject
 {
     get { return detectionObject; }
 }
}

using UnityEngine;

public static class GameConstants
{
public enum OBJECT_TYPE
 {
     GROUND,
     FLYING
 }
 
 public enum OBJECT_ATTACKABLE
 {
     GROUND,
     FLYING,
     BOTH
 }

 public enum UNIT_RANGE
 {
     MELEE,
     RANGE
 }
}

using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;

public class Units : MonoBehaviour, IDamageable, IPunObservable
{
[SerializeField]
 private BaseStats stats;
 
 [SerializeField]
 private List<GameObject> hitTargets;

 public List<GameObject> HitTargets
 {
     get { return hitTargets; }
 }
 public BaseStats Stats
 {
     get { return stats; }
 }
public void OnTriggerEnter(Collider other)
 {
     if(!other.transform.CompareTag(gameObject.tag))
     {
         Component damageable = other.transform.gameObject.GetComponent(typeof(IDamageable));
         if(damageable)
         {
             if(!hitTargets.Contains(damageable.gameObject))
             {
                 hitTargets.Add(damageable.gameObject);

             }
         }
     }
 }
}

damageable is returning a null condition. i know this through debugging. i have all objects set to "ground" type and attackable in the inspector. am i not using the interface correctly? am i not assigning something? i thought as long as the interface was inherited it would work. thanks.

CodePudding user response:

You are using interfaces correctly. It seems like the GameObject with the trigger Collider just doesn't have any components that implement IDamageable (such as Units) attached to it.

You can add this logging to the beginning of your OnTriggerEnter event function and check that the other object is the one you are assuming it to be, and that it has the components that you are assuming it to have. You can pause the game and click on the message in the Console to highlight the other object in the Hierarchy.

void OnTriggerEnter(Collider other)
{
    Debug.Log(other.name   " contains components: "   string.Join(", ", other.GetComponents<Component>().Select(c => c.GetType().Name).ToArray()), other);

CodePudding user response:

Let me know if my understanding is wrong but from what I see-

  1. You have an interface "IDamageable" which determines if an object can be damaged or not
  2. In Class UNITS, you have inherited "IDamageable" interface
  3. In UNITS, after collision, you're trying to see if the object that you collided with has "IDamageable" interface or not.

Component damageable would return NULL for the following reasons -

  1. Assigned to WRONG object. "IDamageable" should be assigned to objects which are colliding with "UNITS" class. So if I have a gun/sword, "IDamageable" script should be attached to things which gun/sword can damage and not on the sword itself.
  2. Check if collisions are working properly.
  3. Check if Rigidbodies are attached to objects
  4. Check "isTrigger", if enabled or disabled, Rigidbodies needs to be modified accordingly.

Now for some extra information - INTERFACE! They are generic classes with only declarations and no implementations.

Suppose you have to design a shop system where you need to sell cars. There are 1000 different types of companies.

Basic (not recommended) method -

Class Toyota 
{
    string name;
    int price;
}
Class Volvo
{
    string name;
    int price;
}
Class Maruti
{
    string name;
    int price;
}

Here, you are defying the basic programming rule- DO NOT REPEAT YOURSELF (DRY principle)

Now, same code implemented with INFERFACE -

Interface CarProperties
{
    string name;
    int price;
}
Class Toyota : CarProperties
{}
Class Volvo : CarProperties
{}
Class Maruti : CarProperties
{}

Now for both the code types, all I need to do is Toyota.VariableName.name to access the STRING NAME variable. Since every car, no matter the company, make year, etc SOME VARIABLES WOULD EXIST AS GENERIC.

These generic variables & functions can be stored as an extra INTERFACE class and inherited to all the rest of the classes.

  • Related