ANDROID嵌入式应用Unity3D视图(画廊3D模型) (3)

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端的布局文件,布局非常easy,上下各有一个buttonbutton,两个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端的代码就介绍完了,非常easy。唯一的难点就是UnityPlayerActivity和UnityPlayer的使用,就这两个破玩意花了我好几天的时间,非常easy的东西不知道为什么官方不给个文档或者API(也可能我太挫没找到。。。



Unity3D端代码:

先看一下我的项目结构:

ANDROID嵌入式应用Unity3D视图(画廊3D模型)


JavaScript存放的是脚本

Models存放的是我在Assert Store中下载的免费的一些模型文件

Plugins下是我的Androidproject。详细做法參考网上教程(这里推荐雨松大神的第17篇)

Prefab我是调整模型后定义的预制体

在场景中。我仅仅有一个摄像机。和一个直射光。将脚本绑定到摄像机上。然后将之前调整好的5个预设模型加入到脚本的对应对象中。

ANDROID嵌入式应用Unity3D视图(画廊3D模型)


以下是脚本的代码,关于模型的旋转缩放是直接用了雨松MOMO的一篇文章中的代码。然后再加上了本例中的一些逻辑而组成的。

#pragma strict //5个模型,从外部传入 var car : GameObject; var helicopter : GameObject; var suv : GameObject; var plane : GameObject; var tank : GameObject; //模型数组下标 private var index : int; //模型数组 private var models : GameObject[]; //当前模型对象 private var mCurrentGameObject : GameObject; /******************************************/ /*切割线之下的变量用于触摸手势镜头控制旋转和缩放*/ /******************************************/ //缩放系数 var distance = 10.0; //左右滑动移动速度 var xSpeed = 250.0; var ySpeed = 120.0; //缩放限制系数 var yMinLimit = -20; var yMaxLimit = 80; //摄像头的位置 var x = 0.0; var y = 0.0; //记录上一次手机触摸位置推断用户是在左放大还是缩小手势 private var oldPosition1 : Vector2; private var oldPosition2 : Vector2; function Start () { //初始化模型数组 index = 0; models = new GameObject[5]; models[0] = car; models[1] = helicopter; models[2] = suv; models[3] = plane; models[4] = tank; //克隆一个初始模型对象 mCurrentGameObject = Instantiate(models[index], Vector3(0,0,0), Quaternion.Euler(-20,0,0)); //初始化镜头參数 var angles = transform.eulerAngles; x = angles.y; y = angles.x; } function Update () { //推断触摸数量为单点触摸 if(Input.touchCount == 1) { //触摸类型为移动触摸 if(Input.GetTouch(0).phase==TouchPhase.Moved) { //依据触摸点计算X与Y位置 x += Input.GetAxis("Mouse X") * xSpeed * 0.02; y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02; } } //推断触摸数量为多点触摸 if(Input.touchCount > 1 ) { //前两仅仅手指触摸类型都为移动触摸 if(Input.GetTouch(0).phase==TouchPhase.Moved||Input.GetTouch(1).phase==TouchPhase.Moved) { //计算出当前两点触摸点的位置 var tempPosition1 = Input.GetTouch(0).position; var tempPosition2 = Input.GetTouch(1).position; //函数返回真为放大。返回假为缩小 if(isEnlarge(oldPosition1,oldPosition2,tempPosition1,tempPosition2)) { //放大系数超过3以后不同意继续放大 //这里的数据是依据我项目中的模型而调节的。大家能够自己随意改动 if(distance > 3) { distance -= 0.5; } }else { //缩小洗漱返回18.5后不同意继续缩小 //这里的数据是依据我项目中的模型而调节的,大家能够自己随意改动 if(distance < 18.5) { distance += 0.5; } } //备份上一次触摸点的位置,用于对照 oldPosition1=tempPosition1; oldPosition2=tempPosition2; } } } //函数返回真为放大,返回假为缩小 function isEnlarge(oP1 : Vector2,oP2 : Vector2,nP1 : Vector2,nP2 : Vector2) : boolean { //函数传入上一次触摸两点的位置与本次触摸两点的位置计算出用户的手势 var leng1 =Mathf.Sqrt((oP1.x-oP2.x)*(oP1.x-oP2.x)+(oP1.y-oP2.y)*(oP1.y-oP2.y)); var leng2 =Mathf.Sqrt((nP1.x-nP2.x)*(nP1.x-nP2.x)+(nP1.y-nP2.y)*(nP1.y-nP2.y)); if(leng1 < leng2) { //放大手势 return true; }else { //缩小手势 return false; } } //Update方法一旦调用结束以后进入这里算出重置摄像机的位置 function LateUpdate () { //mCurrentGameObject为我们当前模型对象,缩放旋转的參照物 if (mCurrentGameObject.transform) { //重置摄像机的位置 y = ClampAngle(y, yMinLimit, yMaxLimit); var rotation = Quaternion.Euler(y, x, 0); var position = rotation * Vector3(0.0, 0.0, -distance) + mCurrentGameObject.transform.position; transform.rotation = rotation; transform.position = position; } } static function ClampAngle (angle : float, min : float, max : float) { if (angle < -360) angle += 360; if (angle > 360) angle -= 360; return Mathf.Clamp (angle, min, max); } // 当android中按下next,显示下一个模型 function Next () { index = index+1; if (index > models.Length-1) { index = 0; } Debug.Log("next"); // 摧毁当前对象 Destroy(mCurrentGameObject); // 建立新的模型对象 mCurrentGameObject = Instantiate(models[index]); } // 当android中按下previous,显示上一个模型 function Previous () { index = index-1; if (index < 0) { index = models.Length-1; } Debug.Log("previous"); // 摧毁当前对象 Destroy(mCurrentGameObject); // 建立新的模型对象 mCurrentGameObject = Instantiate(models[index]); }

最后就是在Unity3D中将projectBuild成APK文件,然后再手机或模拟器中执行(假设手机或模拟器连着Eclipse则能够打出log方便调试找错)。

最后附上代码Demo:

Unity端代码太大了,所以我就把Android端和Unity端代码还有而apk文件上传到百度云了。

代码点击下载


结束语:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzydjx.html