アプリ連動機能 (Unity)

カラメルカラムでは複数のアプリをインストールしたときに、連動してコンテンツが増える仕組みを入れています。

その機能が入っているのは主にALTER EGOです。
ALTER EGOクリア状態で、AZNANAやALTER EGO COMPLEXという別ゲーム(後者はシリーズ作品ですが)をインストールすると、ALTER EGO内で新規エピソードがそれぞれ解放されます。

ALTER EGO 連動シナリオの表示
AZNANAインストール後→特殊シナリオが読める

少し昔話になりますが、この機能を最初に入れたのは、ムシカゴというゲームでした。
ムシカゴは別会社の運営であるトリカゴというゲームのスピンオフ(プロモーション目的)として開発されたゲームであり、ムシカゴから入ったユーザーにもトリカゴをインストールしてもらうために入れました。
当初ディレクターは「そんなことできるのか?入れて問題ないのか?」と多少難色を示していましたが、実現可能なことと規約的にも問題ないことを確認して実装してみたところ、ムシカゴをインストールしたユーザーの内12%ほどのユーザーがトリカゴもインストールしてくださり、割と良い結果を出すことができたのかな〜と思っています。

その後トリカゴはサービスを終了してしまいましたので、以降はトリカゴをインストールしなくてもそのエピソードが読めるように改修しており(v1.3の頃)、今現在ではムシカゴにその機能は入っていません。なぜかムシカゴはトリカゴから離れた後もv2, v3とコンテンツを増やすアップデートを続けています。

話は戻り、そうやって味を占めた我々は自社アプリ同士にもその連動機能を入れ、ALTER EGOを軸にいろんなアプリを遊んでねという啓蒙をひっそりアプリに落とし込んでいるわけです。
とはいえ、世界観を重視するディレクターはそう簡単にこの機能を入れさせれてはくれず、今のところはALTER EGOから本つながりなどで許されたときだけこの機能が入ることになっています。
(世界観だけでなく、言語対応の有無など仕様的な制限もあったりなかったりします)

アプリ連動 (インストール判定) の実装

ここから実装方法を説明します。
なお「アプリ連動」といっても見ているのはインストールしているかどうかだけで、ゲームの進行状況などの情報は使っていません。

Andorid

環境
・Unity 2021.3.8f
・Android SDK 33

Androidのインストール判定は対象アプリのパッケージ名さえ分かれば、チェックする側のアプリだけ実装すればOKです。
設定するのは大きく2箇所。

以下、"com.caracolu.aznana"アプリをチェックする場合のコード例

(1) AndroidManifest.xml
・PlayerSettings→BuildSettingsからCustomMainManifestを有効化

・作成された AndroidManifest.xml に下記定義を追記
<queries>
  <package android:name="com.caracolu.aznana" />
</queries>

(2) AndroidUtil.java 作成 (Plugins/Android に配置)

package com.caracolu.appcommon;

import android.content.pm.PackageManager;
import java.lang.Exception;

public class Util {
    public boolean IsInstalled(String packageID) {
        PackageManager pm = UnityPlayer.currentActivity.getPackageManager();
        boolean ret = false;
        try {
            pm.getPackageInfo(packageID, PackageManager.GET_ACTIVITIES);
            ret = true;
        } catch (Exception e) {
            //指定のアプリは取得できない = インストールされていない
        }
        return ret;
    }
}

Unity C#側から以下のように呼び出して判定できます。

string appID = "com.caracolu.aznana";  //PlayerSettingsで設定したパッケージ名
using (var util = new AndroidJavaObject("com.caracolu.appcommon.Util")) {
    bool isInstalled = util.Call<bool>("IsInstalled", appID);
    if (isInstalled) Debug.Log("インストールされています");
    else Debug.Log("インストールされていません");
}

iOS

環境
・Unity 2021.3.8f
・Xcode 14.1.0

iOS用は実際にはインストールされているかをチェックするのではなく、カスタムURLスキームという機能を使って擬似的に実現しています。
チェックされる側に独自にURLスキームを定義し、チェックする側は「そのURLを開くことができる」=「アプリが存在する」とみなします。
そのためチェックする側/される側両方に実装(設定)が必要です。

以下、"sample12345"をカスタムURLとした場合のコード例

(1) Info.plist に設定
チェックされる側:CFBundleURLSchemesの設定
チェックする側:LSApplicationQueriesSchemesの設定

PostProcessBuildiOS.cs (Editorフォルダに配置)
OnPostprocessBuildでInfo.plistを上記を自動設定するコード

using System.Collections.Generic;

using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.iOS.Xcode;

public class PostProcessBuildiOS : IPostprocessBuildWithReport
{
	public int callbackOrder { get { return 1; } }

    public void OnPostprocessBuild(BuildReport report) {
    	string pathToBuildProject = report.summary.outputPath;
		var plistPath = Path.Combine(pathToBuiltProject, "Info.plist");
		var pList = new PlistDocument();
		pList.ReadFromFile (plistPath);

		string customUrl = "sample12345";

		// チェックされる側に必要
		var mainArray = pList.root.CreateArray("CFBundleURLTypes");
		var dict = mainArray.AddDict();
		dict.SetString("CFBundleURLName", "com.caracolu.alterego");  //bundleIDを指定
		var subArray = dict.CreateArray("CFBundleURLSchemes");
		subArray.AddString(customUrl);

		// チェックする側に必要
		var queryArray = pList.root.CreateArray("LSApplicationQueriesSchemes");
		queryArray.AddString(customUrl);

		pList.WriteToFile (plistPath);
	}
}

(2) iOSUtil.mm (Plugins/iOS に配置)

extern "C" {
    bool _CanOpenURL(char *url) {
        return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:getStr(url)]];
    }
}

Unity C#側から以下のように呼び出して判定できます。

using System.Runtime.InteropServices;

[DllImport("__Internal")]
static extern bool _CanOpenURL(string url);

{
    //  (中略)
    string customUrl = "sample12345://";   // "://"をつける
    bool isInstalled = util.Call<bool>("IsInstalled", customUrl);
    if (isInstalled) Debug.Log("インストールされています");
    else Debug.Log("インストールされていません");
}

UnityからAndroid/iOSのネイティブコードを呼ぶのはけっこう簡単ですが、慣れてないとドキュメントを探すのも難しいところです。自分はもともとAndroidのエンジニアだったのでAndroid側の実装は親しみがあるものの、iOSは知見が乏しく、見様見真似でやっています…。

ソースコード載せるのって難しいですね。
どなたかのご参考になれば幸いです。

この記事が気に入ったらサポートをしてみませんか?