如何将unity模型导入android程序中

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将unity模型导入android程序中相关的知识,希望对你有一定的参考价值。

 1.android端代码可以在Eclipse中开发(AndroidStudio没有试,应该也可以)

  2.Unity3D端代码要在Unity中开发

  3.Android和Unity3D端,两边都需要加入一些代码从而可以使之关联交互。

  4.将Android端代码编译成jar文件以插件形式放入到Unity端中

  5.在Unity中将整个项目Build成apk文件,然后安装到手机或模拟器里运行

  本文主要讲解1,2,3。对于4,5建议大家去看雨松MOMO的Unity博客的第17篇和第18篇。

  UnityPlay:

  在编写Android端和Unity3d端代码前,有必要先了解一下可以使两部分交互的类UnityPlay。

  个人理解UnityPlay是个Unity提供给外部交互的一个接口类。

  为什么是“个人理解”?这我不得不爆粗口了,TMD官网根本就没有相关的API和文档(如果大家有谁找到一定给我来一份,就当我骂自己了)。

  在关联Android时,想拿到UnityPlay以及相关类的jar包可以从下面的地址找到:Unity安装路径\Editor\Data\PlaybackEngines\androidplayer\bin在bin文件夹下有一个classes.jar的jar文件,它就是我们想要的。

  而在bin同目录下有一个src文件,点击到最后有3个类,分别是UnityPlayerActivity.java,UnityPlayerProxyActivity.java,UnityPlayerNativeActivity.java。前两个打开个后只有一行代码,说的是UnityPlayerActivity和UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity。而打开UnityPlayerNativeActivity中居然有代码,而且我估计这应该是UnityPlayerNativeActivity的源码。

  由于关于UnityPlay的资料我只找到这么一个,所以我把UnityPlayerNativeActivity中的代码都贴出来,如果我注解有不对的地方希望大家指正。

  /**
  * UnityPlayerActivity,UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity
  * 而UnityPlayerNativeActivity继承自NativeActivity
  * 在该类里定义了一些和ANDROID生命周期相同的回调方法,留给自定义的Activity子类重写。
  */
  public class UnityPlayerNativeActivity extends NativeActivity
  
  //UnityPlayer的引用,并且我们不能改变这个引用变量的名字,它被native code所引用
  protected UnityPlayer mUnityPlayer;

  protected void onCreate (Bundle savedInstanceState)
  
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  super.onCreate(savedInstanceState);
  // 设置显示窗口参数
  getWindow().takeSurface(null);
  setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
  getWindow().setFormat(PixelFormat.RGB_565);

  // 创建一个UnityPlayer对象,并赋值给全局的引用变量
  mUnityPlayer = new UnityPlayer(this);
  //为UnityPlayer设置一些参数
  if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
  getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
  WindowManager.LayoutParams.FLAG_FULLSCREEN);

  int glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1);
  boolean trueColor8888 = false;
  // UnityPlayer.init()方法需要在将view附加到layout之前调用。它将会调用native code
  mUnityPlayer.init(glesMode, trueColor8888);

  // 从UnityPlayer中获取到Unity的View视图
  View playerView = mUnityPlayer.getView();
  // 将Unity视图加载到根视图上
  setContentView(playerView);
  // 使Unity视图获取焦点
  playerView.requestFocus();
  
  protected void onDestroy ()
  
  // 当Activity结束的时候调用UnityPlayer.quit()方法,它会卸载之前调用的native code
  mUnityPlayer.quit();
  super.onDestroy();
  

  // 下面几个方法都是ANDROID相关回调方法,确保在ANDROID执行相应方法时UnityPlayer也需调用相应方法
  protected void onPause()
  
  super.onPause();
  mUnityPlayer.pause();
  
  protected void onResume()
  
  super.onResume();
  mUnityPlayer.resume();
  
  
  public void onConfigurationChanged(Configuration newConfig)
  
  super.onConfigurationChanged(newConfig);
  mUnityPlayer.configurationChanged(newConfig);
  
  public void onWindowFocusChanged(boolean hasFocus)
  
  super.onWindowFocusChanged(hasFocus);
  mUnityPlayer.windowFocusChanged(hasFocus);
  
  public boolean dispatchKeyEvent(KeyEvent event)
  
  if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
  return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);
  return super.dispatchKeyEvent(event);
  
  
  看完这个类后就知道了为什么在自定义的Activity中继承了UnityPlayerActivity等类以后,只要重写了onCreate并调用super.onCreate()方法后不需要任何其他的代码就会自动的显示出Unity3D的视图。因为初始化Unity视图的代码都在UnityPlayerNativeActivity父类中实现了。

  ANDROID端代码:

  在写ANDROID代码的时候,一定要导入Unity3D提供给我们的jar包,jar包的位置我在上面说了。引入jar包加入到buildpath中这些最基本的我就不多说了。

  要想和Unity交互,我们就不能继承ANDROID提供给我们的Activity,我们需要继承刚才jar包中引入的Unity提供的Activity类,一共有这么3个:

  UnityPlayerActivity,UnityPlayerProxyActivity,UnityPlayerNativeActivity。具体区别不知道,因为没有文档,没有API,没有源码(这里再次鄙视一下)。刚才我们看过UnityPlayerNativeActivity的代码(虽然很短,但我觉得这个就是源码),知道UnityPlayerActivity,UnityPlayerProxyActivity都是它的子类,而且最终父类为NativeActivity。所以我们继承Unity提供的最外层的子类是最好的选择,我这里选择的是UnityPlayerActivity,因为名字最简单,觉得该封装的都应该封装好了。

  public class MainActivity extends UnityPlayerActivity

  private Button topButton;
  private Button bottomButton;

  @Override
  protected void onCreate(Bundle savedInstanceState)
  super.onCreate(savedInstanceState);

  // 设置test为我们的根布局
  setContentView(R.layout.test);

  // 通过刚才的源码分析,知道mUnityPlayer为一个全局的引用变量,而且已经在父类中设置好了,所以直接拿来用就可以了
  View playerView = mUnityPlayer.getView();
  // 将Unity的视图添加到我们为其准备的父容器中
  LinearLayout ll = (LinearLayout) findViewById(R.id.unityViewLyaout);
  ll.addView(playerView);

  // 上面的button设置监听器
  topButton = (Button) findViewById(R.id.topButton);
  topButton.setOnClickListener(new View.OnClickListener()

  @Override
  public void onClick(View v)
  //发送消息给Unity端,该函数第一个参数为接受消息的类对象,第二个该类对象用接受消息的方法,第三个参数为传递的消息
  //所以下面的意思就为:调用Main Camera下面的Previous方法,传送的消息为空
  UnityPlayer.UnitySendMessage("Main Camera","Previous","");
  
  );

  // 为下面的button设置监听器
  bottomButton = (Button) findViewById(R.id.bottomBtn);
  bottomButton.setOnClickListener(new View.OnClickListener()

  @Override
  public void onClick(View v)
  //调用Main Camera下面的Next方法,传送的消息为空
  UnityPlayer.UnitySendMessage("Main Camera","Next","");
  
  );
  
  
  最后看一下Android端的布局文件,布局很简单,上下各有一个button按钮,两个按钮中间是Unity的视图。

  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >

  <Button
  android:id="@+id/topButton"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentTop="true"
  android:text="PREVIOUS" />

  <LinearLayout
  android:id="@+id/unityViewLyaout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_above="@+id/bottomBtn"
  android:layout_below="@+id/topButton"
  android:orientation="horizontal" >
  </LinearLayout>

  <Button
  android:id="@+id/bottomBtn"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:text="NEXT" />

  </RelativeLayout>
  Android端的代码就介绍完了,很简单。唯一的难点就是UnityPlayerActivity和UnityPlayer的使用。
参考技术A   准备工作:

  下面是我总结的流程,目的是使本文思路更加清晰一些:

  1.Android端代码可以在Eclipse中开发(AndroidStudio没有试,应该也可以)

  2.Unity3D端代码要在Unity中开发

  3.Android和Unity3D端,两边都需要加入一些代码从而可以使之关联交互。

  4.将Android端代码编译成jar文件以插件形式放入到Unity端中

  5.在Unity中将整个项目Build成apk文件,然后安装到手机或模拟器里运行

  本文主要讲解1,2,3。对于4,5建议大家去看雨松MOMO的Unity博客的第17篇和第18篇。

  UnityPlay:

  在编写Android端和Unity3d端代码前,有必要先了解一下可以使两部分交互的类UnityPlay。

  个人理解UnityPlay是个Unity提供给外部交互的一个接口类。

  为什么是“个人理解”?这我不得不爆粗口了,TMD官网根本就没有相关的API和文档(如果大家有谁找到一定给我来一份,就当我骂自己了)。

  在关联Android时,想拿到UnityPlay以及相关类的jar包可以从下面的地址找到:Unity安装路径\Editor\Data\PlaybackEngines\androidplayer\bin在bin文件夹下有一个classes.jar的jar文件,它就是我们想要的。

  而在bin同目录下有一个src文件,点击到最后有3个类,分别是UnityPlayerActivity.java,UnityPlayerProxyActivity.java,UnityPlayerNativeActivity.java。前两个打开个后只有一行代码,说的是UnityPlayerActivity和UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity。而打开UnityPlayerNativeActivity中居然有代码,而且我估计这应该是UnityPlayerNativeActivity的源码。

  由于关于UnityPlay的资料我只找到这么一个,所以我把UnityPlayerNativeActivity中的代码都贴出来,如果我注解有不对的地方希望大家指正。

  /**
  * UnityPlayerActivity,UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity
  * 而UnityPlayerNativeActivity继承自NativeActivity
  * 在该类里定义了一些和ANDROID生命周期相同的回调方法,留给自定义的Activity子类重写。
  */
  public class UnityPlayerNativeActivity extends NativeActivity
  
  //UnityPlayer的引用,并且我们不能改变这个引用变量的名字,它被native code所引用
  protected UnityPlayer mUnityPlayer;

  protected void onCreate (Bundle savedInstanceState)
  
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  super.onCreate(savedInstanceState);
  // 设置显示窗口参数
  getWindow().takeSurface(null);
  setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
  getWindow().setFormat(PixelFormat.RGB_565);

  // 创建一个UnityPlayer对象,并赋值给全局的引用变量
  mUnityPlayer = new UnityPlayer(this);
  //为UnityPlayer设置一些参数
  if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
  getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
  WindowManager.LayoutParams.FLAG_FULLSCREEN);

  int glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1);
  boolean trueColor8888 = false;
  // UnityPlayer.init()方法需要在将view附加到layout之前调用。它将会调用native code
  mUnityPlayer.init(glesMode, trueColor8888);

  // 从UnityPlayer中获取到Unity的View视图
  View playerView = mUnityPlayer.getView();
  // 将Unity视图加载到根视图上
  setContentView(playerView);
  // 使Unity视图获取焦点
  playerView.requestFocus();
  
  protected void onDestroy ()
  
  // 当Activity结束的时候调用UnityPlayer.quit()方法,它会卸载之前调用的native code
  mUnityPlayer.quit();
  super.onDestroy();
  

  // 下面几个方法都是ANDROID相关回调方法,确保在ANDROID执行相应方法时UnityPlayer也需调用相应方法
  protected void onPause()
  
  super.onPause();
  mUnityPlayer.pause();
  
  protected void onResume()
  
  super.onResume();
  mUnityPlayer.resume();
  
  
  public void onConfigurationChanged(Configuration newConfig)
  
  super.onConfigurationChanged(newConfig);
  mUnityPlayer.configurationChanged(newConfig);
  
  public void onWindowFocusChanged(boolean hasFocus)
  
  super.onWindowFocusChanged(hasFocus);
  mUnityPlayer.windowFocusChanged(hasFocus);
  
  public boolean dispatchKeyEvent(KeyEvent event)
  
  if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
  return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);
  return super.dispatchKeyEvent(event);
  
  
  看完这个类后就知道了为什么在自定义的Activity中继承了UnityPlayerActivity等类以后,只要重写了onCreate并调用super.onCreate()方法后不需要任何其他的代码就会自动的显示出Unity3D的视图。因为初始化Unity视图的代码都在UnityPlayerNativeActivity父类中实现了。

  ANDROID端代码:

  在写ANDROID代码的时候,一定要导入Unity3D提供给我们的jar包,jar包的位置我在上面说了。引入jar包加入到buildpath中这些最基本的我就不多说了。

  要想和Unity交互,我们就不能继承ANDROID提供给我们的Activity,我们需要继承刚才jar包中引入的Unity提供的Activity类,一共有这么3个:

  UnityPlayerActivity,UnityPlayerProxyActivity,UnityPlayerNativeActivity。具体区别不知道,因为没有文档,没有API,没有源码(这里再次鄙视一下)。刚才我们看过UnityPlayerNativeActivity的代码(虽然很短,但我觉得这个就是源码),知道UnityPlayerActivity,UnityPlayerProxyActivity都是它的子类,而且最终父类为NativeActivity。所以我们继承Unity提供的最外层的子类是最好的选择,我这里选择的是UnityPlayerActivity,因为名字最简单,觉得该封装的都应该封装好了。

  public class MainActivity extends UnityPlayerActivity

  private Button topButton;
  private Button bottomButton;

  @Override
  protected void onCreate(Bundle savedInstanceState)
  super.onCreate(savedInstanceState);

  // 设置test为我们的根布局
  setContentView(R.layout.test);

  // 通过刚才的源码分析,知道mUnityPlayer为一个全局的引用变量,而且已经在父类中设置好了,所以直接拿来用就可以了
  View playerView = mUnityPlayer.getView();
  // 将Unity的视图添加到我们为其准备的父容器中
  LinearLayout ll = (LinearLayout) findViewById(R.id.unityViewLyaout);
  ll.addView(playerView);

  // 上面的button设置监听器
  topButton = (Button) findViewById(R.id.topButton);
  topButton.setOnClickListener(new View.OnClickListener()

  @Override
  public void onClick(View v)
  //发送消息给Unity端,该函数第一个参数为接受消息的类对象,第二个该类对象用接受消息的方法,第三个参数为传递的消息
  //所以下面的意思就为:调用Main Camera下面的Previous方法,传送的消息为空
  UnityPlayer.UnitySendMessage("Main Camera","Previous","");
  
  );

  // 为下面的button设置监听器
  bottomButton = (Button) findViewById(R.id.bottomBtn);
  bottomButton.setOnClickListener(new View.OnClickListener()

  @Override
  public void onClick(View v)
  //调用Main Camera下面的Next方法,传送的消息为空
  UnityPlayer.UnitySendMessage("Main Camera","Next","");
  
  );
  
  
  最后看一下Android端的布局文件,布局很简单,上下各有一个button按钮,两个按钮中间是Unity的视图。

  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >

  <Button
  android:id="@+id/topButton"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentTop="true"
  android:text="PREVIOUS" />

  <LinearLayout
  android:id="@+id/unityViewLyaout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_above="@+id/bottomBtn"
  android:layout_below="@+id/topButton"
  android:orientation="horizontal" >
  </LinearLayout>

  <Button
  android:id="@+id/bottomBtn"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:text="NEXT" />

  </RelativeLayout>
  Android端的代码就介绍完了,很简单。唯一的难点就是UnityPlayerActivity和UnityPlayer的使用,就这两个破玩意花了我好几天的时间,很简单的东西不知道为什么官方不给个文档或者API(也可能我太挫没找到。。。)
转载

以上是关于如何将unity模型导入android程序中的主要内容,如果未能解决你的问题,请参考以下文章

unity项目导入到android studio

Vroid怎么导入unity

Unity3D中如何将导入的资源包删除

Unity Shaders and Effects Cookbook (7-3) 在地形中使用顶点颜色做混合

unity人物模型可以导入到ue5吗

如何将 .fbx 纹理完全导入 Unity