Unity

【Unity×iOS】iOSのスクリーンショットを検知する方法 | UIApplicationUserDidTakeScreenshotNotification

この記事について

Unity標準ではスクリーンショットを検出する機能がありません。しかし、iOSの仕組みを利用すれば簡単に検知することができます。この記事では コピペで使えるプラグインとC#スクリプト を紹介し、さらに応用アイデアまで解説します。

この記事で分かること

  • Unity標準ではスクリーンショット検出ができない理由
  • iOSのNotificationCenterを使ったスクショイベントの受信方法
  • 実際に動作するプラグインとC#コード例
  • スクショ検知を応用した演出・保護機能アイデア

UIApplicationUserDidTakeScreenshotNotification とは?

iOSでスクリーンショットを検知する方法として使えるのが 「UIApplicationUserDidTakeScreenshotNotification」です。これはAppleが用意しているシステム通知のひとつで、ユーザーが端末でスクリーンショットを撮影した瞬間にアプリへ通知が届きます。通知の仕組みは NotificationCenter を通じて動作し、アプリがこの通知を監視することで「スクショが撮られた」という事実を検知できるようになっています。

発火条件

  • 物理キー操作:電源ボタン + 音量アップボタン
  • AssistiveTouch:メニューからのスクショ撮影
  • その他iOSがスクショと認識する操作

Unity標準ではスクリーンショット検知できない理由

Unityには「スクリーンショットボタンを押した」というイベントは用意されていません。
iOS側の機能(UIApplicationUserDidTakeScreenshotNotification)が電源ボタン+音量上ボタンやAssistiveTouchからのスクショなどでのみ発火します。

つまり、Unityだけではスクリーンショット検知は不可能であり、iOSネイティブコードを経由して検知する必要があるわけです。

UIApplicationUserDidTakeScreenshotNotificationを使ったスクショ検出

iOSにはシステム通知(NotificationCenter)があり、
UIApplicationUserDidTakeScreenshotNotification」という特別な通知でスクショ撮影が検出できます。

スクリーンショット検知プラグインを作成

「.mm」ファイルを作成する

プロジェクトに「Assets/Plugins/iOS/ScreenshotDetector.mm」を作成します。
※フォルダがない場合は作成してください。また、「.mmファイル」はメモ帳で作成しています。

  • RegisterScreenshotCallback関数でUnityにコールバックを登録
  • スクリーンショット検出時にUnity側に通知する設計です
#import <UIKit/UIKit.h>

extern "C" {

typedef void (*ScreenshotCallback)();
static ScreenshotCallback callback = NULL;

void RegisterScreenshotCallback(ScreenshotCallback cb)
{
    callback = cb;
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
                                                      object:nil
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
        if (callback != NULL)
        {
            callback();
        }
    }];
}
}

作成してこのようになっていたら問題ありません。

Unity側で受け取るC#スクリプト

「.mm」ファイルの関数「RegisterScreenshotCallback」でコールバックを受け取ることで検出ができます。
※デバッグを見せるよりテキストの方がわかりやすいため、テキストボックスを使用しています。

using System;
using System.Runtime.InteropServices;
using TMPro;
using UnityEngine;

public class ScreenshotDetector : MonoBehaviour
{
    // シングルトン(staticからインスタンスの変数にアクセスするために用意)
    public static ScreenshotDetector Instance;

    // UIに表示するテキスト
    [SerializeField] private TextMeshProUGUI ScreenShot_Text;

    // iOSに渡すコールバック用デリゲート定義
    private delegate void ScreenshotCallbackDelegate();

    // GCに回収されないように static で保持しておく
    private static ScreenshotCallbackDelegate _callbackDelegate;

#if UNITY_IOS && !UNITY_EDITOR
    // iOS側のネイティブ関数を呼び出す宣言
    [DllImport("__Internal")]
    private static extern void RegisterScreenshotCallback(ScreenshotCallbackDelegate callback);
#endif

    void Awake()
    {
        // 自分自身をシングルトンとして保持
        Instance = this;
    }

    void Start()
    {
#if UNITY_IOS && !UNITY_EDITOR
        // C#側のメソッドをネイティブに登録
        _callbackDelegate = OnScreenshotTaken;
        RegisterScreenshotCallback(_callbackDelegate);
#endif
    }

    // iOS側から呼ばれるコールバック関数
    // IL2CPPでストリップされないように属性を付ける
    [AOT.MonoPInvokeCallback(typeof(ScreenshotCallbackDelegate))]
    private static void OnScreenshotTaken()
    {
        Debug.Log("スクリーンショットが撮影されました!");

        // staticメソッドなので直接UI変数に触れない
        // → Instance経由でアクセスする
        if (Instance != null)
        {
            Instance.ScreenShot_Text.text = "ScreenShot";
        }
    }
}

実機ビルド後にスクショを撮ると、Unity側のテキストが更新され、Xcodeではログも出力されます。

スクショ検知を応用した演出・保護機能アイデア

Unityアプリでスクショ検知を活用すると、いろいろな演出やUX改善ができます。

  • スクショ撮影時に「保存ありがとう!」メッセージを表示
  • 限定スクショボーナス(スクショすると隠しアイテム出現)
  • 著作権保護のためにスクショ検知後にウォーターマークを挿入
  • SNS投稿促進(「スクショをそのままシェアしよう!」誘導)

特にカジュアルゲームやSNS連携コンテンツでは、
スクショ検知はうまく使えば超強力なユーザー体験強化ポイントになります!

まとめ

項目内容
Unity標準Inputではスクショ検出不可
iOSUIApplicationUserDidTakeScreenshotNotification を利用
プラグイン.mm ファイルと [DllImport(“__Internal”)] で橋渡し
C#側コールバックを受け取り、UIやログに反映
応用UX演出・著作権保護・SNS促進など

「スクショを撮る」行動を、ゲームやアプリの楽しさに変える仕掛けを、ぜひあなたのUnity×iOSプロジェクトに導入してみてください!