总的来说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. 转:Android Webview 加载外部html时选择加载本地的js,css等资源文件

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

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

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

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

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

  6. worker中加载本地文件报错的解决方案

    如果在一个swf的主线程中加载文件时,报安全沙箱的错误, 网上有诸多的解决方案.但是如果在一个worker中加载本地文件报类似如下的错误: *** 安全沙箱冲突 *** SecurityError: ...

  7. wp加载本地HTML(附带图片,CSS,JS)

    wp加载本地HTML(附带图片,CSS,JS) Windows Phone:Load Local HTML with Img,Css,Js by 唐小崇 http://www.cnblogs.com/ ...

  8. #iOS问题记录#动态Html加载本地CSS和JS文件

    所谓动态Html,指代码中组合生成的html字符串: 若需要加载本地CSS,图片,JS文件,则, 1,需要文件的全路径: 2,需要"file:///"标志: 例如: //获取文件全 ...

  9. 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图

    [源码下载] 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Co ...

随机推荐

  1. MySQL数据迁移到SQL Server

    数据迁移的工具有很多,基本SSMA团队已经考虑到其他数据库到SQL Server迁移的需求了,所以已经开发了相关的迁移工具来支持. 此博客主要介绍MySQL到SQL Server数据迁移的工具:SQL ...

  2. 警惕多iframe下的同名id引起的诡异问题

    遇到个诡异bug,虽然bug中套bug,忽略次要bug,其中最诡异最典型的现象是多行window.top.$("#id")取值操作,其中有一行却取不到值.这个着实让我费解.因为用到 ...

  3. php——文件下载

    php——.doc 文件下载 先看简单实例: 同目录下有两个文件ib.php,test.php与供下载 .doc 文件: test.php文件内容: <?php $attr = glob(&qu ...

  4. Android -- 仿ios上下反弹效果

    1,前几天在一个app上看到了滑动反弹效果,觉得这个效果挺不错的,然后想自己来实现一下,在网上查了一下基本上都是大致的说了下思路,自己看了一下,决定把实现的思路来详细的写下来,先看一下我们实现的效果吧 ...

  5. python中main()函数写法

    顶顶大名的Guido van Rossum(Python之父)推荐的main写法: #!/usr/bin/python import sys import getopt class Usage(Exc ...

  6. Symfony2创建基于域名的路由(原创翻译)

    你可以匹配将要来到的请求以HTTP域名的方式 YAML方式 mobile_homepage: path: / host: m.example.com defaults: { _controller: ...

  7. [moka同学笔记]yii表单dropdownlist样式

    <?= $form->field($modelUser,'name') ?> <div class="form-group field-community-mobil ...

  8. new-nav-css

    header:before, header:after ,.navigation:before, .navigation:after,.nav-row:before, .nav-row:after,. ...

  9. HDU 2059 龟兔赛跑(动态规划)

    龟兔赛跑 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  10. Struts1和Struts2都有什么区别?

    总的来说,Struts1 的 Action 是单例模式,因此开发者必须保证它是线程安全的或是同步的,因为Struts 1中每个Action仅有一个实例来处理所有的请求.     但是在用Struts  ...