美文网首页Unity教程合集Unity技术VR/AR分享
写给VR手游开发小白的教程:(五)Cardboard插件与An

写给VR手游开发小白的教程:(五)Cardboard插件与An

作者: 你的头好大 | 来源:发表于2017-08-30 09:55 被阅读24次

    原文地址:http://blog.csdn.net/mao_xiao_feng/article/details/52416439
    上篇已经把BaseVRDevice这个类解析了一下,紧接着,摆在我们眼前的问题是既然已经完成了VR设备的基类,那后续的子类必然会对基类做一个相应的扩展,以实现AndroidiOS设备所独有的功能。事实上AndroidBaseVRDevice这个类就完成了这些事情,学过android的人都知道一个app的运行最基本的就是Layout和Activity,一个控制前端一个控制后台,而我们本节所要介绍的这个类,就是在BaseVRDevice的基础上,增加了Android所特有的Java对象的创建和Activity的管理,这搭建了一个桥梁,允许我们将Unity和Android两个不同的平台进行通信和交互。

    AndroidBaseVRDevice.cs的代码如下,大家可以参照着看看

    #if UNITY_ANDROID
    
    using UnityEngine;
    using System.Collections.Generic;
    
    public abstract class AndroidBaseVRDevice : BaseVRDevice {
    protected AndroidJavaObject cardboardActivity;
    
    public override bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
    bool support = base.SupportsNativeDistortionCorrection(diagnostics);
    if (cardboardActivity == null) {
    diagnostics.Add("Cannot access Activity");
    }
    return support;
    }
    
    public override void Destroy() {
    if (cardboardActivity != null) {
    cardboardActivity.Dispose();
    cardboardActivity = null;
    }
    base.Destroy();
    }
    
    protected virtual void ConnectToActivity() {
    try {
    using (AndroidJavaClass player = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
    cardboardActivity = player.GetStatic<AndroidJavaObject>("currentActivity");
    }
    } catch (AndroidJavaException e) {
    cardboardActivity = null;
    Debug.LogError("Exception while connecting to the Activity: " + e);
    }
    }
    
    protected virtual bool CallActivityMethod(string name, params object[] args) {
    return CallObjectMethod(cardboardActivity, name, args);
    }
    
    protected virtual bool CallActivityMethod<T>(ref T result, string name, params object[] args) {
    return CallObjectMethod(ref result, cardboardActivity, name, args);
    }
    
    protected AndroidJavaObject Create(string className, params object[] args) {
    try {
    return new AndroidJavaObject(className, args);
    } catch (AndroidJavaException e) {
    Debug.LogError("Exception creating object " + className + ": " + e);
    return null;
    }
    }
    
    protected static bool CallObjectMethod(AndroidJavaObject jo, string name, params object[] args) {
    if (jo == null) {
    Debug.LogError("Object is null when calling method " + name);
    return false;
    }
    try {
    jo.Call(name, args);
    return true;
    } catch (AndroidJavaException e) {
    Debug.LogError("Exception calling method " + name + ": " + e);
    return false;
    }
    }
    
    protected static bool CallObjectMethod<T>(ref T result, AndroidJavaObject jo, string name,
    params object[] args) {
    if (jo == null) {
    Debug.LogError("Object is null when calling method " + name);
    return false;
    }
    try {
    result = jo.Call<T>(name, args);
    return true;
    } catch (AndroidJavaException e) {
    Debug.LogError("Exception calling method " + name + ": " + e);
    return false;
    }
    }
    }
    
    #endif
    

    来自CODE的代码片AndroidBaseVRDevice.cs

    /**************************************************************************************************************************************/

    代码的第一句就给我们摆了难题,AndroidJavaObject这个类看着像是Android的,但事实上它是Unity库里的一个类,见圣典:
    http://www.ceeger.com/Script/AndroidJavaObject/AndroidJavaObject.html
    发现这个类下,有一系列函数和一个构造方法static function AndroidJavaObject (className : string, params args : object[])
    这个构造方法很有趣,它有两个参数分别是1、指定的Java类名2、传递的参数
    为什么说他有趣?
    大家可以看一个例子
    //创建一个java.lang.String对象,持有该字符串"some string"function Start() {var jo = new AndroidJavaObject("java.lang.String", "some string");}

    这是摘自圣典的一个例子,我们通过构造函数将AndroidJavaObject实例化了以后,生成的居然不是AndroidJavaObject的实例而是其字符串参数java.lang.String对象的一个实例。这很神奇,因为我们通常所能认识到的是构造函数构造的一定是类本身,那为什么这里不是?

    事实上,我们构造出来的仍然是本身,只不过“看起来”不一样而已。什么是“看起来”不一样呢?
    从这里需要引申到Java中所有对象的祖先类,Object类,这里的AndroidJavaObject就是Object类的一个泛型,关于Object类的概念,给一个链接这里不再详述
    http://www.cnblogs.com/mengdd/archive/2013/01/03/2842809.html
    好了,现在Object作为泛型类,把AndroidJavaObject这个类作为参数来确定具体实例化哪个对象,而实例化哪个对象的问题,就由实例化的AndroidJavaObject类来解答了,所以说,不管是最终实例化的java.lang.String类,还是我们觉得应该实例化的AndroidJavaObject类,都是产自于Object类,它们事实上来源是相同的,而我们只是通过泛型这种手段来将Object对象做了个“变形”。
    理解了这一步,我们就知道AndroidJavaObject类在Unity中存在的意义了,它就像一座桥梁,将Java对象与远方的Unity中的对象联系起来。

    /**************************************************************************************************************************************/
    AndroidJavaClass player = new AndroidJavaClass("com.Unity3D.player.UnityPlayer"
    //同理AndroidJavaClass也是如此,只不过它联系了Java中的类和Unity中的类。需要说明的一点是,Class类没有公共构造方法,我们都知道类是对象的抽象,而Class是对Java中所有类的一个抽象,它保存的是一个Java类的元信息,负责类的类型标识问题而从不负责类的实例化问题。于是,我们知道AndroidJavaClass的实例得到的是指定的类型,而不是实例化的对象。附上圣典的介绍:
    http://www.ceeger.com/Script/AndroidJavaClass/AndroidJavaClass.html

    /**************************************************************************************************************************************/

    解决了这个问题,让我们接着往下
    using (AndroidJavaClass player = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    //这一步相当于在Java中引用了名为com.unity3d.player.UnityPlayer的库,而C#与Java互通上面已经说了,一句话就是C#中创建的Java对象需要用到添加到Java语言中的com.unity3d.player.UnityPlayer库中的操作,听起来有些拗口。

    cardboardActivity = player.GetStatic<AndroidJavaObject>("currentActivity");
    //然后我们接着调用AndroidJavaClass 类下的GetStatic.<FieldType>方法去获取当前的Activity,这句话如果在上一句之前是无法执行的,因为GetStatic.<FieldType>语句是Unity库里的语句,我们正是通过添加了com.unity3d.player.UnityPlayer库才使得该语句可用。说到这里又有人会问了,我们开头的using UnityEngine不是已经将Unity库导入进来了吗?其实using UnityEngine只是将Unity和C#联系起来,但是我们现在做的,是C#环境中,实现Android和Unity的通信,两者显然不一样。
    哈哈,这就是编程的魅力:无限的扩展性+严密的逻辑性!

    /**************************************************************************************************************************************/

    接下去调用对象方法的一些函数和Creat新的对象就不再详述了,无非就是用泛型实现对象内调用其他对象方法,相信大家都能看懂

    相关文章

      网友评论

        本文标题: 写给VR手游开发小白的教程:(五)Cardboard插件与An

        本文链接:https://www.haomeiwen.com/subject/nduzdxtx.html