😸

Unity製iOSアプリでクイックアクションを実装する

に公開

はじめに

こんにちは、ゲームエンジニアのでぃとです。

今回はUnity製iOSアプリでクイックアクションを実装する方法を紹介します!

クイックアクションって?

クイックアクションとはiOS9から始まった機能で、3D Touchという押す強さに応じてリアクションが変化する技術を元に開発された物です。
現在では3D Touchは廃止されてしまったため、アプリアイコンを長押しする事で表示されます。
こういうものですね。

ここにはアプリごとに任意の動作を実行することができるメニューを追加できます。
メニューのアイコンや文言は自由に設定することができます。

今回作る物

クイックアクションにメニューを追加するためには静的に追加する方法と動的に追加する方法があります。
今回はアプリを起動するアクションを例に、2つの方法をご紹介いたします。

静的に追加する方法

まずは静的に追加する方法です。
この方法の良い点はアプリをインストールしたてのユーザーに対しても表示できる点です。

静的に追加するにはinfo.plistに処理を書き込むのですが、PostProcessBuild を使ってビルド時に自動でinfo.plistに書き込む方法をご紹介いたします。

#if UNITY_IOS
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.IO;
public class iOSQuickActionConfig
{
    [PostProcessBuild]
    public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
    {
        if (buildTarget != BuildTarget.iOS) return;
        string plistPath = Path.Combine(path, "Info.plist");
        PlistDocument plist = new PlistDocument();

        plist.ReadFromFile(plistPath);
        PlistElementArray shortcuts = plist.root.CreateArray("UIApplicationShortcutItems");
        PlistElementDict startAction = shortcuts.AddDict();

        startAction.SetString("UIApplicationShortcutItemType", "$(PRODUCT_BUNDLE_IDENTIFIER).start");
        startAction.SetString("UIApplicationShortcutItemTitle", "ゲームを始める!");
        startAction.SetString("UIApplicationShortcutItemIconType", "UIApplicationShortcutIconTypePlay");

        File.WriteAllText(plistPath, plist.WriteToString());
    }
}
#endif

このコードをAsset/Editorに配置し、ビルドをするとクイックアクションにゲームを起動するためのショートカットが追加されます。
実際にタップしてみるとアプリが起動されます。

動的に追加する方法

次に動的に追加する方法です。
動的に追加する場合は、内容を各ユーザーの進行度等に応じてカスタムできるので、静的に追加するメニューよりも適切なアプローチをすることができます。

ユーザーの進行状況の保持の仕方はプロジェクトによって様々だと思うので、今回はUnity標準機能のprefsから進行度を参照してクイックアクションのテキストを変更してみましょう。
動的に追加する場合はC#のみでは完結できないので、Swiftを使ってネイティブコードを用意します

import UIKit

@_cdecl("UpdateShortcutItem_Swift")
public func UpdateShortcutItem_Swift(type: UnsafePointer<CChar>, title: UnsafePointer<CChar>) {
    let strType = String(cString: type)
    let strTitle = String(cString: title)
    
    let icon = UIApplicationShortcutIcon(type: .play)
    
    let item = UIMutableApplicationShortcutItem(
        type: strType,
        localizedTitle: strTitle,
        localizedSubtitle: nil,
        icon: icon,
        userInfo: nil
    )
    
    UIApplication.shared.shortcutItems = [item]
}

次に、C#でPrefsから値を取得し、先ほどのネイティブコードを叩くクラスを作成します。

using UnityEngine;
using System.Runtime.InteropServices;

public class QuickActionManager : MonoBehaviour
{
#if UNITY_IOS && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void UpdateShortcutItem_Swift(string type, string title);
#endif

    public static void UpdateAction()
    {
#if UNITY_IOS && !UNITY_EDITOR
        int progress = PlayerPrefs.GetInt("Progress", 0);

        string title = "ゲームを始める!";

        if (progress > 0)
        {
            title = $"チャプター{progress}を再開";
        }

        string typeId = Application.identifier + ".dynamic_start";
        UpdateShortcutItem_Swift(typeId, title);
#endif
    }

    private void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
        {
            UpdateAction();
        }
    }
}

サンプルコードでは、これをシーンの常駐オブジェクトにアタッチすることで、アプリがバックグラウンドに戻る瞬間に更新が入るようになっています。
実際にはPrefsが保存されるタイミング等に合わせると良いかと思います。

動作確認用にボタンを押すとカウントがインクリメントされていき、その結果をprefsに保存する簡単な仕組みを作って、クイックアクションのテキストが書き換わるかどうかを見てみます。

インクリメントされた値がクイックアクションに反映されていますね。

終わりに

いかがでしたでしょうか?
今回はUnity製アプリでクイックアクションを使う方法をご紹介しました。
本記事ではアプリを起動するという基本的なアクションをご紹介しましたが、特定のシーンへ遷移したりなど色んな挙動を実装できます。
ユーザーが頻繁に目にする箇所では無いですが、アプリ外からユーザーへアプローチをすることができるのでぜひ実装してみてください!

Happy Elements

Discussion