1.GF万物基于引用池IReference
2.ObjectBase : IReference类的m_Target持有unity中Mono,资源,GameObejct
3.AssetObject : ObjectBase类m_Target持有Assetbundle中的Asset,具有获取,引用两个计数管理释放
4.ResourceObject : ObjectBase类m_Target持有Assetbundle,具有获取,引用两个计数管理释放
5.EntityInstanceObject : ObjectBase类m_Target指向Assetbundle中的Asset实例化后的GameObject,内部m_EntityAsset也是Assetbundle中的Asset
6.对象池具有按照间隔自动释放无用对象,对于实体,获取为0,即无用对象;对于AssetObject,ResourceObject要获取为0,父依赖(自己被别依赖)为0,即无用
7.引用的概念为资源被依赖,例如bundleA依赖bundleB,于是bundleB的引用=1
8.获取的概念:针对资源为对象再派生(关联)出别的对象,例如ResourceObjectA派生出AssetObjectA,即ResourceObjectA获取为1;AssetObjectA再派生出EntityInstanceObjectA,AssetObjectA的获取为1
只能单获取,即不能对一个对象反复Spawn
m_InstancePool = objectPoolManager.CreateSingleSpawnObjectPool<EntityInstanceObject>(Utility.Text.Format("Entity Instance Pool ({0})", name), instanceCapacity, instanceExpireTime, instancePriority);
public void SetObjectPoolManager(IObjectPoolManager objectPoolManager)
{
m_AssetPool = objectPoolManager.CreateMultiSpawnObjectPool<AssetObject>("Asset Pool");
m_ResourcePool = objectPoolManager.CreateMultiSpawnObjectPool<ResourceObject>("Resource Pool");
}
1.每次使用看实体对象池中有无,有是指存在空闲未使用实体对象,取出来用
2.没有的话,需要从资源加载流程中走一遍
UnityGameFramework.Runtime.DefaultEntityHelper.ReleaseEntity
///
/// 释放实体。
///
/// 要释放的实体资源。
/// 要释放的实体实例。
public override void ReleaseEntity(object entityAsset, object entityInstance)
{
m_ResourceComponent.UnloadAsset(entityAsset);
Destroy((Object)entityInstance);
}
1.AssetPool中把entityAsset的获取-1
2.销毁asset实例出来的GameObject
在assetA加载完,assetA的依赖asset的bundle引用+1。注意是依赖的asset的bundle,自身的bundle并不会引用+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.OnLoadResourceAgentHelperLoadComplete
foreach (object dependencyAsset in dependencyAssets)
{
object dependencyResource = null;
if (m_ResourceLoader.m_AssetToResourceMap.TryGetValue(dependencyAsset, out dependencyResource))
{
m_Task.ResourceObject.AddDependencyResource(dependencyResource); //所有依赖这个asset的resource引用+1
}
同时被依赖的bundleB加入到主bundleA的ResourceObject依赖列表中
GameFramework.Resource.ResourceManager.ResourceLoader.ResourceObject.AddDependencyResource
m_DependencyResources.Add(dependencyResource);
bundle被释放时,子依赖bundle引用-1
GameFramework.Resource.ResourceManager.ResourceLoader.ResourceObject.Release
foreach (object dependencyResource in m_DependencyResources)
{
int referenceCount = 0;
if (m_ResourceLoader.m_ResourceDependencyCount.TryGetValue(dependencyResource, out referenceCount))
{
m_ResourceLoader.m_ResourceDependencyCount[dependencyResource] = referenceCount - 1;
//只会-1,不会对为 0 的Assetbundle进行卸载
}
bundleA中获取assetA时,获取+1。此时有有两种情况,
1.执行加载asset任务时,主bundle已加载,从ResourcePool中获取
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.Start
ResourceObject resourceObject = m_ResourceLoader.m_ResourcePool.Spawn(resourceName);
if (resourceObject != null)
{
GameFrameworkLog.Info("ResourcePool获取到了{0},说明asset:{1}的bundle已经加好了,返回bundle", resourceName, m_Task.AssetName);
//从resource对象池中取出,说明之前加载过Assetbundle,任务可以接着执行
OnResourceObjectReady(resourceObject);
return StartTaskStatus.CanResume;
}
2.bundle未加载,加载完后注册入对象池,获取+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.OnLoadResourceAgentHelperReadFileComplete
private void OnLoadResourceAgentHelperReadFileComplete(object sender, LoadResourceAgentHelperReadFileCompleteEventArgs e)
{
GameFrameworkLog.Info("Assetbundle加载完成:{0}", m_Task.ResourceInfo.ResourceName.Name);
ResourceObject resourceObject = ResourceObject.Create(m_Task.ResourceInfo.ResourceName.Name, e.Resource, m_ResourceHelper, m_ResourceLoader);
m_ResourceLoader.m_ResourcePool.Register(resourceObject, true);
s_LoadingResourceNames.Remove(m_Task.ResourceInfo.ResourceName.Name);
OnResourceObjectReady(resourceObject);
}
GameFramework.Resource.ResourceManager.ResourceLoader.AssetObject.Release
m_ResourceLoader.m_ResourcePool.Unspawn(m_Resource);
assetA新加载完成时,创建AssetObjectA,把子依赖asset引用+1
GameFramework.Resource.ResourceManager.ResourceLoader.AssetObject.Create
//所有依赖的asset 引用+1,它自己次数不会+1
foreach (object dependencyAsset in dependencyAssets)
{
int referenceCount = 0;
GameFrameworkLog.Info("AssetObject创建-->{0}引用次数+1", dependencyAsset);
if (resourceLoader.m_AssetDependencyCount.TryGetValue(dependencyAsset, out referenceCount))
{
resourceLoader.m_AssetDependencyCount[dependencyAsset] = referenceCount + 1;
}
else
{
resourceLoader.m_AssetDependencyCount.Add(dependencyAsset, 1);
}
}
AssetObjectA释放时,把所有子依赖资源-1。这里只会找直接子依赖(子节点),不会找到孙节点上
GameFramework.Resource.ResourceManager.ResourceLoader.AssetObject.Release
foreach (object dependencyAsset in m_DependencyAssets)
{
int referenceCount = 0;
if (m_ResourceLoader.m_AssetDependencyCount.TryGetValue(dependencyAsset, out referenceCount))
{
m_ResourceLoader.m_AssetDependencyCount[dependencyAsset] = referenceCount - 1;
//子依赖的asset -1
}
AssetObject的获取,是为了给实例对象实例化。两种情况下
1.任务执行时,AssetPool有,直接返回,获取+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.Start
//从对象池里拿一个
AssetObject assetObject = m_ResourceLoader.m_AssetPool.Spawn(m_Task.AssetName);
if (assetObject != null)
{
//说明资源之前加载过,且在AssetObject缓存池中
//一旦成功执行Spawn,Spawn+1,在释放资源时不为0会跳过
GameFrameworkLog.Info("AssetPool获取到了{0},不需要加载,直接返回asset", m_Task.AssetName);
//如果是实体,实例化asset,并且新建一个实体对象
OnAssetObjectReady(assetObject);
return StartTaskStatus.Done;
}
2.AssetPool没有,从Assetbundle中加载完成asset,创建新AssetObject,并注册进入AssetPool,获取+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.OnLoadResourceAgentHelperLoadComplete
assetObject = AssetObject.Create(m_Task.AssetName, e.Asset, dependencyAssets, m_Task.ResourceObject.Target, m_ResourceHelper, m_ResourceLoader);
GameFrameworkLog.Info("asset-->{0}加载完成,并且创建AssetObject到m_AssetPool缓冲池中", m_Task.AssetName);
m_ResourceLoader.m_AssetPool.Register(assetObject, true);
EntityInstanceObject释放时
UnityGameFramework.Runtime.DefaultEntityHelper.ReleaseEntity
///
/// 释放实体。
///
/// 要释放的实体资源。
/// 要释放的实体实例。
public override void ReleaseEntity(object entityAsset, object entityInstance)
{
m_ResourceComponent.UnloadAsset(entityAsset);
Destroy((Object)entityInstance);
}
加载一个实体,一个asset作为主任务,asset依赖的各个asset作为依赖任务
任务派生LoadAssetTask,LoadDependencyAssetTask,LoadSceneTask
资源准备好,即任务完成。不管是是从AssetPool中获取,还是异步加载完成
private void OnAssetObjectReady(AssetObject assetObject)
{
m_Helper.Reset();
object asset = assetObject.Target;
if (m_Task.IsScene)
{
m_ResourceLoader.m_SceneToAssetMap.Add(m_Task.AssetName, asset);
}
m_Task.OnLoadAssetSuccess(this, asset, (float)(DateTime.UtcNow - m_Task.StartTime).TotalSeconds);
m_Task.Done = true;
}
隐藏某实体时,在对象池自动释放中,如果改实体池依赖的asset获取为0,再判断出bundle获取为0,触发assetbundle.Unload(true),释放内存