UnityからAndroidStudioにエクスポートプロジェクトでFragmentを使用する方法

2018-12-14 14:44:29

 UnityからAndroidStudio用にエクスポートされたプロジェクトは、UnityPlayerというViewクラスが貼り付けられたActivityが生成される。このActivityは特殊なものではないので、自由にカスタマイズすることができる。


 今回はこのUnityPlayerをFragmentに貼り付けることによって、Fragment上でUnityを表示させる部分を解説する。

Fragmentを使うために、ライブラリを追加

2018-12-14 14:49:53

build.gradleに以下の設定を追加する


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:appcompat-v7:28.0.0'
}


ライブラリのバージョンは、そのときに環境に合わせて変更すること

UnityPlayerActivityの基本クラスの入れ替え

2018-12-14 14:51:54

 ActivityにFragmentを管理する機能を持たせるため、基本クラスを以下のように書き換える


public class UnityPlayerActivity extends Activity
             ↓
public class UnityPlayerActivity extends AppCompatActivity


UnityPlayerActivityからUnityPlayerを取り出せるようにする

2018-12-14 15:06:08

クラス内に

public UnityPlayer getUnityPlayer(){
        return mUnityPlayer;
}

を追加

スタイルの変更

2018-12-14 15:01:23

style.xmlのパラメータを以下のように書き換える


<style name="UnityThemeSelector" parent="Theme.AppCompat.Light">


フラグメントの作成

2018-12-14 15:07:36

Fragmentを作成し、以下のコードを追加

R.id.unityはUnityPlayerを貼り付ける場所なので、Fragmentのレイアウトに場所を用意しておくこと
貼り付ける対象はFrameLayoutやLinnerLayoutなどで構わない

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        UnityPlayer unityPlayer = ((UnityPlayerActivity)getActivity()).getUnityPlayer();
        ViewGroup parent = (ViewGroup)unityPlayer.getParent();
        if(parent != null)
            parent.removeView(unityPlayer);
        ((FrameLayout)view.findViewById(R.id.unity)).addView(unityPlayer);
    }

レイアウトを普通に読み込ませる

2018-12-14 15:03:06

UnityPlayerActivity.javaのonCreateの書き換え


    @Override protected void onCreate(Bundle savedInstanceState)
    {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);

        mUnityPlayer = new UnityPlayer(this);
        setContentView(R.layout.activity_main); //新しいレイアウトを自分で作る

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(貼り付け先のID,new フラグメントラス名());
        ft.addToBackStack(null);
        ft.commit();
    }





動作確認

2018-12-14 15:14:39

 ここまで行うとFragment上にUnityのプログラムが表示される。


 本来ならUnityPlayerをFragment側に移動させるべきなのだが、致命的な制約があったため実現不可能だった。UnityPlayerはActivityがフォーカスを持った時点で存在していないと正常に動作しない。そのためボタン操作など、後から切り替わることを前提としたFragment上でUnityPlayerを作成すると、すでにActivityがフォーカスを持っているため、何も表示されない状態となってしまう。強制的にフォーカスを通知しても、例外が発生して正常動作しない。いったんホームに戻ってからActivityに切り替えるとかいう技なら動かすことも可能だが、現実的では無い。

戻るボタンを使えるようにする

2018-12-14 15:23:40

 初期状態だと戻るボタンが無視されてしまう。このままだとAndroidアプリとしては使いにくいので、Activityのデフォルト動作が行われるようにActivityのコードを変更する。やっていることはバックボタンをUnityPlayerに渡さないようにしているだけだ。


    @Override public boolean onKeyUp(int keyCode, KeyEvent event)     {
        if(event.getKeyCode() != KeyEvent.KEYCODE_BACK)
            return mUnityPlayer.injectEvent(event);
        return super.onKeyUp(keyCode,event);
    }
    @Override public boolean onKeyDown(int keyCode, KeyEvent event)   {
        if(event.getKeyCode() != KeyEvent.KEYCODE_BACK)
            return mUnityPlayer.injectEvent(event);
        return super.onKeyDown(keyCode,event);
    }

実は

2018-12-14 15:26:51

 UnityPlayerはFrameLayoutクラスを継承しているただのViewなので、レイアウトの一部に貼り付けたりするのは問題なく可能なのだ。ということでAndroid側のネイティブコンポーネントと共存させるのも特に問題は無い。