android unity 文件读写_Unity3D研究院之Android同步方法读取streamingAssets(八十八)...

版本Unity5.3.3

Android 小米pad1

首先非常感谢 @守着阳光 同学在下面的留言。让我解决了一个大的谜团。。

开始我知道 StreamingAssets 路径是这个 path = “jar:file://” + Application.dataPath + “!/assets/”;

后来我知道了一个新API Application.streamingAssetsPath

Application.streamingAssetsPath 其实就等于 “jar:file://” + Application.dataPath + “!/assets/”;

然而问题就出现在这个路径上。我打印了一下LOG

Application.streamingAssetsPath = jar:file:///data/app/com.xxx.xxx-1.apk!/assets

Application.dataPath+”!assets” = /data/app/com.xxx.xxx-1.apk!assets

也就是说Application.streamingAssetsPath  多了一个   jar:file://

那么如果想在Android上同步方法AssetBundle.LoadFromFile 就得用 Application.dataPath+”!assets”这个路径。

从此这段代码就正常了。

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

usingUnityEngine;

usingSystem.Collections;

publicclassNewBehaviourScript:MonoBehaviour{

publicSpriteRendererspriteRenderer;

voidStart(){

// /data/app/com.xxx.xxx-1.apk!assets/yusong.unity3d

stringpath=Application.dataPath+"!assets/yusong.unity3d";

AssetBundleassetbundle=AssetBundle.LoadFromFile(path);

Spritesprite=assetbundle.LoadAsset("0");

spriteRenderer.sprite=sprite;

}

}

Unity的坑啊~ 55555555555555555555

还有这个路径只能用来AssetBundle.LoadFromFile 。如果想用File类操作。 比如File.ReadAllText  或者 File.Exists  Directory.Exists 这样都是不行的。

———————————-!!从今天以后下面的代码已经可以作废了!!—————————

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

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

C#

1

2

3

4

5

6

7

8

[MenuItem("Assets/Build AssetBundles")]

staticvoidBuildAllAssetBundles()

{

BuildPipeline.BuildAssetBundles("Assets/StreamingAssets",BuildAssetBundleOptions.ChunkBasedCompression,BuildTarget.Android);

AssetDatabase.SaveAssets();

AssetDatabase.Refresh();

}

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

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

usingUnityEngine;

usingSystem.Collections;

publicclassNewBehaviourScript:MonoBehaviour{

publicSpriteRendererspriteRenderer;

voidStart(){

//注释掉的代码是 unity自己的同步方式, 但是在Android上不行, 可是在IOS上可以

//AssetBundle assetbundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath +"/yusong.unity3d");

//

//Sprite sprite = assetbundle.LoadAsset("0");

//

//spriteRenderer.sprite =sprite;

//以下代码通过JAVA代码来同步读取并且返回给unity

AndroidJavaClassm_AndroidJavaClass=newAndroidJavaClass("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类 添加如下代码

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

packagecom.yusong.momo;

importjava.io.ByteArrayOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importcom.unity3d.player.*;

importandroid.app.Activity;

importandroid.content.res.AssetManager;

importandroid.content.res.Configuration;

importandroid.graphics.PixelFormat;

importandroid.os.Bundle;

importandroid.util.Log;

importandroid.view.KeyEvent;

importandroid.view.MotionEvent;

importandroid.view.View;

importandroid.view.Window;

importandroid.view.WindowManager;

publicclassUnityPlayerActivityextendsActivity

{

protectedUnityPlayermUnityPlayer;// don't change the name of this variable; referenced from native code

protectedAssetManagerassetManager;

// Setup activity layout

@OverrideprotectedvoidonCreate(BundlesavedInstanceState)

{

requestWindowFeature(Window.FEATURE_NO_TITLE);

super.onCreate(savedInstanceState);

getWindow().setFormat(PixelFormat.RGBX_8888);//

mUnityPlayer=newUnityPlayer(this);

setContentView(mUnityPlayer);

mUnityPlayer.requestFocus();

assetManager=getAssets();

}

privatebyte[]readtextbytes(InputStreaminputStream)

{

ByteArrayOutputStreamoutputStream=newByteArrayOutputStream();

//长度这里暂时先写成1024

bytebuf[]=newbyte[1024];

intlen;

try{

while((len=inputStream.read(buf))!=-1){

outputStream.write(buf,0,len);

}

outputStream.close();

inputStream.close();

}catch(IOExceptione){

}

returnoutputStream.toByteArray();

}

//读取assetbund并且返回字节数组

publicbyte[]LoadAB(Stringpath)

{

InputStreaminputStream=null;

try{

inputStream=assetManager.open(path);

}catch(IOExceptione){

Log.v("unity",e.getMessage());

}

returnreadtextbytes(inputStream);

}

// Quit Unity

@OverrideprotectedvoidonDestroy()

{

mUnityPlayer.quit();

super.onDestroy();

}

// Pause Unity

@OverrideprotectedvoidonPause()

{

super.onPause();

mUnityPlayer.pause();

}

// Resume Unity

@OverrideprotectedvoidonResume()

{

super.onResume();

mUnityPlayer.resume();

}

// This ensures the layout will be correct.

@OverridepublicvoidonConfigurationChanged(ConfigurationnewConfig)

{

super.onConfigurationChanged(newConfig);

mUnityPlayer.configurationChanged(newConfig);

}

// Notify Unity of the focus change.

@OverridepublicvoidonWindowFocusChanged(booleanhasFocus)

{

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().

@OverridepublicbooleandispatchKeyEvent(KeyEventevent)

{

if(event.getAction()==KeyEvent.ACTION_MULTIPLE)

returnmUnityPlayer.injectEvent(event);

returnsuper.dispatchKeyEvent(event);

}

// Pass any events not handled by (unfocused) views straight to UnityPlayer

@OverridepublicbooleanonKeyUp(intkeyCode,KeyEventevent){returnmUnityPlayer.injectEvent(event);}

@OverridepublicbooleanonKeyDown(intkeyCode,KeyEventevent){returnmUnityPlayer.injectEvent(event);}

@OverridepublicbooleanonTouchEvent(MotionEventevent){returnmUnityPlayer.injectEvent(event);}

/*API12*/publicbooleanonGenericMotionEvent(MotionEventevent){returnmUnityPlayer.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

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

最后编辑:2016-05-24作者:雨松MOMO

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

捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值