スマホのバイブレーション機能がUnityに用意されていたので、試しに使ってみました。
環境
- Unity2018.3.7f1
- MacBookPro Mojave v10.14.3
- iPhone SE OS11.4.1
実装
調べてみると呼び出し自体はすごくシンプルで、Handheld.Vibrate関数を呼び出すだけでした。ソースはこんな感じに
1 2 3 4 5 6 7 8 9 10 11 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class VibrationTest : MonoBehaviour { private void Start () { Handheld.Vibrate(); } } |
とてもシンプルですね!ただ、用意されている関数はこれだけの為、強弱や回数、振動しているかどうかというのは取得できないようです。他サイトで調べてみると、自分でネイティブ実装すればできるようですね。
これだけだと面白くないので、再生回数、再生秒数、終了コールバック受け取りできるような形にしたクラスを作ってみました!Vibrationのstatic関数にアクセスしたタイミングで破棄されないGameObjectを生成し振動処理を行う形になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public static class Vibration { public enum ResultType { Interruption = 0, // 中断 . End, // 終了 . } public struct Result { public ResultType Type { get; set; } public uint Uid { get; set; } } private class Vibrate : MonoBehaviour { // 1回の振動が約0.5秒くらいの為、再生時間を0.5秒として設定 . private readonly WaitForSeconds PlaybackSeconds = new WaitForSeconds( 0.5f ); private uint m_uid = 0; private Coroutine m_coroutine = null; private Action<Result> m_callback = null; public bool IsExecuting () { return m_coroutine != null; } public bool IsExecuting ( uint uid ) { return !IsExecuting() ? false : m_uid==uid; } public uint PlayCount ( int count, Action<Result> callback ) { return OnPlay( OnPlayCount( count ), callback ); } public uint PlaySeconds ( float seconds, Action<Result> callback ) { return OnPlay( OnPlaySeconds( seconds ), callback ); } public void Stop () { OnStop( ResultType.Interruption ); } public void Stop ( uint uid ) { if ( IsExecuting( uid ) ) { OnStop( ResultType.Interruption ); } } private uint OnPlay ( IEnumerator enumerator, Action<Result> callback ) { OnStop( ResultType.Interruption ); ++m_uid; m_callback = callback; m_coroutine = StartCoroutine( enumerator ); return m_uid; } private IEnumerator OnPlayCount ( int count ) { int nowCount = 0; while ( nowCount < count ) { Handheld.Vibrate(); yield return PlaybackSeconds; ++nowCount; } OnStop( ResultType.End ); } private IEnumerator OnPlaySeconds ( float seconds ) { float now = Time.realtimeSinceStartup; while ( (Time.realtimeSinceStartup-now) < seconds ) { Handheld.Vibrate(); yield return PlaybackSeconds; } OnStop( ResultType.End ); } private void OnStop ( ResultType type ) { if ( m_coroutine != null ) { if ( m_callback != null ) { Result result; result.Uid = m_uid; result.Type = type; m_callback( result ); m_callback = null; } StopCoroutine( m_coroutine ); m_coroutine = null; } } } private static Vibrate s_instance = null; static Vibration () { GameObject go = new GameObject( "Vibration" ); s_instance = go.AddComponent<Vibrate>(); GameObject.DontDestroyOnLoad( go ); } public static bool IsEnabled () { return SystemInfo.supportsVibration; } public static bool IsExecuting () { return s_instance.IsExecuting(); } public static bool IsExecuting ( uint uid ) { return s_instance.IsExecuting( uid ); } public static uint PlayCount ( int count, Action<Result> callback = null ) { return s_instance.PlayCount( count, callback ); } public static uint PlaySeconds ( float seconds, Action<Result> callback = null ) { return s_instance.PlaySeconds( seconds, callback ); } public static void Stop () { s_instance.Stop(); } public static void Stop ( uint uid ) { s_instance.Stop( uid ); } } |
1回の振動を計測したら、約0.5秒くらいだったので、再生時間を0.5秒として扱ってみました。使い方はこちらです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class VibrationTest : MonoBehaviour { private void Start () { // 3回振動させる Vibration.PlayCount( 3, OnVibrationEnd ); } private void OnVibrationEnd ( Vibration.Result result ) { if ( result.Type == Vibration.ResultType.Interruption ) { Debug.Log( result.Uid + ":中断" ); } else { Debug.Log( result.Uid + ":終了" ); } } } |
まとめ
凝ったことをしなければ、数分で実装する事ができました!振動の強弱や振動終わりを感知するというのもやってみたいので、別の機会で試しみて記事に書こうと思います!
参考url
- https://docs.unity3d.com/jp/460/ScriptReference/Handheld.Vibrate.html
- https://qiita.com/DURIAN_JADE/items/3fdddb4ad19658f50539