学習記事一覧 · Unity教科書_Unity6対応

補足:SwipeCar 付属サンプル更新版(コード対応)

題材・出典: SBクリエイティブ刊『Unityの教科書 Unity 6完全対応版』付属サンプルに基づく学習解説です。書籍の代替提供を目的とせず、コード掲載は学習上必要な範囲(必要最小限)にとどめます。利用条件は書籍付属案内・Readme・出版社サポート情報に従ってください。本シリーズ目次(書籍・著作の注記)

対象読者:Chapter 4 SwipeCarゲーム入門 を読み終えた方・付属サンプルを Unity で開いている方
この記事は 本編とは別ページ の補足です。『Unityの教科書』付属サンプル(Chapter 4 / SwipeCar)を更新した版のコードに、ブログ本編の記述を合わせるためのものです。

マウスをスワイプして車を動かし、フラグへ近づける様子(イメージ)


記事の目次


なぜこの記事があるか

SwipeCarゲーム入門(本編) は、スワイプで車を動かしつつ距離を表示するところまでを、短いコードで追いやすい形にした説明になっています。

一方、手元の 付属サンプルプロジェクト(例:Sample_PC/chapter4/SwipeCar)は、教材の改訂・メンテナンスに合わせて次のような処理が 足されています

  • スワイプで走り出したかどうかの isStart フラグ
  • 車がほぼ止まったときに speed を 0 にそろえる処理
  • result 用の TextMeshPro に、ゴールまでの距離に応じた ポイントを表示

本編のコードブロックはあえて据え置き、更新版の全文は このページ にまとめます。学習の流れは本編 → 必要に応じて本ページ、で問題ありません。


本編(04)との違い

項目 本編(04)のコード 付属サンプル更新版
CarController.speed float(非 public) public float(他スクリプトから参照)
スワイプ開始の扱い 毎回 speed を代入 Mathf.Abs(swipeLength) > 0.1f のときだけ isStart = true
停止後の速度 減速のみ Abs(speed) < 0.001fspeed = 0
GameDirector distance のみ更新 result を追加し、停止後に ポイント表示

シーン側では、名前 result の UI オブジェクト(TextMeshProUGUI)が GameDirector から Find される想定です。


プロジェクトの構成

付属サンプルでは、プレイ用シーンは Assets 直下の GameScene.unity です(Assets/Scenes/SampleScene.unity が残っている場合はテンプレート用のことがあります)。

Assets/
  ├── car.png …(略:本編と同様の素材)
  ├── CarController.cs
  ├── GameDirector.cs
  └── GameScene.unity   # プレイ用(distance / result などを配置)

更新版のコード全体

CarController.cs

using UnityEngine;
using UnityEngine.InputSystem;  // 入力を検知するために必要!!
public class CarController : MonoBehaviour
{
    public float speed = 0;
    public bool isStart = false;
    Vector2 startPos;
    void Start()
    {
        Application.targetFrameRate = 60;
    }
    void Update()
    {
        // スワイプの長さを求める
        if (Mouse.current.leftButton.wasPressedThisFrame)
        {
            // マウスをクリックした座標
            this.startPos = Mouse.current.position.value;
        }
        else if (Mouse.current.leftButton.wasReleasedThisFrame)
        {
            // マウスを離した座標
            Vector2 endPos = Mouse.current.position.value;
            float swipeLength = endPos.x - this.startPos.x;
            // スワイプの長さを初速度に変換する
            this.speed = swipeLength / 500.0f;
            // 画面上のスワイプ量(ピクセル)で開始判定(速度の閾値より任せやすい)
            if (Mathf.Abs(swipeLength) > 0.1f)
                this.isStart = true;
            // 効果音再生
            GetComponent<AudioSource>().Play();
        }
        transform.Translate(this.speed, 0, 0);  // 移動
        this.speed *= 0.98f;                    // 減速
        // 十分遅くなったら 0 にそろえる(止まった判定を確実にする)
        if (Mathf.Abs(this.speed) < 0.001f)
            this.speed = 0f;
    }
}

GameDirector.cs

using TMPro;    // TextMeshProを使うために必要!
using UnityEngine;
public class GameDirector : MonoBehaviour
{
    GameObject car;
    GameObject flag;
    GameObject distance;
    GameObject result;
    void Start()
    {
        this.car = GameObject.Find("car_0");
        this.flag = GameObject.Find("flag_0");
        this.distance = GameObject.Find("distance");
        this.result = GameObject.Find("result");
    }
    void Update()
    {
        CarController cc = this.car.GetComponent<CarController>();
        float length = this.flag.transform.position.x - this.car.transform.position.x;
        this.distance.GetComponent<TextMeshProUGUI>().text = "Distance:" + length.ToString("F2") + "m";
        if (cc.isStart && Mathf.Abs(cc.speed) < 0.001f)
        {
            if (length < 0f)
                this.result.GetComponent<TextMeshProUGUI>().text = "0 Point";
            else
            {
                int pts = (int)Mathf.Max(0f, (14.5f - length) * 100f / 14.5f);
                this.result.GetComponent<TextMeshProUGUI>().text = pts + " Point";
            }
        }
    }
}

追加された挙動の要点

public にした理由
GameDirectorGetComponent<CarController>()speedisStart を読むためです。本編では「距離だけ」だったので speed が非 public でも足りましたが、更新版では 停止判定とセットでスコアを出す必要があります。

isStartAbs(speed) < 0.001f
「一度はスワイプで走り始めたあと、かつ摩擦でほぼ止まったタイミング」だけ結果を確定します。まだスワイプしていない初期状態で result が書き換わるのを防ぎます。

ポイント計算
length は「フラグの X − 車の X」です。length < 0 はゴールを通り過ぎた側の扱いで "0 Point"。それ以外では
(14.5 - length) * 100 / 14.50 未満にならないよう Max で切り、近いほど高得点になるイメージです(14.5 はシーン上のコース長に合わせた定数)。


まとめ

  • 本編 04-SwipeCarゲーム入門 で基礎の流れを押さえたうえで、付属フォルダのコードが進んでいるときは、このページの 更新版ソースと照らし合わせてください。
  • 差分の中心は CarController の状態(isStart・停止時の speed = 0 と、GameDirectorresult 表示です。

本編の カスタマイズ で「スコアを足してみる」前提の読者には、更新版サンプルはすでに近い要素を含んでいると捉えてよいでしょう。