Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How to detect if a field is null?

Discussion in 'Scripting' started by BL4CK0UT19, Mar 4, 2020.

  1. BL4CK0UT19

    BL4CK0UT19

    Joined:
    Aug 21, 2019
    Posts:
    75
    So,i have a bullet that follow target if it gets too close.

    The bullet has a very big Sphere Collider,so when the collider hits a target,it stores the target in a GameObject,and then gets the GameObject position every frame and follow him until the bullet is destroyed or until the Object is destroyed.

    It is working fine. The problem is: If i shot 4 bullets at the target,they all start following him,and the first bullet hits the target and destroys it,the other 3 bullets have nowhere to go,so they just freeze in place,and this is very ugly in the game. I need them to detect if the GameObject they stored on collision is null. So,if it is null,i can just destroy them all.

    Pretty simple if you ask me,but well,it simply does not work :).
    Here is my code:
    Code (CSharp):
    1. public class ShotFollow : MonoBehaviour
    2. {
    3.     private bool FollowTheTarget = false;
    4.  
    5.    
    6.  
    7.     private float Speed = 18f;
    8.  
    9.     private Vector3 target;
    10.  
    11.     public GameObject StoreObject;
    12.    
    13.     private float Lerp;
    14.  
    15.  
    16.  
    17.  
    18.  
    19.  
    20.     void Start()
    21.     {
    22.        
    23.     }
    24.  
    25.  
    26.     void Update()
    27.     {
    28.  
    29.         Lerp = 5f * Time.deltaTime/1.5f ;
    30.      
    31.  
    32.         transform.Translate(Vector3.forward * Time.deltaTime * Speed);
    33.        
    34.  
    35.  
    36.  
    37.         if (FollowTheTarget == true )
    38.  
    39.         {
    40.             target = StoreObject.transform.position;
    41.            
    42.             Invoke("DestroyThisObject2", 1.4f);
    43.  
    44.             Speed = 0f;
    45.  
    46.             transform.position = Vector3.Lerp(transform.position, target,Lerp) ;
    47.  
    48.   if (StoreObject.Equals(null))
    49.         {
    50.          
    51.             Destroy(gameObject);
    52.  
    53.         }
    54.  
    55.          
    56.  
    57.         }
    58.  
    59.  
    60.      
    61.  
    62.  
    63.     }
    64.  
    65.  
    66.  
    67.    
    68.  
    69.     void OnTriggerStay(Collider CollisionDetection)
    70.     {
    71.  
    72.         if (CollisionDetection.gameObject.CompareTag("Enemy"))
    73.         {
    74.  
    75.  
    76.             FollowTheTarget = true;
    77.          
    78.  
    79.  
    80.             GuardarObjeto = CollisionDetection.gameObject;
    81.  
    82.  
    83.         }
    84.     }
    85.  
    86.  
    87.     void DestroyThisObject2()
    88.     {
    89.         Destroy(this.gameObject);
    90.  
    91.  
    92.     }
    93.  
    94. }

    I made the code in another language and just translated the variable names when i pasted it here,so if it have any problems with variables names,is probably because of that,you can just ignore it.

    The part i can't make it work is this:
    (I already used StoreObject == null, and also did not work. On inspector,everything is fine. The bullet start with no object on "StoreObject'',when it collides,it stores it in the "StoreObject'',and when the object is destroyed,the bullets that were following him gets ''Missing (gameObject)" in the "StoreObject" field).
    I really have no idea of what is wrong here.

    Code (CSharp):
    1. if (StoreObject.Equals(null) )
    2.         {
    3.          
    4.             Destroy(gameObject);
    5.         }
     
  2. VSMGames

    VSMGames

    Joined:
    Jan 12, 2020
    Posts:
    47
    Have you tryed:
    Code (CSharp):
    1. if (FollowTheTarget == true && StoredObject != null)
    2. {
    3. ...
    4. }
    5. else if (FollowTheTarget == true && StoredObject == null)
    6. {
    7. Destroy(this.gameObject);
    8. }
    9.  
     
  3. BL4CK0UT19

    BL4CK0UT19

    Joined:
    Aug 21, 2019
    Posts:
    75
    Thanks for the reply!
    Gonna try it right now. I'm trying basically anything at this point.
    This code of yours goes inside the regular Update() method?
     
  4. BL4CK0UT19

    BL4CK0UT19

    Joined:
    Aug 21, 2019
    Posts:
    75
    Sadly,it did not work.
    I get the same error as always:

    "The object of type 'GameObject' has been destroyed but you're still trying to acess it.
    Your script should either check if it is null or you should not destroy the object.

    But damn,checking if it's null or not is EXACTLY what im doing,but it still does not work. I have no idea of what to do here...
     
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    What is the line which causes the error? (if you doubleclick the error message)
     
  6. Rocky_Unity

    Rocky_Unity

    Joined:
    Oct 13, 2017
    Posts:
    96
    StarManta's request will help diagnose the issue too.
    However, I'll add this.. I think your idea of an object == null is not quite correct. If an object that some other object was referenced to no longer exists , it doesn't make those references null. If you look in the inspector, I bet you'll see that public GameObject field says (missing). It sorta depends what the compiler is doing, but your bullet stores a memory address to the target (a reference/pointer).. Something else destroys the target, but some of the bullets still contain an address to that target, which has been freed in memory.
    Luckily the compiler knows to protect you in this instance (and thusly, you don't try accessing something random that was allocated in the heap), and gives you an error instead.
    I may be slightly wrong in my description of this, but the moral of the story is, the public GameObject field is not automatically set to null when the object it's referencing is destroyed.

    There are many ways to do what you want to do in this case. Here are two suggestions:
    1) Unity Events
    2) delegate event
    UnityEvents! Create a unity event that your target can invoke on destroy/death. On each of your bullets (are they prefabs?) Add an Event Listener and add the same unity event to them, which will then in turn call a function to destroy themselves.
    This will work and run great, but a more performance way would be to make a delegate, and subscribe each bullet to the delegate event that is invoked in the case that the target is destroyed. (UnityEvents are still super fast so I honestly wouldn't choose one over the other based on performance unless you were invoking thousands of UnityEvents per frame)

    The link for Unity Events is for making them via ScriptableObject (which is a whole other topic but they are a fantastic tool/thing to know for so many things and I highly recommend learning about them)
    Delegate events are a more advanced coding technique but also an incredibly powerful thing to know.
     
    BL4CK0UT19 likes this.
  7. j04milan

    j04milan

    Joined:
    Feb 6, 2019
    Posts:
    44
    give the object you are colliding with a tag then look for it by findobjectby tag if It is not such object do the thing
     
  8. BL4CK0UT19

    BL4CK0UT19

    Joined:
    Aug 21, 2019
    Posts:
    75
    H
    Hey friend,thanks for the answer
    The error i get is:

    ''MissingReferenceException:The object of type 'GameObject' has been destroyed but you are still trying to access it''.

    When i click it,it goes to this part of the code:
    (precisely,to the ''Destroy(gameObject)" line



    Code (CSharp):
    1. if (StoreObject.Equals(null))
    2.         {
    3.        
    4.             Destroy(gameObject);
    5.         }
     
  9. BL4CK0UT19

    BL4CK0UT19

    Joined:
    Aug 21, 2019
    Posts:
    75
    Thank you for your answer friend. Like i said above,the error goes in this part of the code,on the ''Destroy(gameObject)" line:

    Code (CSharp):
    1. if (StoreObject.Equals(null))
    2.         {
    3.        
    4.             Destroy(gameObject);
    5.         }
    I really don't know much about Unity Events or Delegate Events,but i will take a look at the links you sent me,thank you so much.
    You are 100% correct,when the object is destroyed,the field goes :"Missing(gameObject)".
     
  10. davidnibi

    davidnibi

    Joined:
    Dec 19, 2012
    Posts:
    424
    It's checking if storeobject is null - if it is it's destroying a GameObject - does this have storeobject stored in it?
    Try destorying the object you're referenced directly, instead of generic GameObject.