总的来说Resources和WWW加载本地资源坑比较多,大多与路径有关。

下面代码构成了一个路径的预读模块:

此模块主要解决的坑是:Resources或WWW加载本地的文件夹中的多个文件时,无法获取文件夹下的文件名称的坑,原因是Resources路径和StreamingAssets路径下打包到安卓安装后路径都不再存在的问题。想要读取Resources路径或StreamingAssets路径某个文件夹下的大量文件,找了好久都没找到方法。后来想了一个绕过此坑的办法,就是在程序未执行前先保存一份路径信息到场景中或保存成预设,运行时就可以访问了。

代码1.多叉树实现目录结构

using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 使用多叉树实现目录结构
/// </summary>
[Serializable]
public class PathStruct
{
/// <summary>
/// 目录名称或文件名称(不包含扩展名)
/// </summary>
public string name;
/// <summary>
/// 扩展名都是以“.”开头的
/// </summary>
public string extensionName;
/// <summary>
/// 是否是文件
/// </summary>
public bool isFile;
/// <summary>
/// 父节点
/// </summary>
[NonSerialized]
public PathStruct parent;
/// <summary>
/// 子节点
/// </summary>
public List<PathStruct> children = new List<PathStruct>();

/// <summary>
/// 文件夹结构构造函数
/// </summary>
/// <param name="name"></param>
/// <param name="parent"></param>
/// <param name="children"></param>
public PathStruct(string name, PathStruct parent, List<PathStruct> children = null)
{
this.name = name;
this.parent = parent;
this.children = children;
if (parent != null)
parent.AddChild(this);
if (children == null)
this.children = new List<PathStruct>();
}
/// <summary>
/// 文件结构构造函数
/// </summary>
/// <param name="name"></param>
/// <param name="parent"></param>
/// <param name="extensionName"></param>
public PathStruct(string name, PathStruct parent, string extensionName)
{
this.name = name;
this.parent = parent;
this.extensionName = extensionName;
isFile = true;
if (parent != null)
parent.AddChild(this);
if (children == null)
children = new List<PathStruct>();
}

/// <summary>
/// 放回从父物体到此物体的完整路径,物体间用'/'隔开
/// </summary>
/// <returns></returns>
public override string ToString()
{
if (parent == null || string.IsNullOrEmpty(parent.name))
return name;
return parent +"/"+ name;
}
/// <summary>
/// 输出从根节点到此节点的完整路径(相对完整,并不是绝对路径)
/// </summary>
/// <param name="isContainsExtension">是否包括文件扩展名</param>
/// <returns></returns>
public string ToString(bool isContainsExtension)
{
if(isContainsExtension)
return parent + "/" + name+extensionName;
return ToString();
}
/// <summary>
/// 增加子节点
/// </summary>
/// <param name="pathStruct"></param>
public void AddChild(PathStruct pathStruct)
{
children.Add(pathStruct);
pathStruct.parent = this;
}

/// <summary>
/// 增加子节点
/// </summary>
/// <param name="pathStruct"></param>
public void AddChildren(List<PathStruct> pathStructs)
{
children.AddRange(pathStructs);
foreach (var pathStruct in pathStructs)
{
pathStruct.parent = this;
}
}
/// <summary>
/// 获取该节点下所有子节点的完整路径(相对完整,并不是绝对路径)
/// </summary>
/// <param name="isContainsExtension"></param>
/// <returns></returns>
public List<string> GetChildrenFullPath(bool isContainsExtension)
{
if (children == null || children.Count == 0) return null;
var res = new List<string>(children.Count);
foreach (var pathStruct in children)
{
if (pathStruct.name != null)
{
res.Add(pathStruct.ToString(isContainsExtension));
}
}
return res;
}

/// <summary>
/// 获取该节点下所有子节点的名称(相对完整,并不是绝对路径)
/// </summary>
/// <param name="isContainsExtension"></param>
/// <returns></returns>
public List<string> GetChildrenNames(bool isContainsExtension)
{
if (children == null) return null;
var res = new List<string>(children.Count);
foreach (var pathStruct in children)
{
if (pathStruct.name != null)
{
res.Add(pathStruct.name + (isContainsExtension?extensionName:""));
}
}
return res;
}
/// <summary>
/// 打印出该节点下所有节点
/// </summary>
/// <param name="isFullPath"></param>
/// <param name="isContainsExtension"></param>
public void PrintAll(bool isFullPath = false ,bool isContainsExtension = false)
{
if(isFullPath)
Debug.Log(ToString(isContainsExtension));
else
Debug.Log(name);
if (children != null)
{
foreach (var pathStruct in children)
{
pathStruct.PrintAll(isFullPath, isContainsExtension);
}
}
}
/// <summary>
/// 在子节点中查找符合条件的节点
/// </summary>
/// <param name="condition"></param>
/// <param name="isFindChild"></param>
/// <returns></returns>
public PathStruct Find(Func<PathStruct,bool> condition,bool isFindChild = false)
{
if (children == null) return null;
foreach (var pathStruct in children)
{
if (condition(pathStruct))
return pathStruct;
if (isFindChild)
{
var pathS = pathStruct.Find(condition, isFindChild);
if (pathS != null)
return pathS;
}
}
return null;
}
/// <summary>
/// 在子节点中查找符合条件的节点
/// </summary>
/// <param name="condition"></param>
/// <param name="isFindChild"></param>
/// <returns></returns>
public List<PathStruct> FindAll(Func<PathStruct, bool> condition, bool isFindChild = false)
{
if (children == null) return null;
var res = new List<PathStruct>();
foreach (var pathStruct in children)
{
if (condition(pathStruct))
res.Add( pathStruct);
if (isFindChild)
{
var pathSS = pathStruct.FindAll(condition, isFindChild);
if (pathSS != null)
res.AddRange( pathSS);
}
}
return res;
}
/// <summary>
/// 重新根据子节点信息给各节点装入父节点信息
/// </summary>
public void ResetParent()
{
if (children != null)
foreach (var pathStruct in children)
{
pathStruct.parent = this;
pathStruct.ResetParent();
}
}
}

代码2. 运行在Editor模式下的菜单命令,此代码应该存放在某个Editor目录下

using CommonUtilities;
using UnityEditor;
using UnityEngine;

public class PathStructionBuilder
{
[MenuItem("Path/Create Resouces Path Info To Current Scene")]
static void CreateGObyResources()
{
var resourcesPath = Application.dataPath + "/Resources/";
Debug.Log("resourcesPath: "+ resourcesPath);
ResourcesPathAccess.Instance.root = new PathStruct("",null);
CreatePathStruct(resourcesPath, ResourcesPathAccess.Instance.root);

ResourcesPathAccess.Instance.root.PrintAll(true);
}

[MenuItem("Path/Create StreamingAssets Path Info To Current Scene")]
static void CreateGObyStreamingAssets()
{
var streamingAssets = Application.dataPath + "/StreamingAssets/";
Debug.Log("StreamingAssets: " + streamingAssets);
StreamingAssetAccess.Instance.root = new PathStruct("", null);
CreatePathStruct(streamingAssets, StreamingAssetAccess.Instance.root);

StreamingAssetAccess.Instance.root.PrintAll(true);
}

public static void CreatePathStruct(string path,PathStruct parent)
{
var files = FileHelper.GetFileNames(path);
foreach (var p in files)
{
if (p.Contains(".meta"))
continue;
new PathStruct(GetPathName(p), parent, GetFileExtensionName(p));
Debug.Log("增加文件: " + p);
}
var paths = FileHelper.GetDirectories(path);
foreach (var p in paths)
{
var pathStruct = new PathStruct(GetPathName(p), parent);
Debug.Log("增加路径: " + p);
CreatePathStruct(p, pathStruct);
}

}

private static string GetFileExtensionName(string pathName)
{
return FileHelper.GetExtension(pathName);
}

public static string GetPathName(string path)
{
return FileHelper.GetFileNameNoExtension(path);
}

}

代码3. Resources路径下的信息保存位置

using System;
using System.Collections.Generic;
using UnityEngine;

public class ResourcesPathAccess:SingleBhv<ResourcesPathAccess>
{
public PathStruct root;

public override void Init()
{
base.Init();
root.ResetParent();
}

public List<string> GetFileList(string resourceUri)
{
if (!isInited)
Init();
var ss = resourceUri.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var pathStruct = root;
foreach (var s in ss)
{
if (pathStruct != null)
pathStruct = pathStruct.Find(t => t.name == s);
else
Debug.LogError("resourceUri 错误!");
}
if (pathStruct != null)
{
return pathStruct.GetChildrenFullPath(false);
}
return null;
}
}

代码4. StreamingAssets路径下的信息保存位置

using System;
using System.Collections.Generic;
using UnityEngine;

public class StreamingAssetAccess : SingleBhv<StreamingAssetAccess>
{
public PathStruct root;
public override void Init()
{
base.Init();
root.ResetParent();
}

public List<string> GetFileList(string resourceUri)
{
if(!isInited)
Init();
var ss = resourceUri.Split(new []{'/'},StringSplitOptions.RemoveEmptyEntries);
var pathStruct = root;
List<string> res = new List<string>();
foreach (var s in ss)
{
if (pathStruct != null)
pathStruct = pathStruct.Find(t=>t.name == s);
else
Debug.LogError("resourceUri 错误!");
}
if (pathStruct != null)
{
res = pathStruct.GetChildrenFullPath(true);
}
for (int index = 0; index < res.Count; index++)
{
res[index] = PathTool.Instance.GetSystemHeadPath() + PathTool.Instance.GetStreamAssetsPath() + res[index];
}
return res;
}
}

(其中用到了单例SingleBhv<T>,请参考:http://www.cnblogs.com/fuliufuliu/p/4860685.html)

使用时可以这样:

StreamingAssetAccess.Instance.GetFileList(packageName);

ResourcesPathAccess.Instance.GetFileList(packageName);

 

遗憾的是在每次编译时和执行时会报红,不过这个错误暂时没发现此红对程序有什么不妥(希望大神指点):

填补Resources和WWW加载本地资源的坑的更多相关文章

  1. [IOS]UIWebView 请求网络页面或者加载本地资源页面

    UIWebView是一个能够显示网页的IOS视图控件,我们可以用它来访问一个网站.下面是具体的实例: 操作步骤: 1.首先在xib文件中拖放一个UIWebView控件到view中 2.将下载的页面以及 ...

  2. iOS webView 远程html加载本地资源

    昨天,一个朋友让我帮他在IOS上弄这样一件事情: webView 调用远程URL,并且让远程的web 通过自定义标签能实现内嵌本地的图片.js 或音频等. 比如:在服务器端 的html文件中 这样写到 ...

  3. iOS WebView 加载本地资源(图片,文件等)

    https://www.cnblogs.com/dhui69/p/5596917.html iOS WebView 加载本地资源(图片,文件等) NSString *path = [[NSBundle ...

  4. 引入外部 CDN失效时--怎么加载本地资源文件(本文以jquery为例)

    相信大家都使用过CDN静态资源库,比如下面 CDN官方静态资源库:https://cdnjs.com/ 七牛前端公开库:http://staticfile.org   (vue,react,nl都有) ...

  5. MFC CDHtmlDialog 加载本地资源

    步骤:1.资源视图 项目右击选择资源添加,自定义添加新类型 如:JS(会增加JS文件夹)2. 选择1新建的文件夹右击 添加资源 导入 选择js文件引入3. 在资源文件Resource.h文件夹能找到资 ...

  6. 转:Android Webview 加载外部html时选择加载本地的js,css等资源文件

    原文地址:http://m.blog.csdn.net/blog/qduningning/43196819 在使用WebView加载网页的时候,有一些固定的资源文件如js的jquery包,css,图片 ...

  7. Swift - 网页控件(UIWebView)加载本地数据,文件

    使用UIWebView加载本地数据或资源有如下三种方式: 1,使用loadHTMLString方法加载HTML内容 2,使用loadRequest方法加载本地资源(也可用于加载服务器资源) 3,先将内 ...

  8. Google浏览器如何加载本地文件

    Chrome浏览器加载本地文件 一般来说,为了安全起见,浏览器是不能通过load方法来加载本地文件的,load方法只能加载远程服务器上的文件. 在浏览器默认的情况下,试图加载一个本地文件,会出现交叉域 ...

  9. 【Unity3D】Unity3D之 Resources.Load 动态加载资源

    [Unity3D]Unity3D之 Resources.Load 动态加载资源 1.Resources.Load:使用这种方式加载资源,首先需要下Asset目录下创建一个名为Resources的文件夹 ...

随机推荐

  1. struts2 jquery ajaxFileUpload 异步上传文件

    网上搜集的,整理一下. 一.ajaxFileUpload 实现异步上传文件利用到了ajaxFileUpload.js这个文件,这是别人开发的一个jquery的插件,可以实现文件的上传并能够和strut ...

  2. Oracle字符集修改

    1.使用管理员账号登录到oracle C:\Users\Administrator>sqlplus / as sysdba 2.查看字符集 SQL>select userenv('lang ...

  3. ACM spiral grid

    spiral grid 时间限制:2000 ms  |  内存限制:65535 KB 难度:4   描述 Xiaod has recently discovered the grid named &q ...

  4. (spring-第12回【IoC基础篇】)JavaBean的属性编辑器

    在spring实例化bean的最后阶段,spring利用属性编辑器将配置文件中的文本配置值转换为bean属性的对应值,例如: 代码0011 <bean id="car" cl ...

  5. C#发送邮件源码

    介绍 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式.SMTP协议属于TCP/IP协议 ...

  6. react.js 从零开始(三)JSX 语法及特点介绍

    什么是jsx? jsx = JavaScript + xml jsx 是一种 Ecmascript 的一种新标准. jsx 是一种 带有结构性的语法. jsx 的特点: 1.类xml语法易于理解. 2 ...

  7. guava-19.0和google-collections-1.0 的 ImmutableSet 类冲突

    guava-19.0 google-collections-1.0 都有 ImmutableSet 类,包路径也一致,前者有 copyOf(Collection)? 一.应用报错: 二.解决办法 co ...

  8. 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  9. java实现八大排序算法

    Arrays.sort() 采用了2种排序算法 -- 基本类型数据使用快速排序法,对象数组使用归并排序. java的Collections.sort算法调用的是归并排序,它是稳定排序 方法一:直接插入 ...

  10. win10ssh连接ubuntu服务器并本地绘图

    update @ 2018-11-07 00:36:38 用xrdp+tigervnc等的组合,可以使用原生unity桌面.具体教程见ubuntu日常使用指南 工具准备 win10上: xshell, ...