UnityUnityメモ

【Unity入門】ボールをキャッチして投げ返す仕組みを作ろう!

Unity

はじめに

Unityを使って、ちょっとしたインタラクティブな遊びを作ってみたいな~と思ったこと、ありませんか?
今回はそんなあなたにぴったりの記事です!

この記事では、前からボールが飛んできて、それをプレイヤー(Cube)がキャッチして、スペースキーで投げ返す…という、まるでキャッチボールのような仕組みを作っていきます。

使うのは、Unityの基本的な機能と、少しのC#スクリプトだけ。
「まだUnityに慣れてないけど、何か面白いものを作ってみたい!」という初心者の方にもピッタリな内容です。

ゲームっぽさのある動きがすぐに体験できるので、作っていて楽しいですよ。
この記事を読みながら、一緒に手を動かしてチャレンジしてみましょう!




ステップ①:プレイヤーとしてCubeを作成しよう

まずは、プレイヤーとして操作するオブジェクトを作りましょう!今回はシンプルに「Cube(キューブ)」を使います。箱の形をしたオブジェクトですね。


🟦Cubeの作り方

  1. Unityのヒエラルキー(Hierarchy)ウィンドウで「右クリック」します。
  2. メニューから「3D Object」→「Cube」を選びます。
  3. すると、シーン上に白いキューブが出てきます。

このキューブが、プレイヤーキャラとして動くようになります!


🟦Cubeの位置を少し前に移動しよう

今作ったキューブは、たぶんシーンのまんなか(0,0,0)にいます。
でもこのままだと、あとでボールが飛んでくる位置とかぶってしまうので、ちょっとだけ手前に移動させておきましょう。

  1. Cubeを選んだ状態で、右側のインスペクター(Inspector)ウィンドウを見てください。
  2. 「Transform」っていう項目の中の「Position(位置)」がありますね。
  3. そこの「Z」の値を -3 とか -5 に変えてみてください。

これで、キューブが手前に動いて、ボールが飛んでくるスペースが確保できました!


▶ スクリプトを作成しよう(CubeMove.cs)

さて、プレイヤーとして使うCubeができたら、次はそれを操作できるようにしていきましょう!

今回はキーボードの矢印キー(↑↓←→)と、Wキー・Sキーで、Cubeを前後左右に動かせるようにします。

  1. Projectビューで右クリック → [Create] → [C# Script] を選択
  2. スクリプト名は「CubeMove」にしましょう!
  3. 作成した CubeMove.csCubeオブジェクトにドラッグ&ドロップして追加します

▶ スクリプトの中身を入力しよう

作成した CubeMove.cs をダブルクリックして開き、以下のコードを入力してください。

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

public class CubeMove : MonoBehaviour
{
    private float speed = 10.0f;

    void Update()
    {
        if (Input.GetKey(KeyCode.UpArrow)) {
            transform.position += transform.up * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.DownArrow)) {
            transform.position -= transform.up * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.RightArrow)) {
            transform.position += transform.right * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.LeftArrow)) {
            transform.position -= transform.right * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.W)) {
            transform.position += transform.forward * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.S)) {
            transform.position -= transform.forward * speed * Time.deltaTime;
        }
    }
}

▶ このコードの解説

  • Update() メソッドの中で、毎フレーム キーボードの入力をチェックしています。
  • transform.position += ~ を使って、Cubeを移動させています。
  • 矢印キー(↑↓→←)で上下左右に、WSで前後(Z軸方向)に移動可能です。
  • speed の値を調整すれば、移動速度を変更できます。

▶ 動作確認してみよう

  1. ここまでできたら、一度再生ボタン(▶)を押してCubeが自由に動かせるか試してみましょう!
  2. キーボードでCubeを操作してみましょう
     → 矢印キーやW/Sキーでスムーズに動くはずです!



② ボールの発射装置(GameObject)を作成しよう

さあ次は、プレイヤーに向かってボールが飛んでくる仕組みを作っていきましょう!

このステップでは、まず「ボールの発射地点」となる空のオブジェクトを作り、そこから一定の間隔でボールを飛ばすスクリプトを作っていきます。


▶ 空のGameObjectを作成して配置しよう

まずは発射装置となる空のオブジェクトを作成します。

  1. Hierarchy(ヒエラルキー)ビューで右クリック
  2. [Create Empty] を選択

作成されたオブジェクトにわかりやすい名前をつけましょう。ここでは「BallShooter」と名付けます。

そして、Cubeから少し離れた**前方(Z軸方向)**に移動させておきましょう。
たとえば、TransformのPositionを以下のように設定すると良いです:

項目
Position X0
Position Y0
Position Z20

▶ BallShotスクリプトを作成しよう

続いて、このBallShooterにスクリプトを追加して、定期的にボールを発射できるようにします。

  1. Assetsフォルダ内で右クリック → [Create] → [C# Script] を選択
  2. スクリプト名を BallShot に変更
  3. 作成したBallShotスクリプトをShooterオブジェクトにドラッグ&ドロップしてアタッチしましょう!

▶ BallShot.cs のコードを記述しよう

以下のコードを BallShot.cs に入力してください。

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

public class BallShot : MonoBehaviour
{
    public GameObject player;  // プレイヤー(Cube)
    public GameObject ball;    // 発射するボールのプレハブ

    void Start()
    {
        transform.LookAt(player.transform);  // Cubeの方向を向く
        StartCoroutine("Shot");              // コルーチン開始
    }

    void Update()
    {
        transform.LookAt(player.transform);  // 常にプレイヤーを向くようにする
    }

    IEnumerator Shot()
    {
        while (true)
        {
            var shot = Instantiate(ball, transform.position, Quaternion.identity);  // ボールを生成
            shot.GetComponent<Rigidbody>().velocity = transform.forward.normalized * 10.0f;  // 前方に発射
            yield return new WaitForSeconds(2.0f);  // 2秒待つ
        }
    }
}

このスクリプトのポイントは以下の通りです:

  • transform.LookAt を使って、常にCube(プレイヤー)の方向を向く
  • StartCoroutine を使って、2秒ごとにボールを発射
  • Instantiate でボールのプレハブを複製し、リジッドボディの速度を使って前方へ飛ばす

▶ スクリプトのパラメータを設定しよう

BallShot.cs には playerball という2つのパブリック変数があります。
以下のように設定しましょう:

  1. Hierarchyから CubePlayer フィールドにドラッグ
  2. プレハブ化した Sphere(ボール)を Ball フィールドにドラッグ(次のステップで作成)

✅ ここまでのまとめ

  • 空のGameObject「BallShooter」を作成して前方に配置
  • BallShot.cs を使って、2秒おきにプレイヤーの方向へボールを発射
  • プレイヤーのCubeとボールプレハブをスクリプトに設定

これで、プレイヤーに向かって定期的にボールが飛んでくる仕組みが完成しました!
次は、このボールをキャッチして投げ返す処理を作っていきましょう。




③ ボール(Sphere)を作ろう

次に、プレイヤー(Cube)に向かって飛んでくる**ボール(Sphere)**を作成し、キャッチ&投げ返す処理を実装していきましょう。


1. Sphere(球体)を作成

  • ヒエラルキーで右クリック → 「3D Object」→「Sphere」を選びます
  • 作成されたSphereを選んで、インスペクターで「AddComponent」をクリックして「Rigidbody」コンポーネントを検索して追加しましょう
  • UseGravityのチェックを外しておきます

2. スクリプトを作成してボールに追加

次に、ボールを発射する処理をスクリプトで書いていきます。

  • プロジェクトビューで右クリック →「Create」→「C# Script」を選びます
  • 名前を「SphereScript」にします
  • 作成したSphereScriptスクリプトをSphereオブジェクトにドラッグ&ドロップしてアタッチしましょう!

3. SphereScript.cs の内容

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

public class SphereScript : MonoBehaviour
{
    public bool isRelese;
    public Rigidbody rb;
    GameObject cube;
    GameObject StartPoint;

    void Start()
    {
        isRelese = true;
        rb = GetComponent<Rigidbody>();
        cube = GameObject.Find("Cube"); // プレイヤーを取得
        StartPoint = GameObject.Find("GameObject"); // 発射元を取得
    }

    void Update()
    {
        // スペースキーで投げ返す
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (!isRelese)
            {
                transform.parent = null; // Cubeとの親子関係を解除
                isRelese = true;
                rb.velocity = StartPoint.transform.position.normalized * 10.0f; // 発射元の方向へ投げる
            }
        }
    }

    void OnCollisionEnter(Collision col)
    {
        // Cubeに当たったらキャッチ(くっつける)
        if (col.gameObject.name == "Cube")
        {
            isRelese = false;
            rb.velocity = Vector3.zero; // 動きを止める
            transform.SetParent(cube.transform); // Cubeの子にしてくっつける
        }
    }
}

4. 処理のポイント解説

処理内容解説
OnCollisionEnter()Cubeにぶつかったかを検出する
SetParent()オブジェクトを親子関係にしてCubeにくっつける
Input.GetKeyDown(KeyCode.Space)スペースキーを押したときの処理
velocityリジッドボディの速度を指定してボールを飛ばす

5. プレハブにしておこう

今後ボールを複数生成するために、プレハブ化しておきましょう。

✅ プレハブ化の手順

Hierarchyビュー上のSphereは削除してOKです(Prefabから複製されるため)

作成したSphereをProjectビューにドラッグ&ドロップ

Projectビューに青いアイコンでプレハブが作成されます

これで、プレイヤーに向かって飛んでくるボールの準備が完了しました!
次はいよいよ、発射装置からボールを発射する処理を作っていきましょう!




④ ボール発射装置に設定をしよう

ここまでで、「プレイヤー(Cube)」と「発射されるボール(Sphere)」の準備が整いました。次は、発射装置となるGameObjectに必要なオブジェクトの参照を設定していきましょう。

🔧 BallShotスクリプトのインスペクターを確認

空のGameObjectに追加した BallShot.cs スクリプトには、以下の2つのフィールドがあります:

  • Player(Cube)
  • Ball(Sphereのプレハブ)

これらは手動でインスペクター上から設定する必要があります。

✅ オブジェクトの設定手順

  1. GameObject(発射装置)を選択します
  2. インスペクターを確認すると、BallShot スクリプトの中に
     PlayerBall というフィールドが表示されているはずです
  3. Player に Cube をドラッグ&ドロップします
    • ヒエラルキー上の Cube をそのまま Player 欄に入れます
  4. Ball に Sphereのプレハブをドラッグ&ドロップします
    • プロジェクトビュー内にあるプレハブ化された Sphere を使用してください
    • 間違ってヒエラルキー上の(元の)Sphereを指定しないように注意!

🧠 なぜ設定が必要?

BallShot.cs は、

  • 「どこに向かってボールを撃つのか(Player = Cube)」
  • 「どのPrefabを発射するのか(Ball = Sphere)」
    を明確にするために、スクリプト内で外部オブジェクトを参照しています。

インスペクターからこれらを設定しておかないと、スクリプトは何も発射せず、エラーになる可能性があります。




⑤ゲームプレイで確認しよう

ここまで準備ができたら、いよいよゲームを再生して、実際にボールをキャッチして投げ返す動きを見てみましょう!

まずはUnityエディターの上にある「▶(再生)」ボタンをクリックしてゲームをスタートしてください。

すると……

✅ 奥にあるGameObjectから、2秒おきにボールが飛んできます!
✅ ボールがCube(プレイヤー)にぶつかると、ピタッとCubeの前にくっつきます。これはボールがCubeの子オブジェクトになった状態です。
✅ そしてスペースキーを押すと……ボールがビューン!と発射元の方へ飛んでいきます!

ちゃんと「キャッチして→投げ返す」動作ができていれば成功です!

これで、簡単なキャッチ&リリースの動作が完成しました!


🔍もしうまくいかないときは?

  • ボールが飛んでこない → BallShot.csの設定(Prefabが割り当てられているか)を確認しましょう。
  • ボールが当たってもくっつかない → CubeとSphereにColliderがついているか、SphereにRigidbodyが追加されているか確認してください。
  • スペースキーを押してもボールが飛ばない → SphereScript.csのisReleseの状態や、発射方向の設定を見直してみましょう。

このように、Unityの基本機能だけで簡単なキャッチボールシステムを作ることができます。




🔍 補足・応用編

▶ タグを使って当たり判定を管理する

現在のコードでは、オブジェクト名が "Cube" の場合にキャッチするようにしていますが、大規模なプロジェクトではタグを使った方が管理がしやすくなります。

変更手順:

  1. Cube に「Player」などのタグを設定(インスペクター上部の「Tag」→「Add Tag」→ 新規タグを作成し、Cubeに割り当て)
  2. SphereScript.cs の衝突判定部分を以下のように変更:
void OnCollisionEnter(Collision col) {
if (col.gameObject.tag == "Player") {
isRelese = false;
rb.velocity = Vector3.zero;
transform.SetParent(cube.transform);
}
}

タグを使うことで、名前に依存せず、他のプレイヤーオブジェクトでも再利用しやすくなります。


▶ ボールが一定時間経つと消えるようにする

ボールがたくさん発射されると、シーン内にオブジェクトが溜まり続け、パフォーマンスに影響します。
発射されたボールに寿命タイマーを設定して自動で削除するのがおすすめです。

追加コード(SphereScript.cs内のStart()に追記):

Destroy(gameObject, 10.0f); // 10秒後に自動削除

これで、キャッチされなかったボールは自動的に消えるようになります。


▶ 発射元を複数にしてみよう

発射装置(GameObject)を複製して、異なる位置に配置することで、複数方向からボールが飛んでくるようになります。
スクリプトはそのままで問題ありません。それぞれの GameObject に BallShot.cs を追加して、playerball を設定するだけです。

応用アイデア:

  • ボールのスピードをランダムにする
  • 発射間隔をバラバラにする
  • 一定スコアで難易度が上がるなど、ゲーム要素を追加する

▶ エフェクトやサウンドで演出を強化

よりゲームっぽくするために、以下のような演出を加えると面白くなります。

  • キャッチ時に光るエフェクトを再生
  • 投げ返した時にSEを鳴らす
  • ヒットエフェクトで手応えを演出

UnityのParticle SystemやAudioSourceを使えば、簡単に追加できます!




📝 まとめ

今回は、Unityでキャッチボールのような仕組みを作成する方法を紹介しました。

プレイヤー(Cube)が移動できるようにし、2秒ごとに飛んでくるボール(Sphere)をキャッチして、スペースキーで投げ返すという一連の流れを実装しました。

このチュートリアルで学べたポイントは以下の通りです:

  • Rigidbody を使った物理演算による移動処理
  • OnCollisionEnter() を使った当たり判定
  • transform.SetParent() によるオブジェクトの親子関係の操作
  • Coroutine を使った一定時間ごとの処理
  • Instantiate() によるプレハブの複製と使用方法

仕組み自体はシンプルですが、Unityでゲーム的な動きを作るうえで基礎的かつ重要なテクニックが詰まっています。

ぜひ、今回作ったサンプルをベースにして、以下のような応用にもチャレンジしてみてください:

  • ボールを複数同時に投げる
  • ターゲットのスコア判定を追加する
  • 投げ返す方向をマウスや照準でコントロールする

Unityの学習は、まず「動かしてみる」ことが大切です。
ぜひあなたなりのアレンジを加えて、面白い仕組みに発展させていきましょう!




よくある質問(FAQ)

Q
ボールがCubeに当たってもキャッチできません。なぜですか?
A

以下の点をチェックしてみてください。

  • SphereにRigidbodyがアタッチされているか
  • CubeとSphereのCollider同士が衝突できる設定になっているか(どちらもColliderが必要です)
  • SphereScript.cs の OnCollisionEnter() にあるCubeの名前が「Cube」と一致しているか(大文字小文字も正確に)
Q
スペースキーを押してもボールが投げ返されません。
A

ボールをキャッチしていない状態では、投げ返し処理は動作しません。
まずCubeに当たってボールが「くっついて」いる状態で、スペースキーを押してみてください。また、スクリプト内で StartPoint(=発射元GameObject)の設定が正しく行われているかも確認しましょう。

Q
ボールが発射される方向がおかしいです。Cubeに向かっていません。
A

GameObject(発射装置)の向きを毎フレーム更新しているか確認してください。
BallShot.cs 内で transform.LookAt(player.transform);Update() にも書いておく必要があります。

void Update()
{
transform.LookAt(player.transform);
}

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