这篇文章将为大家详细讲解有关unity怎么使用文件流读取streamingassets下的资源,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
目的:读取streamingassets下的文件中指定的一段字节
已知:文件中的起始位置,和需要读取的长度
var buffer = new byte[size];
FileStream stream = File.OpenRead(path);
stream.Read(buffer , pos, size);
报错:
IsolatedStorageException: Could not find a part of the path "/jar:file:/data/app/com.xxx.xxxx-1/base.apk!/assets/xxx.pack".
主要过程:
Java
public class XXXPlugin extends UnityPlayerNativeActivity {
protected AssetManager assetManager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
assetManager = getAssets();
}
//返回字节数组
public byte[] LoadBytes(String path,int offset,int len)
{
//可以缓存起来,不需每次都open
InputStream inputStream = assetManager.open(path);
try {
byte buf[] = new byte[len];
inputStream.reset();
//注意skip、read的可靠性
inputStream.skip(offset);
inputStream.read(buf,0,len)
inputStream.close();
return buf;
}
catch (IOException e) {
Log.v ("unity", e.getMessage());
}
return null;
}
}
注意skip、read的可靠性,每次调用不一定能返回正确长度,可能需多次调用。
参考how-does-the-skip-method-in-inputstream-work
C#:
public static byte[] read_streamingpath_bytes(string path,IntPtr ptr, int pos, int size)
{
using (AndroidJavaClass cls = new AndroidJavaClass("com.XXX.XXXPlugin";) )
{
AndroidJavaObject m_AndroidJavaObject = cls.GetStatic<AndroidJavaObject>("mainActivity");
byte[] s = m_AndroidJavaObject.Call<byte[]>("LoadBytes", path, pos, size);
return s;
}
return null;
}
这种方法是在Java分配内存。
在Android Studio中生成库libNativeLib.so文件,参考NativeReadBytes
C++
#include "com_XXX_NativeHelper.h"
#include <android/asset_manager_jni.h>
#include <android/asset_manager.h>
#include <string>
#include <jni.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
static AAssetManager *assetManager = nullptr;
JNIEXPORT void JNICALL Java_com_XXX_NativeHelper_SetAssetManager
(JNIEnv *env, jobject jobj, jobject jassetManager) {
assetManager = AAssetManager_fromJava(env, jassetManager);
}
JNIEXPORT int32_t JNICALL ReadAssetsBytesWithOffset(uint32_t pathKey, char* fileName, unsigned char** result, int32_t offset, int32_t length){
if(assetManager == nullptr){
return -1;
}
AAsset* asset = asset = AAssetManager_open(assetManager, fileName, AASSET_MODE_UNKNOWN);
if(asset == nullptr){
return -1;
}
off_t size = AAsset_getLength(asset);
if(size > 0){
try {
AAsset_seek(asset, offset, SEEK_SET);
AAsset_read(asset, *result, length);
}catch (std::bad_alloc){
*result = nullptr;
return -1;
}
}
AAsset_close(asset);
return (int32_t)length;
}
#ifdef __cplusplus
}
#endif
Java
//XXXPlugin.java
public class XXXPlugin extends UnityPlayerNativeActivity {
static{
System.loadLibrary("NativeLib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = this;
//设置AssetManager, C++中要使用
NativeHelper.SetAssetManager(getAssets());
}
}
//NativeHelper.java
public class NativeHelper {
public static native void SetAssetManager(AssetManager assetManager);
}
C#
public class ReadNativeByte
{
#if UNITY_ANDROID
[DllImport("NativeLib")]
public static extern int ReadAssetsBytesWithOffset(uint pathKey,string name, ref IntPtr ptr, int offset, int length);
#endif
}
可以直接在C#下读取,StreamAsseting只有读的权限,用OpenRead
byte[] bytes = new byte[len];
FileStream stream = File.OpenRead(path);
stream.Seek(offset, SeekOrigin.Begin);
stream.Read(bytes, 0, len);
补充:unity中 在移动平台各种读写文件夹存路径整理 如 StreamingAssets 等文件夹 各个路径在各种平台的文件路径
//资源卸载
/*
* Resources.UnloadAsset(obj):卸载非 GameObject类型的资源,会将内存中已加载资源及其克隆体卸载。
Destroy(obj):仅用于卸载GameObject类型的资源的克隆体。
DestroyImmediately(obj):卸载GameObject类型的资源,会将内存中已加载资源及其克隆体卸载,但该方法只能用在非编辑模式下,否则会报错提示改为DestroyImmediately(obj, true),然而编辑模式下使用该函数会连文件夹里的原始Asset一并删除。
*/
在移动端也是只可读的不能写入数据 主要用来存放二进制文件。
//安卓下这两个文件夹路径相同
//Application.streamingAssetsPath = jar:file:///data/app/com.xxx.xxx-1.apk!/assets/ == "jar:file://"+Application.dataPath+"!assets/"
//Application.dataPath+"!assets/" = /data/app/com.xxx.xxx-1.apk!assets/
//Ios下
//Application.dataPath + "/Raw/" == @"file:///" + Application.streamingAssetsPath + "/"
//Editor WIN
//@"file:///" + Application.streamingAssetsPath + "/"
//"file:///" + Application.dataPath + "/StreamingAssets" + "/"
private string path = string.Empty;
public string GetSAPath()
{
//安卓平台 加文件名
#if UNITY_ANDROID && !UNITY_EDITOR
path = Application.streamingAssetsPath + "/"
#elif UNITY_IPHONE && !UNITY_EDITOR
path = @"file:///" + Application.streamingAssetsPath + "/";
#elif UNITY_STANDLONE_WIN||UNITY_EDITOR
path = @"file:///" + Application.streamingAssetsPath + "/";
#endif
return path;
}
这个目录可读可写 一般存本地关卡等
用于存档 直接使用 打包之前是没有这个目录的,直到应用程序在手机上安装完毕才有这个目录。
1.通过服务器直接下载保存到该位置,也可以通过Md5码比对下载更新新的资源
2.没有服务器的,只有间接通过文件流的方式从本地读取并写入Application.persistentDataPath文件下,然后再通过
Application.persistentDataPath来读取操作。
注:在Pc/Mac电脑 以及Android跟Ipad、ipone都可对文件进行任意操作,另外在IOS上该目录下的东西可以被iCloud自动备份。
Application.persistentDataPath + "/tempDic", "testXml"
Windows应用商店应用程序:
application.persistentdatapath指向%userprofile%\appdata\local\packages\<productName>\localstate
ios:application.persistentdatapath指向/var/mobile/containers/data/application/<guid>/documents
android:application.persistentdatapath指向大多数设备上的/storage/emulated/0/android/data/<packagename>/文件(有些旧手机可能指向SD卡上的位置,如果存在),该路径使用android.content.context.getexternalfilesdir解析
关于“unity怎么使用文件流读取streamingassets下的资源”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。