Unity3D研究院之Android同步方法读取streamingAssets(八十八)

版本Unity5.3.3

Android 小米pad1

streamingAssets 这个目录在IOS下是可以同步读取的,但是在Android下必须用www来异步读取。。这就很恶心了~所以最近我就在想办法如何能在Android下也能同步读取。如下图所示,我把一个sprite打成assetbundle并且放在StreamingAssets目录下。

assetbundle的压缩格式 ,我使用的是unity5.x的lz4方式。

 [MenuItem ("Assets/Build AssetBundles")]
 static void BuildAllAssetBundles ()
 {
 BuildPipeline.BuildAssetBundles ("Assets/StreamingAssets",BuildAssetBundleOptions.ChunkBasedCompression,BuildTarget.Android);
 
 AssetDatabase.SaveAssets ();
 AssetDatabase.Refresh();
 }

然后创建一个3D Sprite 在Hierarchy里 试图把这个ab里的sprite加载上去。

using UnityEngine;
using System.Collections;
 
public class NewBehaviourScript : MonoBehaviour {
 
 public SpriteRendererspriteRenderer;
 void Start () {
//注释掉的代码是 unity自己的同步方式, 但是在Android上不行, 可是在IOS上可以
// AssetBundle assetbundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath +"/yusong.unity3d");
//
// Sprite sprite = assetbundle.LoadAsset("0");
//
// spriteRenderer.sprite =sprite;
 
 
 //以下代码通过JAVA代码来同步读取并且返回给unity
 AndroidJavaClassm_AndroidJavaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
 AndroidJavaObjectm_AndroidJavaObject  = null;
 if (m_AndroidJavaClass != null) {
 m_AndroidJavaObject = m_AndroidJavaClass.GetStatic("currentActivity");
 }
 
 byte[] s = m_AndroidJavaObject.Call("LoadAB","yusong.unity3d");
 AssetBundleassetbundle = AssetBundle.LoadFromMemory(s);
 
 Spritesprite = assetbundle.LoadAsset("0");
 spriteRenderer.sprite =sprite; 
 
 }
 
}

然后,把unity导出成android工程。。

用eclipse打开刚刚导出的工程。找到UnityPlayerActivity.java类 添加如下代码

package com.yusong.momo;
 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
 
import com.unity3d.player.*;
 
import android.app.Activity;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
 
public class UnityPlayerActivity extends Activity
{
 protected UnityPlayermUnityPlayer; // don't change the name of this variable; referenced from native code
 
 
 protected AssetManagerassetManager;
 
 // Setup activity layout
 @Override protected void onCreate (BundlesavedInstanceState)
 {
 requestWindowFeature(Window.FEATURE_NO_TITLE);
 super.onCreate(savedInstanceState);
 
 getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
 
 mUnityPlayer = new UnityPlayer(this);
 setContentView(mUnityPlayer);
 mUnityPlayer.requestFocus();
 
 assetManager = getAssets();
 
 
 }
 
 
 private byte[] readtextbytes(InputStreaminputStream) 
 {
 
  ByteArrayOutputStreamoutputStream = new ByteArrayOutputStream();
//长度这里暂时先写成1024
  byte buf[] = new byte [1024];
 
  int len;
 
  try {
 
  while ((len = inputStream.read(buf)) != -1) {
 
    outputStream.write(buf, 0, len);
 
  }
 
  outputStream.close();
 
  inputStream.close();
 
  } catch (IOException e) {
 
  }
  return outputStream.toByteArray();
 }
 
 
 
 
 //读取assetbund并且返回字节数组
 public byte[] LoadAB(String path)
 {
 
 InputStreaminputStream = null ;
 
  try {
 
  inputStream = assetManager.open(path);
 
  } catch (IOException e) {
 
  Log.v ("unity", e.getMessage());
 
  }
 
  return readtextbytes(inputStream);
 }
 
 
 // Quit Unity
 @Override protected void onDestroy ()
 {
 mUnityPlayer.quit();
 super.onDestroy();
 }
 
 // Pause Unity
 @Override protected void onPause()
 {
 super.onPause();
 mUnityPlayer.pause();
 }
 
 // Resume Unity
 @Override protected void onResume()
 {
 super.onResume();
 mUnityPlayer.resume();
 }
 
 // This ensures the layout will be correct.
 @Override public void onConfigurationChanged(ConfigurationnewConfig)
 {
 super.onConfigurationChanged(newConfig);
 mUnityPlayer.configurationChanged(newConfig);
 }
 
 // Notify Unity of the focus change.
 @Override public void onWindowFocusChanged(boolean hasFocus)
 {
 super.onWindowFocusChanged(hasFocus);
 mUnityPlayer.windowFocusChanged(hasFocus);
 }
 
 // For some reason the multiple keyevent type is not supported by the ndk.
 // Force event injection by overriding dispatchKeyEvent().
 @Override public boolean dispatchKeyEvent(KeyEventevent)
 {
 if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
 return mUnityPlayer.injectEvent(event);
 return super.dispatchKeyEvent(event);
 }
 
 // Pass any events not handled by (unfocused) views straight to UnityPlayer
 @Override public boolean onKeyUp(int keyCode, KeyEventevent)    { return mUnityPlayer.injectEvent(event); }
 @Override public boolean onKeyDown(int keyCode, KeyEventevent)  { return mUnityPlayer.injectEvent(event); }
 @Override public boolean onTouchEvent(MotionEventevent)          { return mUnityPlayer.injectEvent(event); }
 /*API12*/ public boolean onGenericMotionEvent(MotionEventevent)  { return mUnityPlayer.injectEvent(event); }
}

OK 大功告成, 我的sprite已经可以同步加载了。

如下图所示,那么实际上unity把已经把streamingAssets目录下的资源放在了android的assets目录下。

那么我们同步加载的原理也是利用Android的AssetManager这个类来读取的。

刚和同事讨论了一下,如果有效率的问题,我们可以在ndk里读取assets下的资源。 比如向这样~ c# 调用 ndk 读取完直接返回给c# 这样就可以不通过java这一层。。

http://www.cppblog.com/johndragon/archive/2012/12/28/196754.html

最后希望大家可以帮忙多多测试看看,谢谢啦~~

MOMO与MO嫂提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!

最后编辑: 2016-04-29

作者:雨松MOMO

专注移动互联网,Unity3D游戏开发

站内专栏 QQ交谈 腾讯微博 新浪微博

捐 赠 如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。

雨松MOMO程序研究院稿源:雨松MOMO程序研究院 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 综合技术 » Unity3D研究院之Android同步方法读取streamingAssets(八十八)

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录