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

Object not destroyed quick enough.

Discussion in 'Scripting' started by MatrixQ, Jun 14, 2020.

  1. MatrixQ

    MatrixQ

    Joined:
    May 16, 2020
    Posts:
    87
    I have an inventory system with 2 extra cameras set aside to display active elements of the inventory. One camera activates when the mouse is hovering over an inventory item and displays the item rotating. The other camera shows the item you chose by clicking on it and it's displayed on an image following the mouse. So far, so good, that works well.

    To have an item in the inventory, it needs a still image. To get that, the new object is put before the hover camera, the render texture is saved to a Texture2D and the item is destroyed again.

    This is my adding code:
    Code (CSharp):
    1.     public void addItemtoInventory(GameObject addedItem)
    2.     {
    3.         GameObject go = Instantiate(addedItem, active.transform.position, active.transform.rotation);
    4.         InventoryItem it = new InventoryItem(addedItem);
    5.         it.setImage(activeCam, active.transform.rotation);
    6.         Destroy(go);
    7.         inventory.Add(it);
    8.         PutImagesInInventory();
    9.     }
    This is taking the image:
    Code (CSharp):
    1.     public void setImage(Camera cam, Quaternion r)
    2.     {
    3.         rot = r;
    4.         cam.Render();
    5.         RenderTexture rTex = cam.targetTexture;
    6.         Texture2D tex = new Texture2D(rTex.width, rTex.height, TextureFormat.RGBA32, false);
    7.         RenderTexture.active = rTex;
    8.         tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
    9.         tex.Apply();
    10.  
    11.         Color col;
    12.         for(int i = 0; i<tex.width;i++)
    13.         {
    14.             for (int j = 0; j < tex.height; j++)
    15.             {
    16.                 float g = tex.GetPixel(i, j).grayscale;
    17.                 col = new Color(g, g, g, tex.GetPixel(i, j).a);
    18.                 tex.SetPixel(i, j, col);
    19.             }
    20.         }
    21.         tex.Apply();
    22.        
    23.         invImg = tex;
    24.     }
    Additionally, any time an object goes from active hover to passive image, the image gets taken again, with the new rotation.

    To test this, I got a list of 3 prefabs I just plug in with the inspector and I add these items to the inventory with a foreach loop over that list. Pretty much how I would do it, if I were to load a save game as well, I'd say.

    Problem is, the gameobject doesn't get destroyed. This works fine once it's loaded and I go over the inventory items with the mouse, so it reloads them, but at first, it doesn't really work well.

    It should look something like this:


    But it looks like this on first load:


    Any idea how I can load a bunch of items at once, without them stacking like this?
     
  2. dhenion65

    dhenion65

    Joined:
    Dec 17, 2019
    Posts:
    21
    Have you tried DestroyImmediate() ?
     
    busterlock likes this.
  3. MatrixQ

    MatrixQ

    Joined:
    May 16, 2020
    Posts:
    87
    Would you look at that, it works. Thank you very much.
     
    busterlock likes this.
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Be aware that DestroyImmediate is not recommended to be used. If it works for you that's fine, but read up on it a bit so that you know what you are dealing with. A bug in your code can lead to a permanent loss of a prefab or asset (in editor scripts only afaik), and functions like OnDestroy are getting called at unusual times, potentially leading to hard to fix nullreference exceptions or other unpleasant sideeffects.

    https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html
    https://forum.unity.com/threads/so-why-is-destroyimmediate-not-recommended.526939/
     
  5. MatrixQ

    MatrixQ

    Joined:
    May 16, 2020
    Posts:
    87
    Hmm, if that's the case, I'd surely prefer the safe way. I guess I would need to update the frame when doing it, so I would only be able to take 1 picture per frame. Any idea how I can implement that in my system?
     
  6. dhenion65

    dhenion65

    Joined:
    Dec 17, 2019
    Posts:
    21
    Good to know Yoreki I wasn't aware of that.
    Could you try moving the object to some far away off-camera location before calling Destroy() then let it get cleared out when the destroy finishes? As for one picture per frame some sort of state variable or even a counter could be used to do one per frame.
     
  7. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    10,004
    Check out the Coroutines. Read up on them, you can return from a method tentatively with the intention that the rest of the method will be executed in the next frame.

    - take your first photo
    - yield return null;
    - take your second photo next frame
    - end of method
     
    Last edited: Jun 15, 2020
    PraetorBlue likes this.
  8. MatrixQ

    MatrixQ

    Joined:
    May 16, 2020
    Posts:
    87
    Will do, thank you very much.
     
  9. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    Would it work to disable the renderer between photos? Or move an object to a layer outside the camera's culling mask? Or just move the object outside of the camera's view frustum?
     
  10. MatrixQ

    MatrixQ

    Joined:
    May 16, 2020
    Posts:
    87
    I solved it using a coroutine. It works, though it creates other problems due to the way I set things up, but those are easily fixable.

    I will try moving the objects out of the way as well, since the coroutine approach means I will only be able to load 60 items per second. I will probably not have that many items lying around, but I don't really like that.

    In any case, I now know 3 ways to solve this problem, so thank you everyone.