unity资源管理帮助

public class ABInfo : Component
{
	private int refCount;
	public string Name { get; }

	public int RefCount
	{
		get
		{
			return this.refCount;
		}
		set
		{
			//Log.Debug($"{this.Name} refcount: {value}");
			this.refCount = value;
		}
	}

	public AssetBundle AssetBundle { get; }

	public ABInfo(string name, AssetBundle ab)
	{
		this.InstanceId = IdGenerater.GenerateId();
		this.Name = name;
		this.AssetBundle = ab;
		this.RefCount = 1;
		//Log.Debug($"load assetbundle: {this.Name}");
	}

	public override void Dispose()
	{
		if (this.IsDisposed)
		{
			return;
		}

		base.Dispose();

		//Log.Debug($"desdroy assetbundle: {this.Name}");

		this.AssetBundle?.Unload(true);
	}
}

// 用于字符串转换,减少GC
public static class AssetBundleHelper
{
	public static readonly Dictionary<int, string> IntToStringDict = new Dictionary<int, string>();
	
	public static readonly Dictionary<string, string> StringToABDict = new Dictionary<string, string>();

	public static readonly Dictionary<string, string> BundleNameToLowerDict = new Dictionary<string, string>() 
	{
		{ "StreamingAssets", "StreamingAssets" }
	};
	
	// 缓存包依赖,不用每次计算
	public static Dictionary<string, string[]> DependenciesCache = new Dictionary<string, string[]>();

	public static string IntToString(this int value)
	{
		string result;
		if (IntToStringDict.TryGetValue(value, out result))
		{
			return result;
		}

		result = value.ToString();
		IntToStringDict[value] = result;
		return result;
	}
	
	public static string StringToAB(this string value)
	{
		string result;
		if (StringToABDict.TryGetValue(value, out result))
		{
			return result;
		}

		result = value + ".unity3d";
		StringToABDict[value] = result;
		return result;
	}

	public static string IntToAB(this int value)
	{
		return value.IntToString().StringToAB();
	}
	
	public static string BundleNameToLower(this string value)
	{
		string result;
		if (BundleNameToLowerDict.TryGetValue(value, out result))
		{
			return result;
		}

		result = value.ToLower();
		BundleNameToLowerDict[value] = result;
		return result;
	}
	
	public static string[] GetDependencies(string assetBundleName)
	{
		string[] dependencies = new string[0];
		if (DependenciesCache.TryGetValue(assetBundleName,out dependencies))
		{
			return dependencies;
		}
		if (!Define.IsAsync)
		{
 #if UNITY_EDITOR
			dependencies = AssetDatabase.GetAssetBundleDependencies(assetBundleName, true);
#endif
		}
		else
		{
			dependencies = ResourcesComponent.AssetBundleManifestObject.GetAllDependencies(assetBundleName);
		}
		DependenciesCache.Add(assetBundleName, dependencies);
		return dependencies;
	}

	public static string[] GetSortedDependencies(string assetBundleName)
	{
		Dictionary<string, int> info = new Dictionary<string, int>();
		List<string> parents = new List<string>();
		CollectDependencies(parents, assetBundleName, info);
		string[] ss = info.OrderBy(x => x.Value).Select(x => x.Key).ToArray();
		return ss;
	}

	public static void CollectDependencies(List<string> parents, string assetBundleName, Dictionary<string, int> info)
	{
		parents.Add(assetBundleName);
		string[] deps = GetDependencies(assetBundleName);
		foreach (string parent in parents)
		{
			if (!info.ContainsKey(parent))
			{
				info[parent] = 0;
			}
			info[parent] += deps.Length;
		}

		foreach (string dep in deps)
		{
			if (parents.Contains(dep))
			{
				throw new Exception($"包有循环依赖,请重新标记: {assetBundleName} {dep}");
			}
			CollectDependencies(parents, dep, info);
		}
		parents.RemoveAt(parents.Count - 1);
	}
}


public class ResourcesComponent : Component
{
	public static AssetBundleManifest AssetBundleManifestObject { get; set; }

	private readonly Dictionary<string, Dictionary<string, UnityEngine.Object>> resourceCache = new Dictionary<string, Dictionary<string, UnityEngine.Object>>();

	private readonly Dictionary<string, ABInfo> bundles = new Dictionary<string, ABInfo>();

	public override void Dispose()
	{
		if (this.IsDisposed)
		{
			return;
		}

		base.Dispose();

		foreach (var abInfo in this.bundles)
		{
			abInfo.Value?.AssetBundle?.Unload(true);
		}

		this.bundles.Clear();
		this.resourceCache.Clear();
	}

	
	public bool GetAssetIsNull(string bundleName, string prefab)
	{
		return this.resourceCache.ContainsKey($"{bundleName}/{prefab}".ToLower());
	}

	public UnityEngine.Object GetAsset(string bundleName, string prefab)
	{
		Dictionary<string, UnityEngine.Object> dict;
		if (!this.resourceCache.TryGetValue(bundleName.BundleNameToLower(), out dict))
		{
			throw new Exception($"not found asset: {bundleName} {prefab}");
		}

		UnityEngine.Object resource = null;
		if (!dict.TryGetValue(prefab, out resource))
		{
			throw new Exception($"not found asset: {bundleName} {prefab}");
		}

		return resource;
	}

	public void UnloadBundle(string assetBundleName)
	{
		assetBundleName = assetBundleName.ToLower();

		string[] dependencies = AssetBundleHelper.GetSortedDependencies(assetBundleName);

		//Log.Debug($"-----------dep unload {assetBundleName} dep: {dependencies.ToList().ListToString()}");
		foreach (string dependency in dependencies)
		{
			this.UnloadOneBundle(dependency);
		}
	}

	private void UnloadOneBundle(string assetBundleName)
	{
		assetBundleName = assetBundleName.ToLower();

		ABInfo abInfo;
		if (!this.bundles.TryGetValue(assetBundleName, out abInfo))
		{
			throw new Exception($"not found assetBundle: {assetBundleName}");
		}
		
		//Log.Debug($"---------- unload one bundle {assetBundleName} refcount: {abInfo.RefCount - 1}");

		--abInfo.RefCount;
        
		if (abInfo.RefCount > 0)
		{
			return;
		}
		this.bundles.Remove(assetBundleName);
		abInfo.Dispose();
		//Log.Debug($"cache count: {this.cacheDictionary.Count}");
	}

	/// <summary>
	/// 同步加载assetbundle
	/// </summary>
	/// <param name="assetBundleName"></param>
	/// <returns></returns>
	public void LoadBundle(string assetBundleName)
	{
		assetBundleName = assetBundleName.ToLower();
		string[] dependencies = AssetBundleHelper.GetSortedDependencies(assetBundleName);
		//Log.Debug($"-----------dep load {assetBundleName} dep: {dependencies.ToList().ListToString()}");
		foreach (string dependency in dependencies)
		{
			if (string.IsNullOrEmpty(dependency))
			{
				continue;
			}
			this.LoadOneBundle(dependency);
		}
    }

	public void AddResource(string bundleName, string assetName, UnityEngine.Object resource)
	{
		Dictionary<string, UnityEngine.Object> dict;
		if (!this.resourceCache.TryGetValue(bundleName.BundleNameToLower(), out dict))
		{
			dict = new Dictionary<string, UnityEngine.Object>();
			this.resourceCache[bundleName] = dict;
		}

		dict[assetName] = resource;
	}

	public void LoadOneBundle(string assetBundleName)
	{
		//Log.Debug($"---------------load one bundle {assetBundleName}");
		ABInfo abInfo;
		if (this.bundles.TryGetValue(assetBundleName, out abInfo))
		{
			++abInfo.RefCount;
			return;
		}

		if (!Define.IsAsync)
		{
			string[] realPath = null;
 #if UNITY_EDITOR
			realPath = AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleName);
			foreach (string s in realPath)
			{
				string assetName = Path.GetFileNameWithoutExtension(s);
				UnityEngine.Object resource = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(s);
				AddResource(assetBundleName, assetName, resource);
			}

			this.bundles[assetBundleName] = new ABInfo(assetBundleName, null);
  #endif
			return;
		}

		string p = Path.Combine(PathHelper.AppHotfixResPath, assetBundleName);
		AssetBundle assetBundle = null;
		if (File.Exists(p))
		{
			assetBundle = AssetBundle.LoadFromFile(p);
		}
		else
		{
			p = Path.Combine(PathHelper.AppResPath, assetBundleName);
			assetBundle = AssetBundle.LoadFromFile(p);
		}

		if (assetBundle == null)
		{
			throw new Exception($"assets bundle not found: {assetBundleName}");
		}

		if (!assetBundle.isStreamedSceneAssetBundle)
		{
			// 异步load资源到内存cache住
			UnityEngine.Object[] assets = assetBundle.LoadAllAssets();
			foreach (UnityEngine.Object asset in assets)
			{
				AddResource(assetBundleName, asset.name, asset);
			}
		}

		this.bundles[assetBundleName] = new ABInfo(assetBundleName, assetBundle);
	}

	/// <summary>
	/// 异步加载assetbundle
	/// </summary>
	/// <param name="assetBundleName"></param>
	/// <returns></returns>
	public async Task LoadBundleAsync(string assetBundleName)
	{
        assetBundleName = assetBundleName.ToLower();
		string[] dependencies = AssetBundleHelper.GetSortedDependencies(assetBundleName);
        // Log.Debug($"-----------dep load {assetBundleName} dep: {dependencies.ToList().ListToString()}");
        foreach (string dependency in dependencies)
		{
			if (string.IsNullOrEmpty(dependency))
			{
				continue;
			}
			await this.LoadOneBundleAsync(dependency);
		}
    }

	public async Task LoadOneBundleAsync(string assetBundleName)
	{
		ABInfo abInfo;
		if (this.bundles.TryGetValue(assetBundleName, out abInfo))
		{
			++abInfo.RefCount;
			return;
		}

        //Log.Debug($"---------------load one bundle {assetBundleName}");
        if (!Define.IsAsync)
		{
			string[] realPath = null;
     #if UNITY_EDITOR
			realPath = AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleName);
			foreach (string s in realPath)
			{
				string assetName = Path.GetFileNameWithoutExtension(s);
				UnityEngine.Object resource = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(s);
				AddResource(assetBundleName, assetName, resource);
			}

			this.bundles[assetBundleName] = new ABInfo(assetBundleName, null);
#endif
			return;
		}

		string p = Path.Combine(PathHelper.AppHotfixResPath, assetBundleName);
		AssetBundle assetBundle = null;
		if (!File.Exists(p))
		{
			p = Path.Combine(PathHelper.AppResPath, assetBundleName);
		}
		
		using (AssetsBundleLoaderAsync assetsBundleLoaderAsync = ComponentFactory.Create<AssetsBundleLoaderAsync>())
		{
			assetBundle = await assetsBundleLoaderAsync.LoadAsync(p);
		}

		if (assetBundle == null)
		{
			throw new Exception($"assets bundle not found: {assetBundleName}");
		}

		if (!assetBundle.isStreamedSceneAssetBundle)
		{
			// 异步load资源到内存cache住
			UnityEngine.Object[] assets;
			using (AssetsLoaderAsync assetsLoaderAsync = ComponentFactory.Create<AssetsLoaderAsync, AssetBundle>(assetBundle))
			{
				assets = await assetsLoaderAsync.LoadAllAssetsAsync();
			}
			foreach (UnityEngine.Object asset in assets)
			{
				AddResource(assetBundleName, asset.name, asset);
			}
		}

		this.bundles[assetBundleName] = new ABInfo(assetBundleName, assetBundle);
	}

	public string DebugString()
	{
		StringBuilder sb = new StringBuilder();
		foreach (ABInfo abInfo in this.bundles.Values)
		{
			sb.Append($"{abInfo.Name}:{abInfo.RefCount}\n");
		}
		return sb.ToString();
	}
}
Unity 资源管理器是一种在Unity开发环境中使用的工具,它可以帮助开发者轻松地浏览、搜索和下载Unity的各种资源。这些资源包括项目模板、插件、脚本、材质、模型等等。以下是关于Unity资源管理器下载的一些信息。 要使用Unity资源管理器下载资源,首先需要在Unity中打开Asset Store窗口。在Asset Store中,可以找到各种各样的资源供开发者下载和使用。开发者可以通过关键字搜索来浏览资源,也可以按照分类浏览资源,例如游戏对象、材质、效果等等。当找到想要的资源后,只需点击下载按钮即可将资源添加到Unity的项目中。 Unity资源管理器的下载速度通常取决于网络连接的速度和资源的大小。资源下载完成后,可以在Unity的项目中使用它们。通过资源管理器,开发者可以方便地查看和管理已下载的资源,可以进行重命名、移动、删除等操作。 此外,Unity资源管理器也提供了一些高级功能,例如资源预览、评分和评论。开发者可以在资源页面中查看资源的预览图和详细信息,并查看其他用户对该资源的评分和评论。这些功能可以帮助开发者更好地了解资源的质量和适用性。 总的来说,Unity资源管理器是Unity开发环境中的一个强大的工具,可以帮助开发者更轻松地浏览、搜索和下载各种资源。它能够大大提高开发效率,使开发者能够更快地找到并使用适合自己项目的资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值