WeatherKitでの天気表示を実装した流れで、ボタンをタップしたときの手応えをもう少し良くしたいと感じ、Core Hapticsによる触覚フィードバックに挑戦しました。
1. UIFeedbackGeneratorと同じものだと思っていた
最初、標準のUIImpactFeedbackGeneratorで得られる「コツン」という振動と、Core Hapticsは同じ仕組みの延長線上にあるものだと思い込んでいました。
let engine = try CHHapticEngine()
try engine.start()
実際にはCore Hapticsは振動の強さ・鋭さ・時間変化を細かく組み合わせて独自の触覚パターンを設計できる、まったく別レイヤーの仕組みでした。標準のフィードバックジェネレーターは「決まったパターンを呼び出すだけ」なのに対し、Core Hapticsは「波形を自分で作る」感覚に近く、最初は勝手が違いすぎて戸惑いました。
2. HapticEngineの起動タイミングを誤っていた
触覚を再生するたびに毎回新しくCHHapticEngineを生成して起動していたところ、再生のたびにわずかな遅延が発生し、タップした瞬間の手応えとしては微妙にずれた感覚になってしまいました。
改善前の実装:
再生の都度エンジンを生成・起動
エンジンはアプリの起動時や画面表示時に一度だけ生成・起動しておき、以降は同じインスタンスを使い回す設計に変更しました。触覚フィードバックは「即座に反応する」ことが体験の質に直結するため、事前準備の設計がそのまま体感に響くと実感しました。
3. 実機とシミュレータで挙動がまったく違った
シミュレータ上で動作確認をしていたところ、コード上はエラーなく実行されているのに、当然ながら振動は一切体感できませんでした。
シミュレータの制約:
Taptic Engineのハードウェアが存在しないため振動自体が発生しない
これはバグではなく、そもそもシミュレータには触覚を生成するハードウェア(Taptic Engine)が搭載されていないための制約でした。触覚まわりの機能は必ず実機で確認する必要があると分かってからは、早い段階で実機を用意して確認するようにしています。
4. あらゆる操作に振動をつけて逆にうるさくなった
触覚フィードバックの効果に味をしめて、ボタンタップだけでなくスクロールや画面遷移など、あらゆる操作に振動を追加していったところ、かえって落ち着かない体験になってしまいました。
見直した基準:
「重要な操作の完了」や「エラー発生時」など意味のある場面に限定
触覚フィードバックは使えば使うほど良いものではなく、ユーザーに伝えたい情報がある場面(成功・失敗・重要な確認)に絞って使うことで、逆に効果が際立つと気づき、多くの箇所から触覚を削る作業を行いました。
まとめ
- Core Hapticsは標準のフィードバックジェネレーターとは別レイヤーの仕組みで、独自の波形パターンを設計できる
- HapticEngineは再生のたびに生成せず、事前に起動しておいて使い回す設計にする
- 触覚フィードバックはシミュレータでは体感できない。実機での確認が必須
- 多用しすぎると逆効果。意味のある場面に絞って使うことで効果が際立つ
地味な機能に見えて、設計次第で体験の質を大きく左右すると実感した実装でした。
次は、カスタムURLスキームでのアプリ間連携を実装してつまずいた話をまとめます。
本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。


コメント