Request gc free gameobject.name API

Since there are more and more non-alloc APIs have been introduced, I hope there’s also a gc free for gameobject.name API or just make gameobject.name API gc free. Thanks.

https://feedback.unity3d.com/suggestions/add-non-alloc-property-to-retrieve-an-objects-name

I doubt we’re going to do this. Making it non-alloc would either mean it could no longer be a string - it would have to be a NativeArray or similar - or it would mean preallocating and holding onto managed strings for every object, when the vast majority of the time you don’t need it, so it’d be a big waste of memory.

Why are you retrieving the GO name every frame?

Could you perhaps introduce a CompareName method, similarly to CompareTag?

5 Likes

I suppose unlike tags where you know what you want with names you often want to use the value for further operations, so a compare method wouldn’t help much (it definitely wouldn’t help us at at least :wink: but we also don’t poll all the names often but just certain ones when needed).

What about just caching the managed string once the name has been requested once? No overhead for those that don’t use object.name but way better when a name is requested multiple times.

1 Like

I submitted a bug-report last year:
(Case 924008) Accessing .name property allocates memory

My suggestion to this response was:

The issue has been close anyway. I don’t think they’re going to improve that.

That’s more plausible.

Unfortunately that is still overhead - we would have to add storage to each object (an extra ~8 bytes I think) for holding a pointer to the cached string (even if it’s NULL for most objects).

2 Likes

To me, using GameObject names at all seems like a bad practice in the first place (in terms of code/architecture robustness)… unless it is for debug and editor tools purposes, in which case GC allocs don’t really matter

I dont think it should be encouraged by adding a .GetNameNonAlloc()

Same as with any sort of GameObject.Find() method. If it were up to me, they’d be gone from the API completely so no one even has the option to use them

7 Likes

Would be sweet if we at least had something like object.GetNameHash() which just returns the hash of the name string without allocating anything for all Unity Objects (GameObjects, ScriptableObjects, etc)

3 Likes

D: i don’t understand how ppl can use name for any other thing than debugging

2 Likes

The times it shows up are all with regards to animation, since animations are based on bone names rather than direct object links. We cache all of those bindings at editor time, but I can imagine that there are situations where that’s not viable.

1 Like

Names can be very useful for convention based api’s of various types. And those do often carry over to runtime.

1 Like

Unity does! The entire mecanim paramater system, shader property system and AudioMixer paramater system which or official Unity APIs are all fundamentally based on string IDs.

It’s simple and it works.

We use the HashCode of the name of a Node ScriptableObject in our Research Tree ScriptableObject as the “ID” of that Node. We reference the nodes by their name hash in the players save file etc.

SaveFile.ResearchTree.GetNode(node.name.hashcode).IsUnlocked.() //etc
1 Like

On instancing I concatenate the name of the prefab with a UID, it’s convenient.

I’m using it for game object pooling. Not access every frame though. Currently I’m using 2 dictionary to solve this gc issue. The first dictionary will get the game object asset based on the name then the second dictionary will get the pooled game object based on game object asset. Game object asset is basically load the game object from Resources.Load or Asset Bundle. Another thing is I see Unity 2018 will introduce ResourceManager that will replace Resources.Load. From what I understand about ResourceManager is that it will directly load and instantiate the game object. If that’s the case my current solution will not work anymore as I have no way to get game object asset anymore.

Here’s roughly how I’d handle this:

  • A ScriptableObject contains direct references to all prefabs you wish to instantiate (instead of loading by name)
  • A dictionnary is created at the moment of instantiating your objects for pooling. This dictionnary’s key is the source prefab GameObject, and the value is the instance(s).

That way nothing relies on names that could potentially change, and nothing creates GC allocs. Everything works with direct references, making it bulletproof

2 Likes

Rather than using Object.name as dictionary key, I use Object.GetInstanceID, which is faster to look up objects and does not produce garbage memory. However, GetInstanceID is different every time you restart the game/level, so it might not a solution that fits all cases.

FWIW, that’s more or less how my pooling system works, if it’s boiled down to basics.

No you dont need to add storage to GameObject.
String in .Net is SharedString so if I have this string somewhere in memory that creating same string just return pointer to existing one.

Just use this api inside you getName implementation and you will never allocate more then once

superpig is probably referring to a member variable that must be added to UnityEngine.Object, which would point to that string in memory. Even if it points to null, that field still costs you either 4 or 8 bytes memory, depending on pointer size.

1 Like