Edited at

iPhoneのUnityゲームで短い・弱い振動(バイブレーション)をさせる方法

More than 1 year has passed since last update.


目標

Unityのゲームで一定の場合には(例えば、GameObjectの衝突が発生した場合)iPhoneを短くかつ弱く振動させることです。

Unityの「Handheld.Vibrate()」を簡単に使ったらバイブレーション自体はできますが、振動の強さ・長さ・種類は一切調整できないため(実機でテストしてみたら、結構強い振動でした。:skull_crossbones:)、必ずほかの方法を見つけないといけません。


解決方法

iOSは、AudioToolbox.frameworkのAudioServicesでさまざまな効果音とバイブレーションを用意してくれています。

しかし、Unityから直接にiOSのAudioServicesを呼び出すことがまだ不可能らしいので、「iOS用のプラグインをビルド」という方法で間接的に呼び出せるようにします。

手順は以下の通りです。(もう自分のUnityゲームで実装済み)


①Object-CのスクリプトplaySystemSound.mmを作成します。

#import <Foundation/Foundation.h>

#import <AudioToolBox/AudioToolBox.h>

extern "C" void playSystemSound (int n)
{
AudioServicesPlaySystemSound(n);
}

名前はplaySystemSoundじゃなくても何でも可。言語はObject-CじゃなくてC++(.cpp)でも問題無さそうだけど、未検証のため、ご興味のある方は自分で試してみてください。


②作成したplaySystemSound.mmファイルをUnityのAssetsフォルダの下に置きます。

image.png

Assetsフォルダーの下ならどこでも可。


③UnityのC#スクリプトにplaySystemSoundメソッドを呼び出すコードを作成します。

自分のゲームのプログラムを例として説明します。

GameObject「Target」の衝突があった時にiPhoneを振動させるとします。

まず、「Target」には「TargetController.cs」というC#スクリプトをアタッチします。

image.png

Targetの衝突があった時、Unityが自動的にOnTriggerEnter関数を呼び出すので、「振動させる」コードをOnTriggerEnterの中に書くとよいでしょう。

public class TargetController : MonoBehaviour

{
/* ほかのコード略 */
[DllImport("__Internal")]
private static extern void playSystemSound(int n);
/* ほかのコード略 */
private void OnTriggerEnter(Collider other)
{
/* ほかのコード略 */
#if UNITY_EDITOR
Debug.Log("Play system sound or vibration on real devices");
#else
playSystemSound(1519);
#endif
/* ほかのコード略 */
}

ここで 注意 していただきたいのは、もし、Unity EditorでplaySystemSoundを呼び出すと、下記のような「EntryPointNotFoundException」が出てしまうのです。 iPhone実機で実行するとそういうExceptionは出ない ので、「#if UNITY_EDITOR」(プラットフォーム依存コンパイル)を使ってUnity Editorの場合を外したほうが無難です。

image.png

なお、playSystemSound(int n)のパラメータ「n」は、 「1519」 を使うと 「プッ」という短い・弱いバーブレーション になります。

別途で「1005」を試してみました。iPhoneをミュートするとシステムアラームの振動と同じようなバイブレーションが出ました。逆にiPhoneをunmuteするとvibrationが出なくてアラームの効果音だけが出ました。

ほかのパラメータについて、ご興味のある方自分で試してみてください :point_right: iOS Predefined sounds

以上です。