Skip to content

第01回 プラグインを作成する(シェア機能)

kyusyukeigo edited this page Feb 26, 2015 · 1 revision

使用するプロジェクト

この回はモバイル編第03回終了時点のプロジェクトを使用します。

モバイル編第03回終了時点のプロジェクトファイルをダウンロード

プラグインのマニュアルを軽く読んでみよう

この回はプラグインの作り方を、実際に何かを作成しながら覚えるというものです。

詳しい説明は省く可能性がありますのでiOS用のプラグインをビルドを読み返しながらこの回を読んでいきましょう。

1.1 シェア機能を実装する

iOSユーザーはよく見る画面かもしれない
図1.1: iOSユーザーはよく見る画面かもしれない

Unityの機能として提供されていないものをプラグインとして実装して利用します。

今回はテキストや画像を簡単に共有できる「UIActivityViewController」を使用します。

Unity側の実装

シェアボタンとして使用するテクスチャのダウンロード

シェアボタンのテクスチャをダウンロード (右クリックして保存)

ダウンロードしたshare.pngのテクスチャをTexturesフォルダ下にインポートします。

Manager.csにシェアするボタンとiOS側の処理を呼び出すコードを追加します。

Manager.cs

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class Manager : MonoBehaviour
{
    // Playerプレハブ
    public GameObject player;

    // タイトル
    private GameObject title;

    // シェアのテクスチャ
    public Texture2D shareButtonImage;

    // iOS側のコードを呼び出すための処理
    [DllImport("__Internal")]
    private static extern void Shooting_Share (string text, string url, string textureUrl);

    void Start ()
    {
        // Titleゲームオブジェクトを検索し取得する
        title = GameObject.Find ("Title");
    }

    void OnGUI ()
    {
        // シェアボタンを設置
        if (GUILayout.Button (shareButtonImage, GUIStyle.none, GUILayout.Width (128), GUILayout.Height (128))) {

            // シェアする処理をコルーチンで実行
            StartCoroutine (Share ());
        }

        // ゲーム中ではなく、タッチまたはマウスクリック直後であればtrueを返す。
        if (IsPlaying () == false && Event.current.type == EventType.MouseDown) {
            GameStart ();
        }
    }

    IEnumerator Share ()
    {
        // 現在の画面をキャプチャして名前をscreenShotとして保存する
        Application.CaptureScreenshot ("screenShot.png");

        // キャプチャを保存する処理として1フレーム待つ
        yield return new WaitForEndOfFrame ();

        string text = "2Dシューティング チュートリアル #unity";
        string url = "http://japan.unity3d.com/developer/document/tutorial/2d-shooting-game/ios/01.html";

        // Application.CaptureScreenshotの保存先はApplication.persistentDataPath
        string textureUrl = Application.persistentDataPath + "/screenShot.png";

        // iOS側の処理を呼び出す
        Shooting_Share (text, url, textureUrl);
    }

    void GameStart ()
    {
        // ゲームスタート時に、タイトルを非表示にしてプレイヤーを作成する
        title.SetActive (false);
        Instantiate (player, player.transform.position, player.transform.rotation);
    }

    public void GameOver ()
    {
        FindObjectOfType<Score> ().Save ();
        // ゲームオーバー時に、タイトルを表示する
        title.SetActive (true);
    }

    public bool IsPlaying ()
    {
        // ゲーム中かどうかはタイトルの表示/非表示で判断する
        return title.activeSelf == false;
    }
}

shareのテクスチャをManagerゲームオブジェクトのShare Button Imageにドラッグ&ドロップします。

これでゲームを再生すると図1.2のように左上にシェアボタンが表示されます。


図1.2:

ボタン押したと同時にゲームが開始されてしまうのでは?

今回、Event.current.typeによるマウスクリック判定・タップ判定を行っています。ここで鋭い人は、ボタンを押した時にEvent.current.typeがEventType.MouseDownとなってしまいゲームが開始してしまうのではないかと思うかもしれません。

ですが、実際はゲームは開始されません。これはボタンを押したと同時に、Event.current.typeがEventType.Usedとなり、使用済みイベントとなるからです。これによって他のイベント処理はすべてスキップされ、次のOnGUIの呼び出しから実行されるようになります。

プラグイン側の実装

次にネイティブコード(Objective-C++)を書いていきます。


図1.3のようにPluginsフォルダ、iOSフォルダを作成し、Share.mmファイルを作成します。

Plugins/iOSフォルダ内にmmファイルを入れておくと、ビルドしたXcodeプロジェクトに自動でファイルを追加してくれます。


図1.3:

mmファイルの作成

UnityEditor上でmmファイルの作成を行うことは出来ません。なのでFinderやExplorer上でファイルの作成を行ってください。

Share.mmにコードを書いていきます。

技術的な説明はObjective-Cに関する説明になってしまうので簡潔に書くと、

Shooting_Shareメソッドでは3つの文字列を引数として受け取り、UIActivityViewControllerで扱えるように変換しています。

メソッド名はユニークな名前にしよう

プラグインを作成してUnityでビルド(Xcodeプロジェクト作成)すると自動的にRegisterMonoModules.cppにメソッドが登録されます。RegisterMonoModules.cppはいじらないようにしましょう。

プラグインを作成する時に気をつけて欲しいのがメソッド名は必ずユニークな名前にするということです。

他のプラグインのメソッドも全てRegisterMonoModules.cppで登録されます。ユニークな名前にしないと他のプラグインで使用しているメソッド名とかぶってしまい、エラーが発生したり、別のプラグインのメソッドが呼ばれてしまうということがあります。

Share.mm

// Unityのバージョンが4.3.4以前であれば
#if UNITY_VERSION <= 434

// Unity4.3.4ではUnityGetGLViewControllerを使用するためにiPhone_Viewのインポートが必要
#import "iPhone_View.h"

#endif

extern "C" {

    void Shooting_Share(const char *text, const char *url, const char *textureURL) {

    // NSStringに変換
    NSString *_text = [NSString stringWithUTF8String:text];
    NSString *_url = [NSString stringWithUTF8String:url];
    NSString *_textureURL = [NSString stringWithUTF8String:textureURL];

    UIImage *image = nil;

    // パスから画像を取得
    if ([_textureURL length] != 0) {
        image = [UIImage imageWithContentsOfFile:_textureURL];
    }

    // テキスト・URL・画像の順に配列を作成する
    NSArray *actItems = [NSArray arrayWithObjects:_text, _url, image, nil];

    // UIActivityViewを作成する
    UIActivityViewController *uiActivityViewController = [[[UIActivityViewController alloc] initWithActivityItems:actItems applicationActivities:nil] autorelease];


    // Unity画面の上にビューを表示させる
    [UnityGetGLViewController() presentViewController:uiActivityViewController animated:YES completion:nil];

    }

}

ビルドしてXcodeプロジェクトを作成しましょう。

Xcodeプロジェクトを開き、Runボタンを押して端末へアプリをインストールして実行します。

iOS上でシェアボタンを押したらUIActivityViewが表示されましたか?

最後にゲーム中はシェアボタンを押さないようにManager.csのOnGUIメソッド内を修正します。

他にもバーチャルジョイスティックを追加して操作できるようにして、ハイスコア

Manager.cs

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class Manager : MonoBehaviour
{
    // Playerプレハブ
    public GameObject player;

    // タイトル
    private GameObject title;

    // シェアのテクスチャ
    public Texture2D shareButtonImage;

    // iOS側のコードを呼び出すための処理
    [DllImport("__Internal")]
    private static extern void Shooting_Share (string text, string url, string textureUrl);

    void Start ()
    {
        // Titleゲームオブジェクトを検索し取得する
        title = GameObject.Find ("Title");
    }

    void OnGUI ()
    {
        // ゲーム中でない時
        if (IsPlaying () == false) {
            // シェアボタンを設置
            if (GUILayout.Button (shareButtonImage, GUIStyle.none, GUILayout.Width (128), GUILayout.Height (128))) {

                // シェアする処理をコルーチンで実行
                StartCoroutine (Share ());
            }

            // タッチまたはマウスクリック直後であればtrueを返す。
            if (Event.current.type == EventType.MouseDown) {
                GameStart ();
            }
        }
    }

    IEnumerator Share ()
    {
        // 現在の画面をキャプチャして名前をscreenShotとして保存する
        Application.CaptureScreenshot ("screenShot.png");

        // キャプチャを保存する処理として1フレーム待つ
        yield return new WaitForEndOfFrame ();

        string text = "2Dシューティング チュートリアル #unity";
        string url = "http://japan.unity3d.com/developer/document/tutorial/2d-shooting-game/ios/01.html";

        // Application.CaptureScreenshotの保存先はApplication.persistentDataPath
        string textureUrl = Application.persistentDataPath + "/screenShot.png";

        // iOS側の処理を呼び出す
        Shooting_Share (text, url, textureUrl);
    }

    void GameStart ()
    {
        // ゲームスタート時に、タイトルを非表示にしてプレイヤーを作成する
        title.SetActive (false);
        Instantiate (player, player.transform.position, player.transform.rotation);
    }

    public void GameOver ()
    {
        FindObjectOfType<Score> ().Save ();
        // ゲームオーバー時に、タイトルを表示する
        title.SetActive (true);
    }

    public bool IsPlaying ()
    {
        // ゲーム中かどうかはタイトルの表示/非表示で判断する
        return title.activeSelf == false;
    }
}

第01回終わり

今回はここで終了です。つまずいてしまった方はプロジェクトファイルをダウンロードして新たな気持ちで次の回へ進みましょう。

今回のプロジェクトファイルをダウンロード

Clone this wiki locally