填补Resources和WWW加载本地资源的坑
总的来说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加载本地资源的坑的更多相关文章
- [IOS]UIWebView 请求网络页面或者加载本地资源页面
UIWebView是一个能够显示网页的IOS视图控件,我们可以用它来访问一个网站.下面是具体的实例: 操作步骤: 1.首先在xib文件中拖放一个UIWebView控件到view中 2.将下载的页面以及 ...
- iOS webView 远程html加载本地资源
昨天,一个朋友让我帮他在IOS上弄这样一件事情: webView 调用远程URL,并且让远程的web 通过自定义标签能实现内嵌本地的图片.js 或音频等. 比如:在服务器端 的html文件中 这样写到 ...
- iOS WebView 加载本地资源(图片,文件等)
https://www.cnblogs.com/dhui69/p/5596917.html iOS WebView 加载本地资源(图片,文件等) NSString *path = [[NSBundle ...
- 引入外部 CDN失效时--怎么加载本地资源文件(本文以jquery为例)
相信大家都使用过CDN静态资源库,比如下面 CDN官方静态资源库:https://cdnjs.com/ 七牛前端公开库:http://staticfile.org (vue,react,nl都有) ...
- MFC CDHtmlDialog 加载本地资源
步骤:1.资源视图 项目右击选择资源添加,自定义添加新类型 如:JS(会增加JS文件夹)2. 选择1新建的文件夹右击 添加资源 导入 选择js文件引入3. 在资源文件Resource.h文件夹能找到资 ...
- qt webengineview 加载本地资源方式
一.如果把资源添加到本地资源qrc库里了,请使用 ui->preview->setUrl(QUrl("qrc:/HelloWorld2.html")): 二.如果没有现 ...
- 转:Android Webview 加载外部html时选择加载本地的js,css等资源文件
原文地址:http://m.blog.csdn.net/blog/qduningning/43196819 在使用WebView加载网页的时候,有一些固定的资源文件如js的jquery包,css,图片 ...
- Swift - 网页控件(UIWebView)加载本地数据,文件
使用UIWebView加载本地数据或资源有如下三种方式: 1,使用loadHTMLString方法加载HTML内容 2,使用loadRequest方法加载本地资源(也可用于加载服务器资源) 3,先将内 ...
- 使用three.js加载3dmax资源,以及实现场景中的阴影效果
使用three.js可以方便的让我们在网页中做出各种不同的3D效果.如果希望2D绘图内容,建议使用canvas来进行.但很多小伙伴不清楚到底如何为我们绘制和导入的图形添加阴影效果,更是不清楚到底如何导 ...
随机推荐
- git 提交代码到github错误处理
git push -u origin mastererror: The requested URL returned error: 403 Forbidden while accessing http ...
- python——线程与多线程基础
我们之前已经初步了解了进程.线程与协程的概念,现在就来看看python的线程.下面说的都是一个进程里的故事了,暂时忘记进程和协程,先来看一个进程中的线程和多线程.这篇博客将要讲一些单线程与多线程的基础 ...
- C#线程通信与异步委托
线程的通知机制 AutoResetEvent是线程实现通知操作的重要方法.通常,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号互相通信. AutoResetEvent时 ...
- 求第N个质数算法
用python求从1开始第1000个质数? 质数:只能被1和它本身整除的数.那好,我们开始写程序(一个小算法). def calc_prime(prime,num): i,gab=7,2 while ...
- css学习归纳总结(三) 转
原文地址:css学习归纳总结(三) 为文档添加样式的三种方法 行内样式 行内样式是写在HTML标签的style属性里的,比如: <p style="font-size: 12px;fo ...
- css属性的书写
书写顺序: 注释方式: /* 块状注释文字 * 块状注释文字 * 块状注释文字 */ .m-list{width:500px;} .m-list li{height:20px;line-height: ...
- shell脚本中的几个括号总结(小括号/大括号/花括号)--from:http://www.cnblogs.com/hanyan225/archive/2011/10/06/2199652.html
在Shell中的小括号,大括号结构和有括号的变量,命令的用法如下: 1.${var}2.$(cmd)3.()和{}4.${var:-string},${var:+string},${var:=stri ...
- lamp遇到问题
1.配置好apache和虚拟host,显示无权, 将网站目录更新755,还是不行,最后selinux: 1.设置下面即可: chcon -R -h -t httpd_sys_content_t /ho ...
- Fibonacci(斐波那契)递归实现。容易看懂
#include<iostream>using namespace std;int fibonacci(int n){if(n<=0) return 0; else if(n==1) ...
- 也谈自动化平台的搭建,另附高大上的名字---无人值守定时巡检系统(selenium+testng+ant+jenkins)
最近公司新项目改版,由于没有运维,开发则负责上线任务,并且都是手动上线,并行的项目多了,分支混乱,经常导致B项目上线覆盖A项目,导致系统不定时出现异常,老板知道了便扣了大家的绩效,作为测试这边必须想个 ...