Unity游戏打包以后无法获取配置文件信息

描述:在Unity编辑器下是可以读取到配置文件的,但是Build以后,就报错:

经过查看帖子以后,才发现Unity读取文件这个地方还是有很多讲究的。我之前的文件路径是这样写的:

这个路径只对应在Editor模式下运行的目录结构,但是不对应打包之后的目录结构。所以会报错~!!!!

按理说,我把AllConfig.ini放在exe同一目录下就行了,但是我突然意识到我之前写的读取ini的代码只能运行在windows下(因为直接调用了WindowsAPI),所以我要写一个能在Windows平台下和Android 平台下都ok的方案。我决定改成比较常见的xml配置文件。同时对Unity不同平台下读取文件进行一定的了解。


下面来说一下Unity中文件操作路径的常见的方法以及它们的区别

Application.dataPath

Application.streamingAssetsPath

Application.persistentDataPath

Application.temporaryCachePath 

在个平台下的具体路径如下:

 

Application.dataPath

Application.streamingAssetsPath

Application.persistentDataPath

Application.temporaryCachePath

IOS

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches

Android

/data/app/xxx.xxx.xxx.apk

jar:file:///data/app/xxx.xxx.xxx.apk/!/assets

/data/data/xxx.xxx.xxx/files

/data/data/xxx.xxx.xxx/cache

Windows

/Assets

/Assets/StreamingAssets

C:/Users/xxxx/AppData/LocalLow/CompanyName/ProductName

C:/Users/xxxx/AppData/Local/Temp/CompanyName/ProductName

Mac

/Assets

/Assets/StreamingAssets

/Users/xxxx/Library/Caches/CompanyName/Product Name

/var/folders/57/6b4_9w8113x2fsmzx_yhrhvh0000gn/T/CompanyName/Product Name

Windows WebPlayer

file:///D:/MyGame/WebPlayer (即导包后保存的文件夹,html文件所在文件夹)

 

 

 

注意:

  • StreamingAssets文件夹(只读)
#if UNITY_EDITOR
string filepath = Application.dataPath +"/StreamingAssets"+"/my.xml";
#elif UNITY_IOS
 string filepath = Application.dataPath +"/Raw"+"/my.xml";
#elif UNITY_ANDROID
 string filepath = "jar:file://" + Application.dataPath + "!/assets/"+"/my.xml;
#endif
  • Resources文件夹(只读)

可以使用Resources.Load("名字"); 把文件夹中的对象加载出来

  • Application.dataPath文件夹(只读)

可以使用Application.dataPath进行读操作

Application.dataPath: 只可读不可写,放置一些资源数据

  • Application.persistentDataPath文件夹(读写)

IOS与android平台都可以使用这个目录下进行读写操作,可以存放各种配置文件进行修改之类的。

在PC上的地址是:C:\Users\用户名 \AppData\LocalLow\DefaultCompany\test


Resources

Resources文件夹是一个只读的文件夹,通过Resources.Load()来读取对象。因为这个文件夹下的所有资源都可以运行时来加载,所以Resources文件夹下的所有东西都会被无条件的打到发布包中。建议这个文件夹下只放Prefab或者一些Object对象,因为Prefab会自动过滤掉对象上不需要的资源。举个例子我把模型文件还有贴图文件都放在了Resources文件夹下,但是我有两张贴图是没有在模型上用的,那么此时这两张没用的贴图也会被打包到发布包中。假如这里我用Prefab,那么Prefab会自动过滤到这两张不被用的贴图,这样发布包就会小一些了。 

StreamingAssets

StreamingAssets文件夹是一个只读的文件夹,但是它和Resources有点区别,Resources文件夹下的资源会进行一次压缩,而且也会加密,不使用点特殊办法是拿不到原始资源的。但是StreamingAssets文件夹就下面的所有资源不会被加密,是原封不动的打包到发布包中,这样很容易就拿到里面的文件。所以StreamingAssets适合放一些二进制文件,而Resources更适合放一些GameObject和Object文件。 StreamingAssets 只能用过www类来读取!!
StreamingAssets在不同的平台上面 (Windows, iOS ,Android),该目录最终发布的位置不同,所以读取的方法也不同。所以如果你的项目只运行在Windows或者IOS下,那么你可以用IO方式读取,但是如果你的项目要运行在Android平台下,那就只能通过www类来读取。个人觉得,如果是这样,在写代码的时候,统一实现WWW方式好了。

 

Windows

IOS

Android

IO读取路径

Application.StreamingAssetPath+"/myfile.txt"

Application.StreamingAssetPath+"/myfile.txt"

不支持

WWW读取路径

"file://"+Application.StreamingAssetPath+"/myfile.txt"

"file://"+Application.StreamingAssetPath+"/myfile.txt"

Application.StreamingAssetPath+"/myfile.txt"

注意:WWW是异步加载所以执行加载命令式不能直接执行读取解析操作,要等待

WWW www = new WWW(filePath);

yield return www; // while (!www.isDone) {}

result = www.text;

Android之所以不支持C# IO流 方式读取StreamingAssets下的文件,是因为Android手机中,StreamingAssets下的文件都包含在压缩的.jar文件中(这基本上与标准的zip压缩文件的格式相同)。不能直接用读取文件的函数去读,而要用WWW方式。具体做法如下: 
1.把你要读取的文件放在Unity项目的Assets/StreamingAssets文件夹下面,没有这个文件夹的话自己建一个。 
2.读取的代码(假设名为"文件.txt") 

//用来存储读入的数据
byte[] bytes;       
//判断当前程序是否运行在安卓下                                                                                                   
if (Application.platform == RuntimePlatform.Android)                                            
{ 
    
    string fpath= "jar:file://" + Application.dataPath + "!/assets/" + "文件.txt"; 
    //等价于string fpath = Application.StreamingAssetPath+"/文件.txt"; 
    
    WWW www = new WWW(fpath);                                                                
    //WWW是异步读取,所以要用循环来等待 
    while(!www.isDone){}                                                                       
    //存到字节数组里 
    bytes= www.bytes;                                                                           
    
 
} 
else 
{ 
    //其他平台的读取代码 
}

 


总结:


一. 在项目根目录中创建Resources文件夹来保存文件。
可以使用Resources.Load("文件名字,注:不包括文件后缀名");把文件夹中的对象加载出来。
注:此方可实现对文件实施“增删查改”等操作,但打包后不可以更改了。

二. 直接放在项目根路径下来保存文件
在直接使用Application.dataPath来读取文件进行操作。
注:移动端是没有访问权限的。

三. 在项目根目录中创建StreamingAssets文件夹来保存文件。
1.可使用Application.dataPath来读取文件进行操作。

#if UNITY_EDITOR
string filepath = Application.dataPath +"/StreamingAssets"+"/my.xml";
#elif UNITY_IPHONE
 string filepath = Application.dataPath +"/Raw"+"/my.xml";
#elif UNITY_ANDROID
 string filepath = "jar:file://" + Application.dataPath + "!/assets/"+"/my.xml;
#endif

2.直接使用Application.streamingAssetsPath来读取文件进行操作。
注:此方法在pc/Mac电脑中可实现对文件实施“增删查改”等操作,但在移动端只支持读取操作。

四. 使用Application.persistentDataPath来操作文件(荐)
该文件存在手机沙盒中,因为不能直接存放文件,
1.通过服务器直接下载保存到该位置,也可以通过Md5码比对下载更新新的资源
2.没有服务器的,只有间接通过文件流的方式从本地读取并写入Application.persistentDataPath文件下,然后再通过Application.persistentDataPath来读取操作。
注:在Pc/Mac电脑 以及Android跟Ipad、ipone都可对文件进行任意操作,另外在IOS上该目录下的东西可以被iCloud自动备份。
 


综上,我决定为了平台可拓展性,用第三种方法来读取配置文件:

/**
*┌──────────────────────────────────────────────────────────────┐
*│ Description:读取或者写入XML文件的基类 ,其他类想要获取XML配置文件信息,可用该类作为中介                                               
*│ Author:#Keneyr#                                              
*│ Version:#2.0#                                                
*│ Date:#2019.8.14#  
*│  UnityVersion: #Unity2018.3.2f#                            
*└──────────────────────────────────────────────────────────────┘
*┌──────────────────────────────────────────────────────────────┐                                   
*│ ClassName:#ConfigManager#                                      
*└──────────────────────────────────────────────────────────────┘
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Xml;

public class ConfigManager 
{
    public static readonly string path = 

#if UNITY_EDITOR || UNITY_STANDALONE_WIN
    Application.streamingAssetsPath + "/Config/AllConfig.xml";  //直接IO类读取就行
#elif UNITY_IOS
    =Application.dataPath + "/Config/AllConfig.xml";
#elif UNITY_ANDROID
    ="jar:file:/" + "/" + Application.dataPath + "!/assets/" +"/Config/" + "/AllConfig.xml"; //需要用www类读取
#else
    =string.Empty;
#endif


    //外部接口,通过Key获取Value
    public static string GetConfigValue(string key)
    {
        string temp = ReadXML(key);
        Debug.Log(key+temp);
        return temp;
    }
    public static int GetConfigValueInt(string key)
    {
        string temp = ReadXML(key);
        
        int result = 0;
        if(int.TryParse(temp,out result))
        {
            result = int.Parse(temp);
        }
        Debug.Log(key+result);
        return result;
    }

    //xml存档--创建XML文件,无关
    private void WriteXML()
    {
        if(!File.Exists(path))
        {
            XmlDocument xml = new XmlDocument();
            XmlDeclaration xmldecl = xml.CreateXmlDeclaration("1.0","UTF-8",""); //设置xml文件编码格式为UTF-8
            XmlElement root = xml.CreateElement("Data"); //创建根节点
            XmlElement info = xml.CreateElement("Info"); //创建子节点
            info.SetAttribute("Name","Anna"); //创建子节点属性名和属性值
            info.SetAttribute("Age","28");
            root.AppendChild(info); //将子节点按照创建顺序,添加到xml

            xml.AppendChild(root);
            xml.Save(path); //保存xml到路径位置
            Debug.Log("创建XML成功!");
            
        }
    }

    //xml读取--读取XML文件
    private static string ReadXML(string key)
    {
        string tmp = null;
#if UNITY_EDITOR || UNITY_IOS || UNITY_STANDALONE_WIN
        if(File.Exists(path))
        {
            
            XmlDocument xml = new XmlDocument();
            xml.Load(path); //加载xml文件
            XmlNodeList nodeList = xml.SelectSingleNode("Data").ChildNodes;
            foreach(XmlElement xe in nodeList) //遍历所有子节点
            {
                if(xe.Name == "InitialInfo")
                {
                    //获取Name属性值
                    tmp = xe.GetAttribute(key);
                    return tmp;
                }
            }
        }
        else
        {
            Debug.Log("不存在该XML文件!");
        }
#elif UNITY_ANDROID
       //暂时不写---- = =.先把Windows下完事儿再说,等我完事儿再来更
       WWW www = new WWW(path);
       while(!www.isDone)
       {
           yield return www;
           all = www.text;
           //ParseXml(www);
       }
#endif
        
        return tmp;
    }




}
   
    

我的xml文件是这样的:


参考帖子:

https://blog.csdn.net/linxinfa/article/details/51679528

https://blog.csdn.net/itsxwz/article/details/80594334

https://www.cnblogs.com/coolbear/p/9262101.html

https://www.cnblogs.com/bw1219/p/9555863.html

https://blog.csdn.net/u010377179/article/details/52922727

https://blog.csdn.net/gameboy_ai/article/details/79713742

https://gameinstitute.qq.com/community/detail/117646

 

  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

keneyr

老爷~给小的赏点盘缠吧555~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值