Unity游戏开发——新发教你做游戏(三):3种资源加载方式
文章目录
- 一、前言
- 二、Unity的目录结构规范
- 1、Resources(不是很推荐把资源放这个目录)
- 2、RawAssets(存放生资源)
- 3、GameRes(存放熟资源)
- 4、StreamingAssets(存放AssetBundle)
- 5、其他目录
- 5.1、Editor目录(存放编辑器的扩展脚本)
- 5.2、Scripts目录 (存放脚本)
- 5.3、Scenes目录 (存放场景)
- 5.4、Plugins目录(SDK依赖的库文件)
- 5.5、Shaders目录(存放shader脚本)
- 三、3种资源加载方式
- 1、编辑器环境下加载GameRes目录中的资源
- 2、加载Resources目录中的资源
- 3、移动平台加载StreamingAssets目录中的资源
- 3.1、设置资源的AssetBundle名
- 3.2、AssetBundle打包
- 3.3、AssetBundle加载
- 四、资源热更
一、前言
文章列表
Unity游戏开发——新发教你做游戏(一):打开游戏开发新世界的大门
Unity游戏开发——新发教你做游戏(二):60个Unity免费资源获取网站
Unity游戏开发——新发教你做游戏(三):3种资源加载方式
Unity游戏开发——新发教你做游戏(四):角色移动控制
Unity游戏开发——新发教你做游戏(五):导航系统Navigation
Unity游戏开发——新发教你做游戏(六):教你2个步骤实现摇杆功能
Unity游戏开发——新发教你做游戏(七):Animator控制角色动画播放
本工程Demo
我已上传到GitHub
,感兴趣的同学可以下载下来学习。
GitHub
工程地址:https://github.com/linxinfa/Unity-RpgGameDemo
嗨,大家好,我是新发,上一篇文章我们讲了资源的获取,我们有了美术资源之后,导入Unity
中,就需要通过程序来加载和管理资源,本文我将介绍资源加载的三种方式。
二、Unity的目录结构规范
第一个问题,我们的资源放在什么目录中?那么,就需要先知道Unity
的目录结构。
Assets
为主目录,其他所有文件都在Assets
目录下,如下,这是我的目录结构,也建议大家在创建工程时就养成规范目录的习惯,不然项目后期必定返工整理目录和文件规范。
以上,和游戏资源相关的目录是四个:Resources
、RawAssets
、GameRes
、StreamingAssets
。
关于
Unity
的目录文件操作,我之前写过一篇文章:https://blog.csdn.net/linxinfa/article/details/51679528
为了方便理清关系,我画了下面这个图。
1、Resources(不是很推荐把资源放这个目录)
只读文件;资源全部被无条件被打进包内;这个文件夹下的资源将被加密和压缩打包;通过Resoureces.Load
方式加载。
做Demo
演示,可以直接把资源放这个目录,如果是实战项目,建议将资源打成AssetBundle
放在StreamingAssets
目录或服务器中,方便热更资源。
2、RawAssets(存放生资源)
RawAssets
不是Unity
默认的文件夹,所以文件夹名字没有严格要求一定要叫RawAssets
。
什么是生资源呢?生就是未加工的意思,大家应该听过生肉、熟肉,嘿嘿。
生资源,比如一个角色模型,我们一般是包装成预设,一个成品预设。这个预设依赖了网格、动画、材质球和贴图等资源,这些被成品依赖的零件
就是生资源。
RawAssets
中的生资源,被依赖性得打进包内,比如,成品预设放在Resources
目录中,那么成品依赖的对应的生资源就会被打进包内了,当然,如果没有被任何成品预设依赖,那么对应的生资源就不会被打进包内了。
3、GameRes(存放熟资源)
相对应与生资源,我们加工好的成品资源就是熟资源。在Editor
环境下,直接通过AssetDatabase.LoadAssetAtPah
同步加载资源。发布的时候,我们将GameRes
中的资源打成AssetBundle
放到StreamingAssets
目录中,当需要资源热更的时候,我们将新打的AssetBundle
放到远程服务器上,客户端下载到本地的Application.persistentDataPath
沙箱目录,再通过AssetBundle.LoadFromFile
同步加载。
加载资源的时候,优先去Application.persistentDataPath
中找,如果没有才去StreamingAssets
中找。
4、StreamingAssets(存放AssetBundle)
StreamingAssets
文件夹是一个只读的文件夹,但是它和Resources
有点区别,Resources
文件夹下的资源会进行一次压缩,而且也会加密,不使用点特殊办法是拿不到原始资源的。但是StreamingAssets
文件夹就下面的所有资源不会被加密,是原封不动的打包到发布包中,这样很容易就拿到里面的文件。我们打AssetBundle
的时候建议自己做一次加密。
我们可以通过WWW
或UnityWebRequest
异步加载资源,也可以通过AssetBundle.LoadFromFile
同步加载资源。
5、其他目录
5.1、Editor目录(存放编辑器的扩展脚本)
所有资源文件或者脚本文件都不会被打进发布包中,并且脚本也只能在编辑时使用。
工具类的脚本放在这里,或者是一些编辑时用的DLL
。
5.2、Scripts目录 (存放脚本)
我们的c#
游戏脚本放在这个目录中,注意,如果是编辑器工具类的c#
脚本,则放在Editor
目录中。
5.3、Scenes目录 (存放场景)
我们的场景文件放在这个目录中,包括场景的Lighting
灯光烘焙数据、Navigation
导航数据等。
5.4、Plugins目录(SDK依赖的库文件)
项目中很可能需要接一些第三方SDK
,比如微信开放平台的SDK
,对应的SDK
库文件就是放这个目录中(子目录Plugins/Android
和Plugins/iOS
)。还有你可能会用到一些第三方库,比如HoTween.dll
、Zxing.dll
、Ionic.Zip.Unity.dll
等,都是放在Plugins
中。
5.5、Shaders目录(存放shader脚本)
shader
一般是技术美术来写。Unity2018
推出了ShaderGraph
,我之前写了一篇关于ShaderGraph
的实战文章,大家有兴趣可以看看:https://blog.csdn.net/linxinfa/article/details/108049048
三、3种资源加载方式
1、编辑器环境下加载GameRes目录中的资源
在编辑器环境下,直接使用这种方式加载资源。
比如加载Assets/GameRes/Cube.prefab
。
注意,这种方式只能在编辑器环境下使用。
//using UnityEditor;
#if UNITY_EDITOR
string resPath = "Assets/GameRes/Cube.prefab";
//加载预设
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(resPath);
//实例化预设
GameObject go = Instantiate<GameObject>(prefab);
#endif
2、加载Resources目录中的资源
Resources
目录中的资源,通过Resources.Load
同步加载。
比如加载Assets/Resources/Cube.prefab
。
//加载预设,注意不用带.prefab后缀
GameObject prefab = Resources.Load<GameObject>("Cube");
//实例化预设
GameObject go = Instantiate<GameObject>(prefab);
3、移动平台加载StreamingAssets目录中的资源
一般我们是将GameRes
目录中的资源打成AssetBundle
放在StreamingAssets
目录中,然后通过WWW
或UnityWebRequest
异步加载,或者通过AssetBundle.LoadFromFile
同步加载。
3.1、设置资源的AssetBundle名
首先,对资源设置AssetBunle
名称,建议以所在目录为名称,比如下图中的Cube
和Sphere
两个预设,都设置成3dprefabs
。
如果资源比较多,建议写个Editor
工具执行自动化设置。
using UnityEngine;
using UnityEditor;
using System.IO;public class BuildTools
{[MenuItem("Tools/SetABName")]public static void SetABName(){//移除没有用的assetbundlenameAssetDatabase.RemoveUnusedAssetBundleNames();
#if UNITY_STANDALONE_WINstring dataPath = Application.dataPath.Replace("/", "\\");string gameResPath = Path.Combine(dataPath, "GameRes\\");
#elsestring dataPath = Application.dataPath;string gameResPath = Path.Combine(dataPath, "GameRes/");
#endifstring[] files = Directory.GetFiles(gameResPath, "*.*", SearchOption.AllDirectories);foreach (string filePath in files){if (filePath.EndsWith(".meta")) continue;string fullPath = filePath;
#if UNITY_STANDALONE_WINfullPath = filePath.Replace("/", "\\");
#endifstring fileFullDirName = Path.GetDirectoryName(fullPath);string fileAssetDirName = fullPath.Replace(dataPath, "Assets");string abName = fileFullDirName.Replace(gameResPath, "");
#if UNITY_STANDALONE_WINif (abName.Contains("\\"))abName = abName.Substring(0, abName.IndexOf("\\"));
#elseif (abName.Contains("/"))abName = abName.Substring(0, abName.IndexOf("/"));
#endifAssetImporter importer = AssetImporter.GetAtPath(fileAssetDirName);importer.assetBundleName = abName;}Debug.Log("SetABName Done");}
}
3.2、AssetBundle打包
接着,通过BuildPipeline.BuildAssetBundles
进行AssetBundle
打包。
using UnityEngine;
using UnityEditor;
using System.IO;public class BuildTools
{[MenuItem("Tools/BuildAB")]public static void StartBuildAB(){// 第3个参数根据你的平台而定BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows);AssetDatabase.Refresh();}
}
打AssetBundle
成功,即可在StreamingAssets
目录中看到了
3.3、AssetBundle加载
接下来是游戏运行时加载AssetBundle
,比如我们想加载3dprefabs
这个AssetBundle
中的Cube
。
方法一:AssetBundle.LoadFromFile同步加载(推荐)
//加载AssetBundle
string abResPath = Path.Combine(Application.streamingAssetsPath, "3dprefabs");
AssetBundle ab = AssetBundle.LoadFromFile(abResPath);
//加载Asset
GameObject prefab = ab.LoadAsset<GameObject>("Cube");
//实例化
GameObject cube = Instantiate<GameObject>(prefab);
方法二:UnityWebRequest异步加载(支持服务器上在资源加载)
IEnumerator LoadAsset()
{//注意:本地目录需要加上"file://"string uri = "file://" + Application.streamingAssetsPath + "/3dprefabs";UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uri, 0);yield return request.SendWebRequest();if (request.isNetworkError){Debug.LogError(request.error);}//获取到ab包AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);//加载AssetGameObject prefab = ab.LoadAsset<GameObject>("Cube");//实例化GameObject go = Instantiate<GameObject>(prefab);
}
方法三:WWW异步加载(支持服务器上在资源加载,已过时)
IEnumerator LoadAsset()
{//注意:本地目录需要加上"file://"string uri = "file://" + Application.streamingAssetsPath + "/3dprefabs";WWW www = new WWW(uri);yield return www;//获取到ab包AssetBundle ab = www.assetBundle;//加载AssetGameObject prefab = ab.LoadAsset<GameObject>("Cube");//实例化GameObject go = Instantiate<GameObject>(prefab);
}
四、资源热更
项目上线后,很可能需要热更游戏资源,这个时候,就需要从服务器端下载AssetBundle
到本地目录:Application.persistentDataPath
。
关于如何下载文件,参见我之前这篇文章:
https://blog.csdn.net/linxinfa/article/details/94436027
加载资源的时候,优先去Application.persistentDataPath
找看看有没有对应的资源,如果有,已Application.persistentDataPath
中的资源为准,否则,再去Application.streamingAssets
目录中找资源。
//你的资源文件
string resName = System.IO.Path.Combine(Application.persistentDataPath, "你的资源文件名");
if(System.IO.File.Exists(resName))
{//在Application.persistentDataPath目录中加载资源
}
else
{//在Application.streamingAssets目录中加载资源
}
也有一些人是在游戏首次启动时将Application.streamingAssets
目录中的所有AssetBundle
拷贝到Application.persistentDataPath
目录中,后面如果有资源热更,就会覆盖Application.persistentDataPath
目录中的资源,加载资源统一在Application.persistentDataPath
中找。
Unity游戏开发——新发教你做游戏(三):3种资源加载方式相关推荐
- (完结)Unity游戏开发——新发教你做游戏(七):Animator控制角色动画播放
文章目录 一.前言 二.Animator状态机组织 三.过渡条件 四.用代码设置过渡条件,触发动画播放 五.CharacterAniLogic.cs完整代码 一.前言 文章列表 Unity游戏开发-- ...
- Unity游戏开发——新发教你做游戏(一):打开游戏开发新世界的大门
文章目录 一.前言 二.制作思路 三.提出问题 四.具体实现 一.前言 嗨,大家好,我是新发,如下,我做了个简单的Demo,接下来我会详细介绍如何一步步制作,Demo工程我已上传到GitHub,感兴趣 ...
- Unity中的三种资源加载和卸载
前言 内容转载自: https://www.cnblogs.com/zhoujiangyue/articles/7066070.html. Unity中三种资源加载方式: 1.静态引用.具体操作:创建 ...
- Unity资源加载方式
一.Unity特殊资源目录 Resources:逻辑资源目录,这个目录中的资源会打入到包中,不允许热更.在打包时会被压缩和加密. 加载方式:Resources.Load(常用) . AssetData ...
- Unity资源加载入门
写在前面 本文转载自:https://gameinstitute.qq.com/community/detail/123460,供自己学习用,如有疑问,请移步原创. 引言 Unity的资源加载及管理, ...
- Unity资源加载管理
转载链接: https://bbs.gameres.com/thread_800362_1_1.html 我理解的资源管理 举一个不恰当的例子来描述我所理解的资源管理(因为我实在想不出更合适的例子了) ...
- 【游戏开发进阶】教你Unity通过Jenkins实现自动化打包,打包这种事情就交给策划了(保姆级教程 | 命令行打包 | 自动构建)
文章目录 一.前言 二.Jenkins简介 三.Jenkins的下载与安装 1.JDK下载与安装 2.Jenkins下载 3.Jenkins安装 4.Jenkins初始化 四.Jenkins的基本操作 ...
- 一个玩游戏的失足青年,转行做游戏开发到教育的挣扎过程(3)
有一个人小时候就有当飞行员的愿望,终于有一天他当上了飞行员.但是他第一次飞行,飞机就出事了. 好在他能够跳伞,但是降落伞坏了,打不开,突然他看见了在正下方的地上有一个很高的干草垛,但是再往下掉他又发现 ...
- 【老脸教你做游戏】小鸟飞过障碍物的游戏(下)
上期我们只实现了小鸟飞行以及障碍物地图随机生成.绘制和滚动,这期我们要完成整个游戏的大体框架,即游戏运行的主体部分,而其他的比如计分,重新开始等不会去实现.文章最后会讲一些个人心得. 本期内容依旧是在 ...
最新文章
- layui关闭表格编辑_Layui表格table关闭拖拽列宽、禁用拖拽列宽
- 生产者发送消息的过程?
- CentOS学习笔记--目录配置
- 自定义控件学习,优秀网站推荐
- WireShark抓DNS请求和回复数据报的分析
- Educational Codeforces Round 80 (Rated for Div. 2) 二分 + 状压
- java list遍历添加元素_java遍历List过程中添加和删除元素的问题
- 【算法导论】第7章快速排序
- layer弹出层扩展自定义样式
- 青少年迷恋上短视频 如何防沉迷?
- ThinkPHP V5.0 正式版发布
- 2018-2019-2 20165313 《网络对抗技术》 Exp6 信息搜集与漏洞扫描
- 量子纠缠2——CHSH不等式
- python导入dat数据_收好Python代码,导入项目数据不费力
- ubuntu 20.04安装输入法,微信,QQ,亲测使用很方便。
- SAP PO Delivery Address的决定因素
- 科学论文的写作内容与要求
- ai将会怎样影响计算机的发展,AI再升级!人工智能会对我们的未来产生怎样的影响?...
- 狄利克雷条件和帕塞瓦尔定理
- [Android Studio]开发APP应用出现软件程序打开闪退的排错
热门文章
- iOS 6与iOS 7的增量更新的区别
- 用户 不在 sudoers 文件中。此事将被报告
- 《从零开始的记账本开发》第2篇 概要设计
- swustoj木材加工(0436)
- “泰迪杯” 挑战赛 - 基于市场资金流向分析的商品期货量化交易策略(附suibian代码)
- MS90C386B:1Port LVDS转LVTTL
- 二进制里的「逢二进一」是什么意思
- 2020年3月笔记本选购记录
- 查询linux系统中文件名颜色分别代表什么
- 单位弹性需求曲线形状_需求曲线为直线时,在单位弹性点上总收益为最大。 - 问答库...