文章目录

  • 一、前言
  • 二、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目录下,如下,这是我的目录结构,也建议大家在创建工程时就养成规范目录的习惯,不然项目后期必定返工整理目录和文件规范。

以上,和游戏资源相关的目录是四个:ResourcesRawAssetsGameResStreamingAssets

关于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的时候建议自己做一次加密。
我们可以通过WWWUnityWebRequest异步加载资源,也可以通过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/AndroidPlugins/iOS)。还有你可能会用到一些第三方库,比如HoTween.dllZxing.dllIonic.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目录中,然后通过WWWUnityWebRequest异步加载,或者通过AssetBundle.LoadFromFile同步加载。

3.1、设置资源的AssetBundle名

首先,对资源设置AssetBunle名称,建议以所在目录为名称,比如下图中的CubeSphere两个预设,都设置成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种资源加载方式相关推荐

  1. (完结)Unity游戏开发——新发教你做游戏(七):Animator控制角色动画播放

    文章目录 一.前言 二.Animator状态机组织 三.过渡条件 四.用代码设置过渡条件,触发动画播放 五.CharacterAniLogic.cs完整代码 一.前言 文章列表 Unity游戏开发-- ...

  2. Unity游戏开发——新发教你做游戏(一):打开游戏开发新世界的大门

    文章目录 一.前言 二.制作思路 三.提出问题 四.具体实现 一.前言 嗨,大家好,我是新发,如下,我做了个简单的Demo,接下来我会详细介绍如何一步步制作,Demo工程我已上传到GitHub,感兴趣 ...

  3. Unity中的三种资源加载和卸载

    前言 内容转载自: https://www.cnblogs.com/zhoujiangyue/articles/7066070.html. Unity中三种资源加载方式: 1.静态引用.具体操作:创建 ...

  4. Unity资源加载方式

    一.Unity特殊资源目录 Resources:逻辑资源目录,这个目录中的资源会打入到包中,不允许热更.在打包时会被压缩和加密. 加载方式:Resources.Load(常用) . AssetData ...

  5. Unity资源加载入门

    写在前面 本文转载自:https://gameinstitute.qq.com/community/detail/123460,供自己学习用,如有疑问,请移步原创. 引言 Unity的资源加载及管理, ...

  6. Unity资源加载管理

    转载链接: https://bbs.gameres.com/thread_800362_1_1.html 我理解的资源管理 举一个不恰当的例子来描述我所理解的资源管理(因为我实在想不出更合适的例子了) ...

  7. 【游戏开发进阶】教你Unity通过Jenkins实现自动化打包,打包这种事情就交给策划了(保姆级教程 | 命令行打包 | 自动构建)

    文章目录 一.前言 二.Jenkins简介 三.Jenkins的下载与安装 1.JDK下载与安装 2.Jenkins下载 3.Jenkins安装 4.Jenkins初始化 四.Jenkins的基本操作 ...

  8. 一个玩游戏的失足青年,转行做游戏开发到教育的挣扎过程(3)

    有一个人小时候就有当飞行员的愿望,终于有一天他当上了飞行员.但是他第一次飞行,飞机就出事了. 好在他能够跳伞,但是降落伞坏了,打不开,突然他看见了在正下方的地上有一个很高的干草垛,但是再往下掉他又发现 ...

  9. 【老脸教你做游戏】小鸟飞过障碍物的游戏(下)

    上期我们只实现了小鸟飞行以及障碍物地图随机生成.绘制和滚动,这期我们要完成整个游戏的大体框架,即游戏运行的主体部分,而其他的比如计分,重新开始等不会去实现.文章最后会讲一些个人心得. 本期内容依旧是在 ...

最新文章

  1. layui关闭表格编辑_Layui表格table关闭拖拽列宽、禁用拖拽列宽
  2. 生产者发送消息的过程?
  3. CentOS学习笔记--目录配置
  4. 自定义控件学习,优秀网站推荐
  5. WireShark抓DNS请求和回复数据报的分析
  6. Educational Codeforces Round 80 (Rated for Div. 2) 二分 + 状压
  7. java list遍历添加元素_java遍历List过程中添加和删除元素的问题
  8. 【算法导论】第7章快速排序
  9. layer弹出层扩展自定义样式
  10. 青少年迷恋上短视频 如何防沉迷?
  11. ThinkPHP V5.0 正式版发布
  12. 2018-2019-2 20165313 《网络对抗技术》 Exp6 信息搜集与漏洞扫描
  13. 量子纠缠2——CHSH不等式
  14. python导入dat数据_收好Python代码,导入项目数据不费力
  15. ubuntu 20.04安装输入法,微信,QQ,亲测使用很方便。
  16. SAP PO Delivery Address的决定因素
  17. 科学论文的写作内容与要求
  18. ai将会怎样影响计算机的发展,AI再升级!人工智能会对我们的未来产生怎样的影响?...
  19. 狄利克雷条件和帕塞瓦尔定理
  20. [Android Studio]开发APP应用出现软件程序打开闪退的排错

热门文章

  1. iOS 6与iOS 7的增量更新的区别
  2. 用户 不在 sudoers 文件中。此事将被报告
  3. 《从零开始的记账本开发》第2篇 概要设计
  4. swustoj木材加工(0436)
  5. “泰迪杯” 挑战赛 - 基于市场资金流向分析的商品期货量化交易策略(附suibian代码)
  6. MS90C386B:1Port LVDS转LVTTL
  7. 二进制里的「逢二进一」是什么意思
  8. 2020年3月笔记本选购记录
  9. 查询linux系统中文件名颜色分别代表什么
  10. 单位弹性需求曲线形状_需求曲线为直线时,在单位弹性点上总收益为最大。 - 问答库...