Search Unity

Question Destroying Clones Simple Issue

Discussion in 'Scripting' started by LeoVInci, Jun 4, 2023.

  1. LeoVInci

    LeoVInci

    Joined:
    Mar 5, 2015
    Posts:
    3
    Hey, I have a simple issue but I'm relatively new and can't figure it out. I define enemyClone at the top as a gameObject and want the clone to be destroyed once it's past a certain Z position to make room for the new one being created. However, the Destroy function is destroying it in a way that doesn't allow me to reference it for creation again.

    I have tried defining enemyClone in the function as
    var enemyClone = (...) as GameObject;
    but then can't figure out how to access enemyClone in the other parts of the function for the other things I need to do. Any insight would be appreciated.

    Code (csharp):
    1.  
    2. public class Enemy : MonoBehaviour
    3. {
    4.     public float spawnPosX;
    5.     public float constantZMovement;
    6.     public float moveSpeed = -8f;
    7.  
    8.     public Rigidbody rb;
    9.  
    10.     public GameObject enemy;
    11.     public GameObject enemyClone;
    12.  
    13.     public EnemyMovement enemyMovement;
    14.  
    15.     public float Timer;
    16.     public float reduceTime = 0f;
    17.  
    18.     public float score = 0;
    19.  
    20.  
    21.  
    22.  
    23.     // Start is called before the first frame update
    24.     void Start()
    25.     {
    26.         createEnemy();
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void Update()
    31.     {
    32.         createEnemy();
    33.     }
    34.     void createEnemy()
    35.     {
    36.         enemyClone.transform.position += new Vector3(0, 0, Time.deltaTime * moveSpeed);
    37.         if (enemyClone.transform.position.z <= -6)
    38.         {  
    39.             spawnPosX = Random.RandomRange(-7, 7);
    40.             enemyClone = Instantiate(enemy, (new Vector3(spawnPosX, 3, 15)), transform.rotation);
    41.             moveSpeed -= 0.3f;
    42.             score += 1;
    43.             Destroy(enemyClone);
    44.         }
    45.     }
    46.    
    47.    
    48. }
    49.  
     

    Attached Files:

    Last edited: Jun 4, 2023
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    Photographs of code are not a thing.

    If you post a code snippet, ALWAYS USE CODE TAGS:

    How to use code tags: https://forum.unity.com/threads/using-code-tags-properly.143875/

    As to your question,

    Referencing variables, fields, methods (anything non-static) in other script instances:

    https://forum.unity.com/threads/hel...-vars-in-another-script.1076825/#post-6944639

    https://forum.unity.com/threads/accessing-a-gameobject-in-different-scene.1103239/

    It isn't always the best idea for everything to access everything else all over the place. For instance, it is BAD for the player to reach into an enemy and reduce his health.

    Instead there should be a function you call on the enemy to reduce his health. All the same rules apply for the above steps: the function must be public AND you need a reference to the class instance.

    That way the enemy (and only the enemy) has code to reduce his health and simultaneously do anything else, such as kill him or make him reel from the impact, and all that code is centralized in one place.
     
  3. LeoVInci

    LeoVInci

    Joined:
    Mar 5, 2015
    Posts:
    3
    Hello, thanks for the response. Do you have any insight as to where im going wrong destroying the clone?
    Everything works correctly with my code right now except for the destroying. The error I get is (The object of type GameObject is being destroyed but you are still trying to reference it.)
    Im guessing I have something wrong with how I define and reference things but I can't figure out the proper way to go about it.
     
  4. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    Your code isn't doing what it is supposed to do, which means it isn't working properly at all.

    You are instantiating an object, assigning it to a field that you then tell the engine to destroy. Destroy it first then instantiate a new one.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    This is just a null reference by any other name, and the answer is ALWAYS the same:

    How to fix a NullReferenceException error

    https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

    Three steps to success:
    - Identify what is null <-- any other action taken before this step is WASTED TIME
    - Identify why it is null
    - Fix that

    If your program is not executing the way you expect and you have no errors...

    Time to start debugging! Here is how you can begin your exciting new debugging adventures:

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the names of the GameObjects or Components involved?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
  6. LeoVInci

    LeoVInci

    Joined:
    Mar 5, 2015
    Posts:
    3
    You were correct here, now instead of crashing right away it reaches the point where it's supposed to destroy and then crashes upon trying to create a new one. The code is obviously referencing something wrong when attempting to instantiate a new object, else the destroy code would work but I'm having a hard time figuring out where exactly this is.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    See debug steps above. Nobody here can do it for you. One thing at a time until you find it.
     
  8. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    This 100%
     
    Kurt-Dekker likes this.
  9. Hexolenn

    Hexolenn

    Joined:
    Dec 27, 2021
    Posts:
    44
    Code (csharp):
    1.  
    2.     public GameObject enemy;
    3.     public GameObject enemyClone;
    4.  
    In here if you are putting the same prefab to both of them or a prefab you shouldn't change that is your problem.

    Code (csharp):
    1.  
    2. spawnPosX = Random.RandomRange(-7, 7);
    3. enemyClone = Instantiate(enemy, (new Vector3(spawnPosX, 3, 15)), transform.rotation);
    4. moveSpeed -= 0.3f;
    5.  score += 1;
    6. Destroy(enemyClone);
    7.  
    I think the part you are doing wrong is that you already have a "GameObject enemyClone" so when instantiate works it deletes your enemy prefab because you overwrite it. You need to make it like

    var temp = Instantiate(enemy, (new Vector3(spawnPosX, 3, 15)), transform.rotation);

    With this you will be actually creating a new clone instead of writing over one.

    after this to find them easily add them a tag like "enemyClone" so finding and destroing them can be done easily

    Code (csharp):
    1.  
    2. temp.tag = "EnemyClone";
    3. var clones = GameObject.FindGameObjectsWithTag("EnemyClone");
    4. foreach (var clone in clones)
    5. {
    6.     Destroy(clone);
    7. }
    8.  
    With this you will be creating NEW clones instead of WRITING OVER one. And destroying them using tags. The code I provided here might not work in your code this was a copy of my code you would still need to learn and understand how to put it into your code but this is as much as I can help I am a new unity user as well.

    Good Luck!