private void RemoveObject(object handler, int objId)
        {
            var key = handler.GetHashCode();

            if (this.handlerToObjects.TryGetValue(key, out var list) == true)
            {
                var resItem = new InternalResourceItem(handler, objId);
                if (list.Remove(resItem) == true)
                {
                    if (list.Count == 0)
                    {
                        this.handlerToObjects.Remove(key);
                    }
                }
            }
        }
        private void AddObject(object handler, object obj, Resource resource)
        {
            var key = handler.GetHashCode();

            if (this.handlerToObjects.TryGetValue(key, out var list) == false)
            {
                list = new HashSet <InternalResourceItem>();
                this.handlerToObjects.Add(key, list);
            }

            {
                var resItem = new InternalResourceItem(handler, obj, resource);
                if (list.Contains(resItem) == false)
                {
                    list.Add(resItem);
                }
            }
        }
        private void UnloadObject(object handler, object obj)
        {
            var key = handler.GetHashCode();

            if (this.handlerToObjects.TryGetValue(key, out var list) == true)
            {
                var objId   = obj.GetHashCode();
                var resItem = new InternalResourceItem(handler, objId);
                foreach (var item in list)
                {
                    if (item.GetHashCode() == resItem.GetHashCode())
                    {
                        //Debug.Log("Attempt to unload object " + obj + " (handler: " + handler + "), type: " + item.resourceSource.type);
                        switch (item.resourceSource.type)
                        {
                        case Resource.Type.Manual: {
                            // TODO: Put into pool if object could been pooled

                            if (obj is Object o)
                            {
                                Object.DestroyImmediate(o);
                            }
                        }
                        break;

                        case Resource.Type.Direct: {
                            // Direct asset skipped because there are always in memory
                        }
                        break;

                        case Resource.Type.Addressables: {
                            UnityEngine.AddressableAssets.Addressables.Release(obj);
                        }
                        break;
                        }

                        break;
                    }
                }
            }
        }