代码分析
-
ResInfoBase
与ResInfo<T>
:ResInfoBase
是资源信息的基类,定义了一个refCount
属性,用于记录资源的引用计数。ResInfo<T>
是泛型类,用于保存具体类型T
的资源信息。它包含了资源对象asset
、异步加载结束后的回调callBack
、协程对象coroutine
,以及isDel
标志,决定是否在引用计数为0时真正移除资源。
-
ResMgr
类:- 继承自
BaseManager<ResMgr>
,实现了单例模式,保证资源管理器在整个项目中只有一个实例。 resDic
是一个字典,用于存储已经加载的资源以及其对应的资源信息(ResInfoBase
)。Load<T>
:同步加载 Resources 下的资源,并根据路径和类型将资源存储在字典中。LoadAsync<T>
:异步加载资源,使用协程进行异步操作,并在加载完成后调用回调函数callBack
。UnloadAsset<T>
:根据资源路径卸载不再使用的资源,通过引用计数系统确保资源安全地被卸载。UnloadUnusedAssets
和ClearDic
:分别提供了卸载未使用资源和清空字典的功能,优化内存。
- 继承自
案例:实现一个子弹对象的加载与复用
在一个射击类游戏中,子弹是频繁生成和销毁的对象。我们可以使用 ResMgr
实现一个子弹的加载和对象池复用,从而避免频繁的 Instantiate
和 Destroy
操作,提升性能。
1. 准备工作:
- 创建一个名为
Bullet
的子弹预制体,并将其保存在 Resources 目录下。 - 编写
Bullet
类来处理子弹的逻辑,比如移动和销毁。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResBullet : MonoBehaviour
{
public float speed = 10f;
public float lifeTime = 2f;
private void OnEnable()
{
Invoke(nameof(Recycle), lifeTime);
}
private void Update()
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
void Recycle()
{
ResMgr.Instance.UnloadAsset<GameObject>("ResBullet", true);
gameObject.SetActive(false);
}
}
2. 子弹生成管理器:
编写一个 BulletManager
类,负责生成子弹,并通过 ResMgr
管理子弹的加载和回收。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResBulletManager : BaseManager<ResBulletManager>
{
public string bulletPrefabPath = "ResBullet";
ResBulletManager() { }
public void ShootBullet(Vector3 position, Quaternion rotation)
{
GameObject bullet = ResMgr.Instance.Load<GameObject>(bulletPrefabPath);
if (bullet != null)
{
GameObject.Instantiate(bullet);
bullet.SetActive(true);
bullet.transform.position = position;
bullet.transform.rotation = rotation;
}
}
public void ShootBulletAsync(Vector3 position, Quaternion rotation)
{
Debug.Log("ShootBulletAsync");
ResMgr.Instance.LoadAsync<GameObject>(bulletPrefabPath, (bullet) =>
{
Debug.Log("ShootBulletAsync1");
if (bullet != null)
{
Debug.Log("ShootBulletAsync2");
GameObject.Instantiate(bullet);
bullet.SetActive(true);
bullet.transform.position = position;
bullet.transform.rotation = rotation;
}
});
}
public void RecycleBullet(GameObject bullet)
{
ResMgr.Instance.UnloadAsset<GameObject>("Bullet", true);
bullet.SetActive(false);
}
}
3. 测试步骤:
- 将
BulletManager
脚本挂载到主角或场景中的某个物体上。 - 在游戏中按下某个按键时调用
ShootBullet
或ShootBulletAsync
来发射子弹:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResPlayerController : MonoBehaviour
{
public Transform firePoint;
private void Start()
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Space");
ResBulletManager.Instance.ShootBullet(firePoint.position, firePoint.rotation);
}
if (Input.GetKeyDown(KeyCode.A))
{
Debug.Log("A");
ResBulletManager.Instance.ShootBulletAsync(firePoint.position, firePoint.rotation);
}
}
}
案例总结:
通过这个案例,你展示了如何使用 ResMgr
来管理子弹对象的加载与回收,从而避免频繁的实例化和销毁操作。ResMgr
提供了同步和异步加载两种方式,结合引用计数系统和资源池,能够有效优化资源管理,提高游戏性能。