本篇文章主要是展示一般Android与Unity混合开发的过程,并且说一些本人在混合开发中踩到的奇怪的坑,如果有错误欢迎大家指正!
此外本文除了通信不会在代码进行解释,需要一定的Unity和Android基础~
一般来说Android内嵌Unity开发主要是把Unity作为Android界面的一部分进行交互或者内容展示,主要是以Android为主体框架。
现在普遍使用的把Unity塞进Android里的方法主要有两个:
先在安卓创建项目,之后进行一系列配置,再创建Unity项目,开发之后export,把jar包塞进Android然后再进行一系列配置,再二次开发先在Unity创建项目,进行开发之后配置然后export出Android项目,直接在Android Studio中打开项目,进行配置之后可以二次开发本人觉得第二种方法更加方便,而且对于我(Android基础比较薄弱)更容易理解,所以这次就以第二种方法为例子,展示一下整个过程。
Unity相关
首先是简易弄一个Unity项目:
主要是添加了一个手势识别移动相机的脚本,其中用到了Unity自带的TouchAPI,这里有一个坑是我踩到的,现在也没有解决,下面会提到。
然后几个Text展示与Android的交互信息,也有展示Touch的信息的。具体的函数绑定就不过多解释了。
这里分享一下我写的相机移动的脚本,最下面的函数主要是与AndroidHybrid的时候Unity的TouchAPI有关,后面会提到。
使用的相机移动脚本
主要的交互代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HybridTest : MonoBehaviour
{
private HybridTest instance;
public HybridTest GetInstance()
{
instance = this;
if (instance)
{
return instance;
}
return null;
}
public Text textShow;
public Text countShow;
public int count = 0;
AndroidJavaClass jc;
AndroidJavaObject jo;
public int layoutHeight;
public int layoutWidth;
public Text textSize;
private void Start()
{
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
GetLayoutSize();
}
public void Add()
{
int sum = jo.Call<int>("Add", 2, 3);
textShow.text = sum.ToString();
}
//调用安卓的Toast
public void CallAndroidShowToast()
{
jo.Call("ShowToast", "Receive from Unity Successfully!");
}
//给Android调用的
public void GetMessageFromAndroid(string content)
{
textShow.text = content;
count++;
countShow.text = count.ToString();
}
//Unity先发送一个拿到Android layout大小的申请,然后安卓再发送回来
public void GetLayoutSize()
{
jo.Call("ReturnScreenSize", "");
}
public void SetLayoutSize(string content)
{
layoutWidth = int.Parse(content.Split('/')[0]);
layoutHeight = int.Parse(content.Split('/')[1]);
Debug.Log("unity get width" + layoutWidth);
Debug.Log("unity get height" + layoutHeight);
textSize.text = layoutWidth.ToString() + "/" + layoutHeight.ToString();
}
}
Unity调用Android
可以看到在Start中实例化了两个东西,一个是jc一个是jo,具体就是Unity拿到安卓的UnityClass和Activity要用到的接口,是Unity发送Message给Android的关键。
然后以下两个函数就是负责调用Android中的函数,具体结构就是:
jo.Call<如果Android中有返回的值,值的类型>( “Android中的函数名,String类” , 要发送的参数,类型都可);
可以参考例子
下面这两个函数就是给Android调用的,主要是传回Android中Unity的Layout大小,用于交互范围判断,后面也会提到:
导出的时候记得添加Scene并且勾选Export,记得选择对应的安卓最高最低版本就ok了:
Android相关
直接用Android Studio打开Unity导出的项目,基础结构应该如下:
其中UnityPlayerActivity这个类是最重要的,负责Unity在Android中的显示和生命周期等等,如果没有二次开发的需求可以不用理会它。
我们当前的目标是在Android中弄一个FrameLayout用于展示Unity的内容,因为大小会自己适配,所以我们只用考虑FrameLayout的大小就好了。
ToastUtils小工具
新建一个MainActivity继承UnityPlayerActivity,然后就开始 *** 作啦,先整一个看起来还可以的布局:
然后再MainActivity中绑定Layout并且写一些和Unity交互的函数:
package com.unity3d.player;
import android.app.ActionBar;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends UnityPlayerActivity{
FrameLayout unityLayout;
int dpHeight;
int dpWidth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUnityPlayer = new UnityPlayer(this);
setContentView(R.layout.layout_main);
unityLayout = (FrameLayout) findViewById(R.id.unity_layout);
ActionBar.LayoutParams layoutParams = new ActionBar.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
unityLayout.addView(mUnityPlayer.getView(), 0, layoutParams);
//绑定按钮发送消息给Unity
Button buttonSendToUnity = (Button) findViewById(R.id.btn_sendSize);
buttonSendToUnity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
GetLayoutSize();
Log.i("toUnity", String.valueOf(dpHeight));
Log.i("toUnity", String.valueOf(dpWidth));
callUnityTest("MessageManager","SetLayoutSize",dpWidth + "/" + dpHeight);
}
});
Button buttonSendSize = (Button) findViewById(R.id.btn_toUnity);
buttonSendSize.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
callUnityTest("MessageManager","GetMessageFromAndroid","Receive from Android successfully!");
}
});
}
//Unity调用的显示Toast方法
public void ShowToast(final String mStr2Show){
runOnUiThread(new Runnable() {
@Override
public void run() {
ToastUtils.show(getApplicationContext(),"Receive from Unity successfully!");
}
});
}
public void GetLayoutSize(){
// DisplayMetrics metrics =new DisplayMetrics();
// getWindowManager().getDefaultDisplay().getMetrics(metrics);
// int dpi = metrics.densityDpi;
dpWidth = unityLayout.getMeasuredWidth();
dpHeight = unityLayout.getMeasuredHeight();
//callUnityTest("MessageManager","SetLayoutSize",res);
}
public void ReturnScreenSize(){
GetLayoutSize();
//Log.i("SendToUnity", String.valueOf(dpWidth));
//Log.i("SendToUnity", String.valueOf(dpHeight));
String res = "";
res += dpWidth;
res += "/";
res += dpHeight;
callUnityTest("MessageManager","SetLayoutSize",res);
}
// 第一个参数是unity中的对象名字,记住是对象名字,不是脚本类名
// 第二个参数是函数名
// 第三个参数是传给函数的参数
public void callUnityTest(String _objName , String _funcStr, String _content)
{
UnityPlayer.UnitySendMessage(_objName, _funcStr, _content);
}
}
按钮事件绑定就不多解释了,开头就先照着UnityPlayerActivity把Layout绑定,再写按钮的事件。
Android调用Unity这里我是把Unity调用安卓的方法封装了一下,不习惯的小伙伴可以直接用UnityPlayer.UnitySendMessage即可,具体格式如下:
// 第一个参数是unity中的对象名字,记住是对象名字,不是脚本类名
// 第二个参数是函数名
// 第三个参数是传给函数的参数
public void callUnityTest(String _objName , String _funcStr, String _content)
{
UnityPlayer.UnitySendMessage(_objName, _funcStr, _content);
}
可以发现参数是String类型,所以在Unity中接收的时候还要进行解析 *** 作,上面Unity中的代码也有示范。
Android中的两个按钮作用就是给Unity发送信息啦,这里我是弄了两个按钮,一个可以改变Unity中的计数,一个可以发送给Unity在Android中Layout的大小,具体实现可以看上面的代码。
这里要注意我在Unity中写了个交互范围的判断,所以在SendSize把Layout大小发给Unity之后Unity接收到了才能进行交互,直接CV的小伙伴要注意哦。
这里就是Unity调用Android然后展示Toast,要记得在Android中写:
不要忘记在Manifest中注册一下,并且把一进去的MAINActivity换成MainActivity:
然后就可以直接在Android Studio中连接设备进行测试啦!值得注意的是Unity中的Debug也可以在Android中的Logcat中Log出来,所以还是挺方便的。
因为是基于Touch实现的交互,所以后面就研究了一下,发现了就是在Android发送了Layout大小之后,在Unity的FramLayout中坐标是以FramLayout的左下角为原点,然后在FrameLayout中debug出来的TouchPosition都是正常的,但是在LinearLayout中点击的话,显示的坐标是Unity的FramLayout在MarginTop之前的坐标:
这样的话如果使用TouchPosition判断交互范围就很困难了,目前还没有想到什么好的解决方法,只能让Unity贴着上面了,如果各位大佬有什么解决方法希望能解答一下!谢谢!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)