1
\$\begingroup\$

I have a Prefab with a number of Components, such as:

  • Rect Transform
  • Text Mesh Pro
  • Sprite Renderer
  • Box Collider 2D

I think Instantiate a GameObject using the Prefab, and configure it. As the GameObject is configured, some of the settings get changed:

  • The Sprite of the Sprite Renderer is customized
  • The text in the Text Mesh Pro object gets changed
  • The height/width of the Rect Transform gets customized to match the above
  • The Size and Offset of the Box Collider also gets customized to match

As the game progresses over time, some of these settings may continue to change. This continues until the GameObject is no longer needed.

I'm looking for a way to reset all the GameObject's component settings to match the original Prefab. That will allow me to scrub the GameObject, and set up Object Pooling.

Resetting the GameObject's settings pretty easy to do manually: I can just audit the code and make a list of all possible changes, and manually change each of the settings back to the default value.

I don't mind doing this work, but am wondering if there's an easy way to check my work.

  1. Is there a way that I can easily compare a GameObject's component settings to a Prefab's component setting, and identify which ones are different?

  2. Or alternatively, is there a way to check if the settings for two components are identical? Other than just visually inspecting both Components' Settings...

Or if there's an easier way to do all this, please let me know!

\$\endgroup\$
3
  • \$\begingroup\$ Why not have an Init method on your GO that has the default values? Setting fixed values should always be faster compared to do a deep comparison between all values and you would still need to set them \$\endgroup\$
    – Zibelas
    Feb 24, 2023 at 9:51
  • \$\begingroup\$ Yah I will do that... but then I'd like to check the results quickly and easily and see if the two sets of Component Settings are equal! I'll be doing this with dozens/hundreds of GameObjects (to doublecheck that it's working), so just wondering if there's an easy way to compare two Component settings. If not, I can write a script to check each field one at a time... \$\endgroup\$
    – kanamekun
    Feb 24, 2023 at 10:13
  • 1
    \$\begingroup\$ To compare fast the settings of two objects, you could write a custom hash/ equals method that just takes the values of the settings you are interested in. \$\endgroup\$
    – Zibelas
    Feb 24, 2023 at 10:18

1 Answer 1

1
\$\begingroup\$

Part 1 indirection

"We can solve any problem by introducing an extra level of indirection."

There are many opportunities for modification of the GameObject:

  1. "Instantiate a GameObject using the Prefab, and configure it."
  2. "As the game progresses over time, some of these settings may continue to change."
  3. "... and manually change each of the settings back to the default value."(before put it back to the pool)

The question now is you want to reduce the effort of manually reviewing code. Why is this a problem? Because the code to access the GameObject is everywhere. Currently your code is highly coupled.

enter image description here

In order to solve this, we need to confine the access to the GameObject to the same place, that is to say, we need to abstract and encapsulate the GameObject. You may be interested in Facade pattern:

Analogous to a facade in architecture, a facade is an object that serves as a front-facing interface masking more complex underlying or structural code.

We need to create a class that manages the GameObject, specifying which interfaces are exposed, and all access to the GameObject must be done through this class instead of directly accessing its child nodes/internal information:

public class MyText : MonoBehaviour
{
    private RectTransform trans;
    private TextMeshPro textMeshPro;
    private SpriteRenderer renderer;
    private BoxCollider2D collider;

    void Awake()
    {
        trans = xxx.GetComponent<RectTransform>();
        textMeshPro = xxx.GetComponent<TextMeshPro>();
        renderer = xxx.GetComponent<SpriteRenderer>();
        collider = xxx.GetComponent<BoxCollider2D>();
    }
    public void Init(string text,Sprite sprite)
    {
        SetText(text);
        SetSprite(sprite);
    }
    public void Reset()
    {
        SetText("");
        SetSprite(null);
    }
    public void SetText(string text)
    {
        textMeshPro.text = text;
        collider...
        trans....
    }
    public void SetSprite(Sprite sprite)
    {
        renderer.sprite = sprite;
    }

}

In the pseudo-code above, only four methods are exposed, because the outside only needs to call these methods to control its functions.

The height/width of the Rect Transform gets customized to match the above. The Size and Offset of the Box Collider also gets customized to match.

These are completely dependent on its text content, so they don't need to be exposed, but processed internally.

Part 2 memory pool

The memory pool is completely used to optimize performance, and it is necessary to consider whether it achieves the purpose for different usage scenarios. Everything is subject to performance testing, but I have some guesses here.

  1. Is it necessary to reset the object before putting it back into the mempool? If you initialize every time before use, then reset is not necessary.

  2. Are objects put into the same memory pool similar enough? For example where does the current Sprite come from? If they are loaded from another place (disk) and placed on this object, then the consumption of modifying the difference of the object in is very large, in other words, they are not similar enough. Generally speaking, the consumption of reading data from the disk is relatively large, and the memory pool strategy should try to solve this part of the consumption. You can create different memory pools for objects holding different sprites, which can maximize their similarity.

  3. What happens when the object is recycled to the memory pool? There are a few different ways to handle unused pool objects in Unity. Examples include setting Active, turning off component functionality (such as a particle system), or simply moving it offscreen. Different objects will have different performance, similarly, the test shall prevail.

\$\endgroup\$
2
  • \$\begingroup\$ You are right that I could do a better job of creating clean interfaces to set these various variables! I will do that, and hopefully that will reduce the surface area of the variables I need to check. As for the Rect Transform and Box Collider 2d, actually it's a word game and so the text does determine those sizes. But I can calculate it internally as you say! \$\endgroup\$
    – kanamekun
    Feb 24, 2023 at 16:03
  • \$\begingroup\$ 1. You are right that it's not necessary to reset every object variable before recycling the object. A good reminder! 2. For now I just have one object pool, but will keep this in mind as I add more types of objects 3. I think for now I'll just make the GameObject Inactive... but am open to other options if they are more efficient! Thank you again. \$\endgroup\$
    – kanamekun
    Feb 24, 2023 at 16:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .