Embedded Unity3D view (3D model display) and androidunity3d in ANDROID applications

Source: Internet
Author: User

Embedded Unity3D view (3D model display) and androidunity3d in ANDROID applications

Reprint please indicate this article from the blog of the big glutinous rice (http://blog.csdn.net/a396901990), thank you for your support!

Effect display:


 



Opening nonsense:

My current Team needs a person to introduce a knowledge point or a new technology every week. It was my turn this week. Since I only worked for one year, I felt a little dead when I spoke to the old birds. So I am going to introduce a new technology.

Since I learned Unity3D for a while in college, the technology I want to introduce is it, but what I do now is application development. I cannot make a small game to demonstrate it to you. So what I think is simple and intuitive, and what I can actually use is to display 3D models in Android apps. For example, the 3D model of the product is displayed directly when the product is displayed, rather than an image. The effect should be very good (OpenGL should also be able to do it ).

After the idea was set, I found that the Unity3D content I learned in college was basically forgotten. Although sometimes there are Unity3D articles that I would like to open, I still have to learn it again. I remember reading a blog called Yu Song MOMO when I was studying Unity3D. At that time, I was young and ignorant. If I couldn't find a direction, I sent an email to Yu songda to ask questions about how to study and play games at the university, as a result, I became more lost and went on to learn android... Go far again... So I found his blog and read all the articles in the basic section of Unity3D.

However, his blog shows how to call Android in Unity3D. What I want to do is to call Unity3D in Android and embed Unity3D In the ANDROID view. Finally, I spent a lot of effort to make this Demo.


Preparations:

The following is my summary process to make the ideas of this article clearer:

1. Android-side code can be developed in Eclipse (Android studio is not tested and should be fine)

2. Unity3D code should be developed in Unity

3. Android and Unity3D terminals, both sides need to add some code so that it can be associated with interaction.

4. Compile the Android code into a jar file and add it to the Unity as a plug-in.

5. Build the entire project into an apk file in Unity and install it on your mobile phone or simulator to run it.

This article mainly describes 1, 2, and 3. For 17th, we suggest you read 18th and of the Unity blog of Yusong MOMO.


UnityPlay:

Before writing the Android and Unity3d code, you must first understand the UnityPlay class that can make the two parts interact.

In my opinion, UnityPlay is an interface class provided by Unity for external interaction.

Why is it "personal understanding "? I have to crack down on this. There are no related APIs and documents on the TMD official website. (If anyone can find me a copy, I will scold myself ).

When associating Android, you can find the UnityPlay and related jar packages from the following address:Unity installation path \ Editor \ Data \ PlaybackEngines \ androidplayer \ binIn the bin folder, there is a jar file named classes. jar, which is what we want.

In the bin directory, there is a src file, and three classes are clicked to the end: UnityPlayerActivity. java, UnityPlayerProxyActivity. java, and UnityPlayerNativeActivity. java. There is only one line of code after the first two opens. The UnityPlayerActivity and UnityPlayerProxyActivity both inherit from UnityPlayerNativeActivity. The UnityPlayerNativeActivity contains code, and I guess this is the source code of UnityPlayerNativeActivity.

I only found this one for UnityPlay, So I posted all the code in UnityPlayerNativeActivity. If there is something wrong with my annotation, I hope you can correct it.

/*** UnityPlayerActivity and UnityPlayerProxyActivity all inherit from UnityPlayerNativeActivity * And UnityPlayerNativeActivity inherit from NativeActivity * define some callback methods with the same lifecycle as ANDROID, this parameter is left to the custom Activity subclass for rewriting. */Public class UnityPlayerNativeActivity extends NativeActivity {// reference of UnityPlayer, and we cannot change the name of the referenced variable. It is referenced by the native code protected UnityPlayer mUnityPlayer; protected void onCreate (Bundle savedInstanceState) {requestWindowFeature (Window. FEATURE_NO_TITLE); super. onCreate (savedInstanceState); // sets the display window parameter getWindow (). takeSurface (null); setTheme (android. r. style. theme_NoTitleBar_Fullscreen); getWindow (). setFormat (PixelFormat. RGB_565); // create an UnityPlayer object and assign a value to the global reference variable mUnityPlayer = new UnityPlayer (this); // set some parameters for 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. The init () method needs to be called before attaching the view to layout. It will call native codemUnityPlayer. init (glesMode, trueColor8888); // you can obtain the View of Unity from UnityPlayer. playerView = mUnityPlayer. getView (); // loads the Unity View to the root view. setContentView (playerView); // obtains the focus playerView for the Unity view. requestFocus ();} protected void onDestroy () {// call UnityPlayer when Activity ends. the quit () method that uninstalls the previously called native codemUnityPlayer. quit (); super. onDestroy () ;}// the following methods are ANDROID-related callback methods. Ensure that when ANDROID executes the corresponding method, UnityPlayer also needs to call the corresponding method 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 );}}
After reading this class, you can see why the UnityPlayerActivity class is inherited in the Custom Activity. After that, you only need to override onCreate and call super. after the onCreate () method, the Unity3D view is automatically displayed without any other code. Because the code for initializing the Unity view is implemented in the UnityPlayerNativeActivity parent class.

ANDROID code:

When writing ANDROID code, you must import the jar package provided by Unity3D to us. The location of the jar package is described above. Add the jar package to buildpath.

To interact with Unity, we cannot inherit the Activity that ANDROID provides to us. We need to inherit the Activity class provided by Unity introduced in the jar package. There are three in total:

UnityPlayerActivity, UnityPlayerProxyActivity, and UnityPlayerNativeActivity. I don't know the specific difference, because there is no documentation, no API, no source code (here I despise it again ). Just now we have read the UnityPlayerNativeActivity code (although it is very short, but I think this is the source code). We know that UnityPlayerActivity and UnityPlayerProxyActivity are all subclasses of it, and the final parent class is NativeActivity. Therefore, inheriting the outermost subclass provided by Unity is the best choice. Here I chose UnityPlayerActivity. Because the name is the simplest, I think all the encapsulated classes should be encapsulated.

Public class MainActivity extends UnityPlayerActivity {private Button topButton; private Button bottomButton; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // set test as our root layout setContentView (R. layout. test); // Through the source code analysis, we know that mUnityPlayer is a global reference variable and has been set in the parent class, so you can use it directly to View playerView = mUnityPlayer. getView (); // Add the Unity View to the parent container we have prepared for it. LinearLayout ll = (LinearLayout) findViewById (R. id. unityViewLyaout); ll. addView (playerView); // The above button sets the listener topButton = (Button) findViewById (R. id. topButton); topButton. setOnClickListener (new View. onClickListener () {@ Overridepublic void onClick (View v) {// send a message to the Unity end. The first parameter of this function is the class object for receiving messages, the second class object uses the method of receiving messages, and the third parameter is the transmitted message // so the following meaning is: Call the Previous method under Main Camera, the message sent is empty. unitySendMessage ("Main Camera", "Previous", "") ;}}); // set the listener bottomButton = (button) findViewById (R. id. bottomBtn); bottomButton. setOnClickListener (new View. onClickListener () {@ Overridepublic void onClick (View v) {// call the Next method under Main Camera. The message sent is empty. unitySendMessage ("Main Camera", "Next ","");}});}}

Finally, let's take a look at the layout file on the Android end. The layout is very simple. There is a button between the top and bottom, and the center of the two buttons is the Unity view.

<?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>
The Android code is very simple. The only difficulty was the use of UnityPlayerActivity and UnityPlayer, which took me several days to complete, I don't know why the official website does not provide a document or API (or I may be too frustrated to find it ...)

Unity3D code:

Let's take a look at my project structure:


JavaScript stores scripts.

Models stores some free model files that I downloaded in Assert Store.

Plugins is my Android project. For details, refer to the online tutorial (Here we recommend the 17th articles of Yu songda)

Prefab I am the premade body defined after model Adjustment

In this scenario, I only have one camera and one direct light. Bind the script to the camera, and then add the five preset models that have been adjusted to the corresponding objects of the script.


The following is the script code. The rotation and scaling of the model are directly composed of the code in an article by Yusong MOMO, which is then added with some logic in this example.

# Pragma strict // five models are imported from the external var car: GameObject; var helicopter: GameObject; var suv: GameObject; var plane: GameObject; var tank: GameObject; // model array subscript private var index: int; // model array private var models: GameObject []; // The current model object private var mCurrentGameObject: GameObject; /*************************************** * ** // ** variables under the split line are used to control rotation and scaling of the touch gesture lens *//******************* * ********************* // The scaling factor var distance = 10.0; // left and right sliding speed var xSpeed = 250.0; var ySpeed = 120.0; // scaling restriction coefficient var yMinLimit =-20; var yMaxLimit = 80; // The camera position var x = 0.0; var y = 0.0; // record the last Mobile Phone Touch position to determine whether the user is in the left zoom in or zoom out gesture private var oldPosition1: Vector2; private var oldPosition2: Vector2; function Start () {// initialize the model Array index = 0; models = new GameObject [5]; models [0] = car; models [1] = helicopter; models [2] = suv; models [3] = plane; models [4] = tank; // clone an initial model object mCurrentGameObject = Instantiate (models [index], Vector3 (0, 0), Quaternion. euler (-20, 0, 0); // initialize the lens parameter var angles = transform. eulerAngles; x = angles. y; y = angles. x;} function Update () {// determines the number of touch points. if (Input. touchCount = 1) {// The touch type is mobile touch if (Input. getTouch (0 ). phase = TouchPhase. moved) {// calculate the X and Y positions x + = Input based on the touch point. getAxis ("Mouse X") * xSpeed * 0.02; y-= Input. getAxis ("Mouse Y") * ySpeed * 0.02;} // determines the number of touch points. if (Input. touchCount> 1) {// The first two finger touch types are all moving touch if (Input. getTouch (0 ). phase = TouchPhase. moved | Input. getTouch (1 ). phase = TouchPhase. moved) {// calculate the position of the current two-point touch point var tempPosition1 = Input. getTouch (0 ). position; var tempPosition2 = Input. getTouch (1 ). position; // if the function returns a scaled-in value, the false value is returned. if (isEnlarge (oldPosition1, oldPosition2, tempPosition1, tempPosition2 )) {// After the amplification factor is greater than 3, you cannot zoom in. // The data here is adjusted based on the model in my project. You can modify if (distance> 3) by yourself) {distance-= 0.5 ;}} else {// The data here is adjusted according to the model in my project, you can modify if (distance <18.5) {distance + = 0.5 ;}/// back up the last touch point location, which is used to compare oldPosition1 = tempPosition1; oldPosition2 = tempPosition2 ;}}// if the function returns a zoom-in value, the false value is the zoom-out function isEnlarge (oP1: Vector2, oP2: Vector2, nP1: Vector2, nP2: Vector2 ): boolean {// The function transmits the position of the last two points of touch and the position of the two points of this touch to calculate the user's gesture 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) {// zoom-In gesture return true;} else {// zoom-out gesture return false;} // The Update method enters here after the call ends and calculates the position of the camera reset function LateUpdate () {// mCurrentGameObject is our current model object. if (mCurrentGameObject. transform) {// reset the camera position 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) ;}// when you press next in android, the Next model function next () {index = index + 1 is displayed; if (index> models. length-1) {index = 0;} Debug. log ("next"); // Destroy the current object Destroy (mCurrentGameObject); // create a new model object mCurrentGameObject = Instantiate (models [index]);} // when previous is pressed in android, the Previous model function previous () {index = index-1 is displayed; if (index <0) {index = models. length-1;} Debug. log ("previous"); // Destroy the current object Destroy (mCurrentGameObject); // create a new model object mCurrentGameObject = Instantiate (models [index]);}

Finally, Build the project into an APK file in Unity3D, and then run it on the mobile phone or simulator (if the mobile phone or simulator is connected to Eclipse, log can be played to facilitate debugging and troubleshooting ).

The Code Demo is attached:

The Unity code is too big, so I uploaded the Android and Unity code and the apk file to Baidu cloud.

Click to download the code


Conclusion:

When I first went to college, I dreamed of playing games after graduation. But when I volunteered, I chose java. Later I realized that java was not suitable for playing games. Later I learned c ++ by myself, openGL, and later I watched Unity3D, but I didn't stick to it all. In college, I played wow with my classmates every day. As a result, after graduation, I found that the game-related things were not learned at all, in addition, Dalian does not have a game development job. Although I really want to try it in Beijing, it was too troublesome to go to Beijing for an internship and may not be able to find it, so I directly found an Android development in Dalian and gave up my original dream. However, I still want to go to Beijing next year to see if I can find a game development job. In the middle of this year, I will mainly learn Android and Java, and I will take a look at graphics and mathematical knowledge for the rest of the year, I don't know what I learned when I was in college, because now I know that programming is basically generic, so I should learn something first.




How does unity3d import 3d models?

Max or maya exports the model to the. fbx or. obj file (if there is no animation, obj will work)
Drag the file to unity3d.

Unity3d Model Animation

The usage of animator is different from that of animation. As shown in the figure below, no animator controller is set. Check the usage of animator or use legecy to use the animation component on the rig page.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.