【Unity】スマホの加速度センサーでボールを動かす

【Unity】スマホの加速度センサーでボールを動かす Unity
記事内に広告が含まれています。
スポンサーリンク

記事作成時の動作環境

  • Unity 2022.3.1f1

加速度センサーとは?

加速度センサーは「スマホが机に置かれているか」「手で持っているか」などの状態を検知するのに使われています。

他にもシェイク機能や歩数計、画面の向き(縦向き・横向き)に合わせた回転などでも使われるようです。

加速度センサーではXYZの「軸」の動きを取得できます。

ジャイロセンサー(角速度)とは別物です。

加速度センサーでボールを動かす

今回はシンプルに、加速度センサーを使ってボールを移動させてみます。

Unityのプロジェクトテンプレートには「3D Mobile」を選択し、動作確認はAndroidスマホを使用しています。

スマホの傾きに合わせてボールを移動させる

加速度センサーを使うには「Input.acceleration」を使用します。

動作確認のため、まずはUnityのマニュアルから持ってきたコードをそのまま試してみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AccelerometerTest : MonoBehaviour
{
    float speed = 10.0f;

    void Update()
    {
        Vector3 dir = Vector3.zero;

        dir.x = -Input.acceleration.y;
        dir.z = Input.acceleration.x;

        if (dir.sqrMagnitude > 1)
            dir.Normalize();

        dir *= Time.deltaTime;

        transform.Translate(dir * speed);
    }
}

ヒエラルキービューで「3D Object > Sphere」を追加し、スクリプトをアタッチします。

球が回転しているかどうか分かりやすくするためにボーダー柄のマテリアルをつけてみました。

ビルドして動かしてみると、動きはしましたが傾けた方向とボールの移動する方向が合っていませんでした。

現状、縦持ち横持ちに関係なく以下のように動いています。

スマホを傾ける方向ボールの移動する方向
手前
手前

このままだと操作しづらいので、スクリプトの以下の部分を修正します。

//dir.x = -Input.acceleration.y;
//dir.z = Input.acceleration.x;
dir.x = Input.acceleration.x;
dir.z = Input.acceleration.y;

Input.accelerationの値はスマホが水平な場所に置かれている状態を基準に、手前に傾けると(0,-1,0)、奥に傾けると(0,1,0)となるため、dir.zの値にInput.acceleration.yを使用するようにします。

また、右に傾けると(1,0,0)、左に傾けると(-1,0,0)だったので、dir.xはInput.acceleration.xを代入しています。

これでスマホの傾きとボールの移動方向が一致するようになりました。

壁と床を追加する

PlaneとCubeのオブジェクトを追加し、壁と床を配置します。

ボールには「Rigidbody」アタッチします。

ゲーム画面も横向きにして、カメラはステージを上から見下ろすような位置に変えました。

ビルドして動かすと、壁にぶつかってからの挙動がおかしくなってしまいました。

これではまともに遊べなくなってしまうので、スクリプトを修正します。

//transform.Translate(dir * speed);
transform.Translate(dir * speed, Space.World);

transform.Translateの引数を省略すると「Space.Self」が適用されます。

Selfの場合ローカルの軸が基準となるため、ボールの向きが変わると移動方向も変わり、挙動がおかしくなっていました。

「Space.World」を指定してワールド座標系を基準にすることで、壁にぶつかってボールの向きが変わっても移動方向はそのままになります。

ボールを回転させる

今のままでは壁に当たるまでボールは全く回転していない状態です。

せっかくなので、移動に合わせてボールが回転するようにしてみます。

Updateに以下の記述を追加します。

transform.Rotate(new Vector3(dir.z, 0, -dir.x) * angularSpeed, Space.World);

移動で使っているdirをそのまま使うと回転方向が合わなかったので場所を変更・反転しています。

最終的なスクリプト

完成したスクリプトがこちら。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AccelerometerTest : MonoBehaviour
{
    float speed = 10.0f;
    float angularSpeed = 360.0f;

    void Update()
    {
        Vector3 dir = Vector3.zero;

        dir.x = Input.acceleration.x;
        dir.z = Input.acceleration.y;

        if (dir.sqrMagnitude > 1)
            dir.Normalize();

        dir *= Time.deltaTime;

        transform.Translate(dir * speed, Space.World);
        transform.Rotate(new Vector3(dir.z, 0, -dir.x) * angularSpeed, Space.World);
    }
}

動かしてみると、壁に当たってもどこかに飛んで行ったりせず、思った通りの動きをしてくれるようになりました。

さいごに

スコアアイテムや障害物などを追加していけば玉転がしゲームが作れます。

ジャイロセンサーでの実装についても紹介したかったのですが、使っているAndroidがまさかのジャイロ非搭載機種でした。

試していないので何とも言えませんが、公式ドキュメントを見た感じだとジャイロセンサーを使う方が加速度センサーよりも圧倒的に楽に実装できそうな気がします。

Macを買ってiOSのビルドが出来るようになるか、ジャイロ搭載のAndroidが手に入ったら、ジャイロセンサーでの実装も試してみたいです。

加速度センサーについては後述の参考サイトの解説が分かりやすいと思ったので、気になる方は読んでみてください。

参考サイト

コメント

タイトルとURLをコピーしました