Laya 是如何管理资源的?

Laya资源加载类,主要是Loader

所有资源:Loader.loadedMap

贴图资源:Loader.textureMap

c 复制代码
_loadResource(type, url) {
	switch (type) {
		case Loader.IMAGE:
		case "htmlimage":
		case "nativeimage":
			this._loadImage(url);
			break;
		case Loader.SOUND:
			this._loadSound(url);
			break;
		case Loader.TTF:
			this._loadTTF(url);
			break;
		case Loader.ATLAS:
		case Loader.PREFAB:
		case Loader.PLF:
			this._loadHttpRequestWhat(url, Loader.JSON);
			break;
		case Loader.FONT:
			this._loadHttpRequestWhat(url, Loader.XML);
			break;
		case Loader.PLFB:
			this._loadHttpRequestWhat(url, Loader.BUFFER);
			break;
		default:
			this._loadHttpRequestWhat(url, type);
	}
}
//加载完成
complete(data) {
	this._data = data;
	if (this._customParse) {
		this.event(Event.LOADED, data instanceof Array ? [data] : data);
	}
	else {
		Loader._loaders.push(this);
		if (!Loader._isWorking)
			Loader.checkNext();
	}
}
//逐批处理
static checkNext() {
	Loader._isWorking = true;
	var startTimer = Browser.now();
	while (Loader._startIndex < Loader._loaders.length) {
		Loader._loaders[Loader._startIndex].endLoad();
		Loader._startIndex++;
		//如果某一帧处理 超过100毫秒 则停止,下一帧再继续处理
		if (Browser.now() - startTimer > Loader.maxTimeOut) {
			console.warn("loader callback cost a long time:" + (Browser.now() - startTimer) + " url=" + Loader._loaders[Loader._startIndex - 1].url);
			ILaya.systemTimer.frameOnce(1, null, Loader.checkNext);
			return;
		}
	}
	Loader._loaders.length = 0;
	Loader._startIndex = 0;
	Loader._isWorking = false;
}
//分发事件
endLoad(content = null) {
	content && (this._data = content);
	if (this._cache)
		Loader.cacheRes(this._url, this._data);
	this.event(Event.PROGRESS, 1);
	this.event(Event.COMPLETE, this.data instanceof Array ? [this.data] : this.data);
}


//获得
static getRes(url) {
	var res = Loader.textureMap[URL.formatURL(url)];
	if (res)
		return res;
	else
		return Loader.loadedMap[URL.formatURL(url)];
}
static getAtlas(url) {
	return Loader.atlasMap[URL.formatURL(url)];
}
//缓存
static cacheRes(url, data) {
	url = URL.formatURL(url);
	if (Loader.loadedMap[url] != null) {
		console.warn("Resources already exist,is repeated loading:", url);
	}
	else {
		if (data instanceof Texture) {
			Loader.loadedMap[url] = data.bitmap;
			Loader.textureMap[url] = data;
		}
		else {
			Loader.loadedMap[url] = data;
		}
	}
}
//清除
static clearRes(url) {
	url = URL.formatURL(url);
	var arr = Loader.getAtlas(url);
	if (arr) {
		for (var i = 0, n = arr.length; i < n; i++) {
			var resUrl = arr[i];
			var tex = Loader.getRes(resUrl);
			delete Loader.textureMap[resUrl];
			if (tex)
				tex.destroy();
		}
		arr.length = 0;
		delete Loader.atlasMap[url];
	}
	var texture = Loader.textureMap[url];
	if (texture) {
		texture.destroy();
		delete Loader.textureMap[url];
	}
	var res = Loader.loadedMap[url];
	(res) && (delete Loader.loadedMap[url]);
}

资源存取类 Resource

针对Loader资源的一个处理

c 复制代码
class Resource extends EventDispatcher {
	//当前内存,以字节为单位。	 
	static get cpuMemory():number;
	
	//当前显存,以字节为单位。
	static get gpuMemory():number;
	
	//通过资源ID返回已载入资源。
	static getResourceByID(id:number):Resource;
	
	//通过url返回已载入资源。
	static getResourceByURL(url:string,index?:number):Resource;
	
	//销毁当前没有被使用的资源,该函数会忽略lock=true的资源。
	static destroyUnusedResources():void;

	//是否加锁,如果true为不能使用自动释放机制。
	lock:boolean;
	//获取资源的引用计数。
	get referenceCount():number;
	
	//是否已处理。
	get destroyed():boolean;
	//销毁资源,销毁后资源不能恢复。
	destroy():void;
}

Resource销毁

c 复制代码
static destroyUnusedResources() {
	for (var k in Resource._idResourcesMap) {
		var res = Resource._idResourcesMap[k];
		//条件是:锁定为false,引用数量为0
		if (!res.lock && res._referenceCount === 0){
			res.destroy();
		}
			
	}
}

destroy() {
	if (this._destroyed)
		return;
	this._destroyed = true;
	this.lock = false;
	//Resource子级实现
	this._disposeResource();
	//移除全局 source
	delete Resource._idResourcesMap[this.id];
	var resList;
	//_url不为空,表示有贴图,之所以用数组,是因为图集大的有可能超过一张贴图
	if (this._url) {
		resList = Resource._urlResourcesMap[this._url];
		if (resList) {
			resList.splice(resList.indexOf(this), 1);
			(resList.length === 0) && (delete Resource._urlResourcesMap[this._url]);
		}
		//顺便删除Loader 引用
		var resou = ILaya.Loader.loadedMap[this._url];
		(resou == this) && (delete ILaya.Loader.loadedMap[this._url]);
	}
}

Resource存放字典

c 复制代码
	//Key从1开始 value为Resource子类
	Resource._idResourcesMap = {};
	//Key为文件路径 value为Texture2D
	Resource._urlResourcesMap = {};

Resource子类

c 复制代码
1.位图
bitmap:  BaseTexture  HTMLCanvas  HTMLImage
BaseTexture:Texture2D  RenderTexture2D  VideoTexture


2.
BaseShader:Shader
Shader: Shader2X

3.文本
TextTexture
相关推荐
zyplayer-doc2 小时前
VuePress类静态文档站和动态知识库怎么选:两种技术路线的适用场景
javascript·人工智能·后端·安全·智能手机
紫禁玄科3 小时前
Shai-Hulud:npm生态的自我复制蠕虫风暴
前端·npm·node.js
东风破_4 小时前
后端API没写好,前端难道干等着吗?
前端
用户938515635074 小时前
从前后端分离到前端接口工程:React + MockJS + Vite 解析
前端·后端·全栈
用户938515635074 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformers.js 全链路实战(三)
前端·react.js·typescript
excel4 小时前
当前端行情变差,我们为什么还要坚持?
前端
鸿是江边鸟,曾是心上人5 小时前
快速搭建HTTPS本地开发环境
前端
To_OC5 小时前
写了 5 个表单 Demo 后,我终于彻底搞懂了 React 受控与非受控组件
前端·react.js·前端框架
Sterting6 小时前
第9课 Vue Router 路由
前端·vue.js
用户059540174466 小时前
LangChain Memory 测试踩坑实录:用 pytest 自动化回归对话记忆,我折腾了整整一个周末
前端·css