スマホアプリの中には、音量ボタンで操作できる便利なUIや、ユーザーの隠れたアクションを検知する仕組みがあります。
しかしUnityには、標準で音量ボタン(ハードボタン)を検出する仕組みがありません。
この記事では、iOSの音量ボタン(+/−)の操作をUnityから検知する方法を、ネイティブプラグイン+C#スクリプトの構成で詳しく解説します。
コピペOKのコード付きで、誰でも簡単に導入できます!
この記事で分かること
- Unityでは音量ボタンが検出できない理由
- 音量の変化をフックしてボタン操作を検知する仕組み
- 【コピペOK】Objective-C++プラグイン+Unity連携スクリプト
- 音量ボタン検出を活用した便利な使い方
なぜUnityでは音量ボタンを検出できないのか?
Unityはタッチやキー入力には対応していますが、
iOSの物理ボタン(音量+/−、サイレントスイッチなど)は標準でアクセスできません。
ただし、iOSではAVAudioSessionやMPVolumeViewを使えば、
音量の変化を検知することで音量ボタンの操作を間接的に検出することができます!
【コピペOK】音量ボタン検出プラグインの作成
.mmファイルを作成する
Assets/Plugins/iOS/VolumeButtonDetector.mm に以下を記述:
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>
static float lastVolume = -1.0f;
static void (*volumeCallback)(int) = NULL;
extern "C" {
void SetVolumeCallback(void (*callback)(int))
{
volumeCallback = callback;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
lastVolume = session.outputVolume;
[[NSNotificationCenter defaultCenter] addObserverForName:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
float currentVolume = [session outputVolume];
if (volumeCallback) {
if (currentVolume > lastVolume)
volumeCallback(1); // volume up
else if (currentVolume < lastVolume)
volumeCallback(-1); // volume down
}
lastVolume = currentVolume;
}];
}
}
Unity側C#スクリプトを書く
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class VolumeButtonDetector : MonoBehaviour
{
#if UNITY_IOS && !UNITY_EDITOR
[DllImport("__Internal")]
private static extern void SetVolumeCallback(VolumeCallbackDelegate callback);
private delegate void VolumeCallbackDelegate(int direction);
#else
private static void SetVolumeCallback(VolumeCallbackDelegate callback) { }
private delegate void VolumeCallbackDelegate(int direction);
#endif
public static event Action OnVolumeUp;
public static event Action OnVolumeDown;
[AOT.MonoPInvokeCallback(typeof(VolumeCallbackDelegate))]
private static void OnVolumeChanged(int direction)
{
if (direction > 0) OnVolumeUp?.Invoke();
else if (direction < 0) OnVolumeDown?.Invoke();
}
void Start()
{
SetVolumeCallback(OnVolumeChanged);
}
}
使用例(音量ボタンでUI切り替え)
public class SampleUI : MonoBehaviour
{
void OnEnable()
{
VolumeButtonDetector.OnVolumeUp += () => Debug.Log("音量UPボタンが押されました");
VolumeButtonDetector.OnVolumeDown += () => Debug.Log("音量DOWNボタンが押されました");
}
void OnDisable()
{
VolumeButtonDetector.OnVolumeUp -= () => Debug.Log("音量UPボタンが押されました");
VolumeButtonDetector.OnVolumeDown -= () => Debug.Log("音量DOWNボタンが押されました");
}
}
注意点・制限事項
- 音量の変化で判定しているため、連打検出には向きません
- ユーザーが音量をMAX or MINにしていると検出できない
- 初回呼び出しでAVAudioSession.setActive(true)を忘れると検知できません
活用アイデア(音量ボタンの使い道)
- バレずにスクショ → 音量ボタンで隠し機能をトリガー
- 動画・音楽再生中に再生速度切り替え
- ゲーム中に音量ボタンでUI開閉やモード変更(片手プレイに最適)
- 設定画面なしでボリューム調整 or 設定パネルを表示
まとめ
項目 | 内容 |
---|---|
Unity標準では音量ボタンの検出不可 | ネイティブ連携が必要 |
AVAudioSession+通知センターで変化検出 | |
コピペOKプラグイン+C#で簡単導入可能 | |
UX強化や隠し操作トリガーに応用できる |
音量ボタンという「いつでも押せる物理UI」を活かして、
ユーザーに新しい操作体験を届けてみましょう!