最近做了一个小项目,遇到了一个问题,感觉比较经典,就想写下来,希望对其他人有所帮助
问题的报错就是这个.....
I/Unity ( 8298): NullReferenceException: Object reference not set to an instan
ce of an object
I/Unity ( 8298): at Heathwork.Update () [0x00000] in <filename unknown>:0
Heathwork是一个挂载在gameobject上的脚本组件,在unity上测试一直都是好的,但是在手机上就是不行
一直报这个错,经过很多查询才知道,原来是我在untiy上使用了一个配置文件放在/assets/data下面,unity打包的时候
没有打进去,所以手机上是读不到这个文件的,我在Heathwork之中的start之中使用了这个文件,于是Heathwork没有实例化成功,
所以在update的时候才会报未将对象引用到对象的实例。于是我又去查了一下unity的打包机制,在此总结一下
1.unity(5.x)的资源打包过程
1.1 唯一的API
调用builgpipeline.BuildAssetBundles,引擎将自动根据资源的assetbundleName
属性批量打包,自动建立bundle以及资源之间的依赖关系
1.2 打包规则
在资源的inpector界面最下方可设置一个abName,每个abName(包含路劲)对应一个
bundle,即abName相同的资源会打在一个Bundle中,如果所以来的资源设置了不同的abName
则会与之建立依赖关系,避免出现冗余,
支持增量式发布,即在资源内容改变并重新打包时,会自动跳过内容未变的bundle。
1.3 新打包的选项
5.x 下默认开启三个选项(completeAssets,用于保证资源单的完备性,collectDependencies
,用于收集资源的依赖项,DeterministicAssetBundle,用于为资源维护固定id)之外
ForceRebuildAssetBundle
用于强制重打所有AssetBundle文件;
IgnoreTypeTreeChanges
用于判断AssetBundle更新时,是否忽略TypeTree的变化;
AppendHashToAssetBundleName
用于将Hash值添加在AssetBundle文件名之后,开启这个选项,可以直接通过文件名来判断哪些Bundle的内容进行了更新
(4.x下普遍需要通过比较二进制等方法来判断,但在某些情况下即使内容不变重新打包,Bundle的二进制也会变化)。
1.4 Manifest文件
在打包后生成的文件夹中,每个Bundle都会对应一个manifest文件,记录了Bundle的一些信息,
但这类manifest只在增量式打包时才用到;同时,根目录下还会生成一个同名manifest文件及其对应的Bundle文件,
通过该Bundle可以在运行时得到一个AssetbundleManifest对象,而所有的Bundle以及各自依赖的Bundle都可以通过该对象提供的接口进行获取。
1.5 Variant参数
在资源的Inspector界面最下方,除了可以指定abName,在其后方还可以指定Variant。打包时,Variant会作为
后缀添加在Bundle名字之后。相同abName,不同variant的Bundle中,资源必须是一一对应的,且他们在Bundle中的ID也是相同的,
从而可以起到相互替换的作用。
https://blog.uwa4d.com/archives/ABtopic_2.html
2.unity项目下的文件结构
2.1 GUID与fileID(本地ID)
Unity会为每个导入到Assets目录中的资源创建一个meta文件,文件中记录了GUID,GUID用来记录资源之间的引用关系。
还有fileID(本地ID),用于标识资源内部的资源。资源间的依赖关系通过GUID来确定;资源内部的依赖关系使用fileID来确定。
2.2 MonoScripts
一个MonoScripts含有三个字符串:程序库名称,类名称,命名空间。
构建工程时,Unity会收集Assets文件夹中独立的脚本文件并编译他们,组成一个Mono程序库。Unity会将Assets目录中的语言分开编译,Assets/Plugins目录中的脚本同理。Plugin子目录之外的C#脚本会放在Assembly-CSharp.dll中。而Plugin及其子目录中的脚本则放置在Assembly-CSharp-firstpass.all中。
这些程序库会被MonoScripts所引用,并在程序第一次启动时被加载。
2.3 Assets
为unity编辑器下的资源文件夹,unity编辑时的所有资源都将置于此文件夹内,
可以使用AssetDatabase.LoadAssetAtPath("Assets/x.txt"); 来获取资源对象
ps:只能在编辑器下使用,当项目打包后,游戏内无法运作,参数为包含Assets的文件全路径
并且需要文件后缀
Assets下的资源除特殊文件夹内 或者会被打入保内的场景引用的资源化,其余资源不会被打入包中,
2.4 Resources
资源载入
Assets下的特殊文件夹,此文件夹内的资源将会在项目打包时,全部打入包内,并能通过以下方法获得对象:
Resources.Load("fileName");
注意:函数内的参数为相对于Resource目录下的文件路径与名称,不包含后缀。Assets目录下可以拥有任意路径及数量的Resources文件夹,在运行时,Resources下的文件路径将被合并。
例:Assets/Resources/test.txt与 Assets/TestFloder/Resources/test.png在使用Resource.Load("test")载入时,将被视为同一资源,只会返回第一个符合名称的对象。如果使用Resource.Load(“test”)将返回text.txt;
如果在Resources下有相同路径及名称的资源,使用以上方法只能获得第一个符合查找条件的对象,使用以下方法能或得到所有符合条件的对象:
Object[] assets = Resources.LoadAll("fileName");
TextAsset[] assets = Resources.LoadAll("fileName");
在工程进行打包后,Resource文件夹中的资源将进行加密与压缩,打包后的程序内将不存在Resource文件夹,故无法通过路径访问以及更新资源
意思就是打包无法进行更改了
2.5 StreamingAssets
概述
StreamingAssets文件夹为流媒体文件夹,此文件夹内的资源将不会经过压缩与加密,原封不动的打包进游戏包内。在游戏安装时,StreamAssets文件件内的资源将根据平台,移动到对应的文件夹内。StreamingAssets文件夹在Android与IOS平台上为只读文件夹.
你可以使用以下函数获得不同平台下的StreamingAssets文件夹路径:
Application.streamingAssetsPath
请参考以下各平台下StreamingAssets文件夹的等价路径,Application.dataPath为程序安装路径。Android平台下的路径比较特殊,请留意此路径的前缀,在一些资源读取的方法中是不必要的(AssetBundle.LoadFromFile,下详)
Application.dataPath+"/StreamingAssets"//Windows OR MacOS
Application.dataPath+"/Raw" //IOS
"jar:file://"+Application.dataPath+"!/assets/" //Android
在pc跟mac中可以有读写权限,但是移动端只支持读取操作
ps:也可以在Assets下直接创建其他文件夹 也会被打进项目中,使用application.datapath来访问,但是
在移动端是没有访问权限的!!!!
2.6 AssetBundle
概述
AssetBundles let you stream additional assets via the WWW class and instantiate them at runtime. AssetBundles are created via BuildPipeline.BuildAssetBundle.
AssetBundle是Unity支持的一种文件储存格式,也是Unity官方推荐的资源存储与更新方式,它可以对资源(Asset)进行压缩,分组打包,动态加载,以及实现热更新,
但是AssetBundle无法对Unity脚本进行热更新,因为其需要在打包时进行编译。
它的位置就在 你随便点击一个perfab 在inspector中 最下面的那个就是assetBundle
总结几点:
1.Resources 打包会被进入,但是会被加密,不能进行更改,可存放一些固定配置的文件,通过
Resources.Load("fileName"); 或者使用textAsset拖入脚本中使用
2.直接在Assets中放入文件
使用application.dataPath+"fileName" 来读取 但是这个在移动端是没有访问权限的
3.StreamingAssets
在项目中创建这个文件夹之后,
可以使用Application.streamingAssetsPath 来读取文件 也可以使用Application.dataPath来读取
Application.dataPath使用的话必须分清楚平台路径
#if UNITY_ANDROID //安卓
string filepath= "jar:file://" + Application.dataPath + "!/assets/"+"Filename";
#elif UNITY_IPHONE //iPhone
string filepath=Application.dataPath + "/Raw/"+"Filename";
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR //windows平台和web平台
string filepath = "file://" + Application.dataPath + "/StreamingAssets/"+"Filename";
#end
实验做出来的是只能www去读 IO无法读取内容 在手机上
4.使用Application.persistentDataPath 来操作文件(推荐)
此文件存在手机沙盒中,项目中是找不到的,
在移动端使用服务器下载文件后 保存在这个文件 使用md5对比下载更新新资源
如果没有服务器 可以通过文件流的形式在本地读取然后写入Application.persistentDataPath中,
再通过Application.persistentDataPath 来读取操作文件
ps:在移动端可以进行任意文件操作,同时IOS会被icloud备份
5.Application.temporaryCachePath
操作方式跟Application.persistentDataPath一样 但是不能被icloud备份
以上都是理论部分......废话不多说 来点干货
void Start () {
text = (TextAsset)Resources.Load ("test2");
testtxt = text.text;
this.gameObject.GetComponent<Text> ().text = testtxt;
}
testtxt = text.text;
this.gameObject.GetComponent<Text> ().text = testtxt;
public TextAsset text;
public string testtxt;
// Use this for initialization
void Start () {
//string path = Application.streamingAssetsPath+"/test3.txt";
//或者使用下面的filepath 也是可以的
#if UNITY_ANDROID //安卓
string filepath= "jar:file://" + Application.dataPath + "!/assets/"+"/test3.txt";
#elif UNITY_IPHONE //iPhone
string filepath=Application.dataPath + "/Raw/"+"/test3.txt";
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR //windows平台和web平台
string filepath = "file://" + Application.dataPath + "/StreamingAssets/"+"/test3.txt";
#endif
testtxt = Loadfile(filepath);
this.gameObject.GetComponent<Text> ().text = testtxt+" "+filepath;
}
// Update is called once per frame
void Update () {
}
public string Loadfile(string path){
StreamReader sr = null;
try{
sr = File.OpenText(path);
}catch(Exception e){
return null;
}
string line;
//字符分割就不做了 可以用sr.ReadLine();
line = sr.ReadToEnd ();
sr.Close ();
sr.Dispose ();
return line;
}
public TextAsset text;
public string testtxt;
// Use this for initialization
void Start () {
#if UNITY_ANDROID //安卓
string path = Application.streamingAssetsPath+"/test4.txt";
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR //windows平台和web平台
string path ="file://"+ Application.streamingAssetsPath+"/test4.txt";
#endif
StartCoroutine (readwww (path));
}
// Update is called once per frame
void Update () {
}
IEnumerator readwww(string path){
//Debug.Log (path);
WWW www = new WWW (path);
yield return www;
testtxt = www.text;
//Debug.Log ("!!!"+testtxt);
this.gameObject.GetComponent<Text> ().text = testtxt+path;
}
public string Loadfile(string path){
StreamReader sr = null;
try{
sr = File.OpenText(path);
}catch(Exception e){
return null;
}
string line;
//字符分割就不做了 可以用sr.ReadLine();
line = sr.ReadToEnd ();
sr.Close ();
sr.Dispose ();
return line;
}
public TextAsset text;
public string testtxt;
// Use this for initialization
void Start () {
string txt = "测试手机沙盒的读与写";
string path = Application.persistentDataPath+"/test5.txt";
write (path, txt);
testtxt = Loadfile (path);
this.gameObject.GetComponent<Text> ().text = testtxt+path;
}
// Update is called once per frame
void Update () {
}
public void write(string path,string text){
StreamWriter sr = null;
FileInfo file = new FileInfo (path);
if (!file.Exists) {
sr = file.CreateText ();
}else{
sr = file.AppendText ();
}
sr.Write (text);
sr.Close ();
sr.Dispose ();
}
public string Loadfile(string path){
StreamReader sr = null;
try{
sr = File.OpenText(path);
}catch(Exception e){
return null;
}
string line;
//字符分割就不做了 可以用sr.ReadLine();
line = sr.ReadToEnd ();
sr.Close ();
sr.Dispose ();
return line;
}
这里分别是五个模式下的核心代码运行之后的效果如图
第二张图则是在手机上运行结果
我把工程项目文件也传上来了,有兴趣可以下载看看
- 大小: 83.2 KB
- 大小: 54 KB
分享到:
相关推荐
在Unity引擎中,读写文本文件是常见的数据处理任务,特别是在保存游戏进度、配置设置或者简单日志记录等场景。本篇文章将详细讲解如何在Unity中利用C#语言的静态方法进行TXT文件的读写操作。 首先,Unity的C#脚本...
在Unity游戏开发中,配置文件通常用于存储游戏的设置、玩家数据或关卡信息等,而.ini文件是一种常见的文本配置文件格式,易于读写且结构清晰。本篇将详细介绍如何在Unity中直接使用内置功能来读写.ini配置文件,无需...
在Unity游戏开发中,JSON(JavaScript Object Notation)文件常被用来存储数据,如游戏配置、用户设置等,因为它们格式简洁且易于读写。在Unity中,虽然没有内置的JSON解析器,但通过C#的System.Text.Json库或者...
在Unity中,保存和加载文件是常见的需求,比如存储玩家进度、设置或游戏数据。"Unity存文件到PC示例工程"是一个教程项目,旨在教给开发者如何在不依赖外部插件的情况下,通过调用系统文件对话框让玩家将项目数据保存...
在 Unity 中,我们可以使用文件流来保存和读取资源,但是在 IOS 平台下,我们需要使用特殊的方法来保存和读取资源。这篇文章将详细介绍如何在 Unity 中在 IOS 平台下保存和读取资源,并将资源保存到文件夹目录中。 ...
总的来说,这个Demo是一个很好的学习实例,展示了如何在Unity3D中处理Android平台的文件读写操作,这对于创建需要存储用户数据或下载内容的游戏和应用至关重要。在实际开发中,你需要考虑到不同Android版本的兼容性...
标题“unity读写.Excel文件”表明我们将讨论如何在Unity中直接读取和写入Excel文件,而无需额外的插件或复杂的脚本。描述中提到使用静态方法执行,这可能指的是利用C#内置的功能或者特定库的静态类来简化操作流程。 ...
写入XML文件则需要创建一个`XmlElement`对象,添加子节点,然后保存到文件: ```csharp XmlElement root = xmlDoc.CreateElement("root"); xmlDoc.AppendChild(root); XmlElement element = xmlDoc.CreateElement(...
UnityExcel读写是一种在Unity引擎中处理Excel文件的解决方案,主要依赖于EPPlus库的优化。EPPlus是一款强大的.NET框架下的开源库,专门用于处理Excel 2007及以后版本的Open XML格式文件。在Unity中,由于其内置的C#...
在Unity游戏开发中,有时我们需要处理数据,例如存储玩家进度、游戏设置或排行榜等,这时Excel文件因其易读写和管理的特点,成为了理想的选择。本文将深入探讨如何在Unity环境中,利用C#语言实现跨平台(Windows和...
总之,"unity读取excel配置文件插件"是Unity开发者的重要工具,它简化了游戏配置数据的管理,让策划人员能够更轻松地修改Excel表格,同时保持代码与数据的分离。通过熟练掌握这种插件的使用,你可以提高开发效率,使...
在Unity游戏开发中,数据存储是一项至关重要的任务,它涉及到游戏进度、用户设置、成就、排行榜等信息的保存。这个“Unity数据存储项目源码”是DT教程第六章的内容,旨在帮助开发者掌握如何在Unity中有效地管理和...
在Unity3D游戏开发中,XML(eXtensible Markup Language)文件常被用来存储非游戏逻辑相关的配置信息,如角色属性、关卡设置、道具数据等。由于XML格式易于理解和解析,它成为开发者们首选的数据存储方式。本文将...
为了在Unity中读写Excel文件,我们需要引入一些外部库,这些库提供了与Excel文件交互的功能。在你提供的信息中提到了四个关键的dll文件,它们分别是: 1. **Excel.dll**:这可能是一个专门用于处理Excel文件的第三...
在Unity3D中,XML文件可以用来保存游戏配置、用户数据或其他需要持久化的信息,而无需依赖数据库。 在Unity3D中读取和保存XML文件通常涉及以下步骤: 1. 定义数据结构:首先,你需要创建一个类来表示你想要存储的...
在Unity3D游戏开发中,有时我们需要将数据存储在文本文件中,以便在游戏中读取或保存用户进度、配置等信息。本文将详细讲解如何在Unity3D中进行文本文件的读写操作,这对于游戏的数据管理至关重要。 首先,了解...
这个压缩包“Unity的EPPlus,与Excel读写.zip”包含了使用EPPlus在Unity环境中读取和写入Excel文件的相关资源,主要就是EPPlus.dll文件,这是一个动态链接库,提供了对Excel数据操作的接口。 EPPlus库的优点在于它...
在Unity游戏开发中,有时我们需要处理数据,例如存储玩家进度、配置信息或者游戏逻辑数据,这时Excel文件因其直观易用的特性成为理想的选择。本文将详细介绍如何在Unity中实现读写Excel文件,以及如何利用提供的dll...
在Unity中,这需要保存已下载文件的部分数据,如已下载的字节数、文件总大小等信息。 1. **保存状态**:在下载开始前,检查本地是否有已下载部分的文件。如果有,读取文件大小作为起始位置。 2. **设定范围请求**:...