【中学生・高校生におすすめ】Unityで3Dゲームを作ってみよう!(第4回)

【中学生・高校生におすすめ】Unityで3Dゲームを作ってみよう!(第3回)

(画像はUnity 2019.4 より)

Unity(ユニティ)とは、プログラミング初心者がプログラミングをはじめるのにおすすめな技術です。
より詳しく知りたい方はこちらの記事をご覧ください。

【初心者におすすめ】ゲーム開発で人気のUnityの特長を3つ紹介!

このコラムでは、プログラミング教室N Code Labo(Nコードラボ)がUnity初心者に向けて、実際にUnityをインストールし、どのようにゲームを作るのかという、Unityを使えるようになるまでの一連の流れを紹介します。

本コラムはUnity(ユニティ)を使った3Dゲーム制作の手順紹介の第4回です。
第3回の完成データを使いますので、これまでのコラムを読まれていない方は第1〜3回から取り組んでみましょう。

【中学生・高校生におすすめ】Unityで3Dゲームを作ってみよう!(第1回)
【中学生・高校生におすすめ】Unityで3Dゲームを作ってみよう!(第2回)
【中学生・高校生におすすめ】Unityで3Dゲームを作ってみよう!(第3回)

本コラムの構成

本コラムは以下の構成でお届けしています。

第1回
Unityのインストールと簡単なプログラムを制作する

第2〜4回(今回)
Unityで3Dゲームを制作する

第5回以降
3DゲームをWebサイト上で遊べる形にする

それぞれの所要時間は1時間程度です。

制作するゲームの概要

まずこれから作っていく「ボールを避けるゲーム」の概要を説明します。
ボールはビリヤードの球のように壁にぶつかると跳ね返り、ステージ内を動き回ります。
そのボールに一定時間、当たらないように避けるゲームです。
このゲームで作っていく機能は以下のとおりです。

・プレイヤー
・ステージとなる上下左右の壁
・動くボール
・タイマー
・試合開始の処理
・試合終了の処理

家庭用ゲーム機で遊ぶようなゲームにするにはメニュー画面やスコア記録の画面、BGMや効果音もあるとよいですが、まず、ゲームとして楽しむための必要最小限の機能から実装しましょう。

第1回で制作したファイルを開こう

まずは、第1回で作成したファイルを開きます。
インストールした「Unity Hub(ユニティハブ)」を開きます。

Unity Hubを開くと、現在制作中のゲームの一覧が表示されます。
前回作成したプロジェクトを選択します。プロジェクト名をクリックすることでファイルが展開されます。展開には長くて数分ほどかかることがあります。

動くボールを作ろう

第3回まででゲームのベースはできています。
しかし、これだと最初に落ちてくるボールを避けるだけのゲームになっているため、動くボールを避けるようなゲームにします。

これから、ボールがビリヤードのように壁を跳ね返っていくようにプログラムを作っていきます。

まずは、Ballについている重力の設定を外します。
Hierarchy ViewからBallを選択し、Inspector ViewのRigidbodyからUse Gravityのチェックボックスを外します。

これでゲームを再生すると、ボールは落ちてこなくなります。
重力の設定を外したことで、ボールに対する重力が働かなくなり、ボールは動かなくなります。
言い換えると、ボールに対してどこかの方向に力を加えれば動く、ということになります。この力のことをベクトルといいます。UnityではVectorという機能を利用することで、ベクトルを加えることができます。

※ベクトル:向きと大きさとを持った量のことで、高校数学や物理で学習します。ベクトルはドイツ語読みで、Unityで用いるVector(ベクター)は英語読みです。例えば何かを押すときの力は、どの方向に押すか(向き)、どのくらいの強さで押すか(大きさ)をベクトルで表すことができます。

Ballに力を加えるプログラムを作っていきます。
Hierarchy ViewからBallを選択し、Inspector Viewの最下部Add ComponentからNew Scriptを選択し、新しく「BallScript」を作ります。

BallScriptを作成したら、プログラムを書いていくので、BallScriptをVisual Studioで開きます。
書き加えるプログラムは次の通りです。

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

public class BallScript : MonoBehaviour
{
   public float speed = 20.0f;
   // Start is called before the first frame update
   void Start()
   {
       this.GetComponent().AddForce(
           (transform.up + transform.right) * speed,
           ForceMode.VelocityChange);  
   }

   // Update is called once per frame
   void Update()
   {
       
   }
}

「public float speed = 20.0f」はBallの速さを宣言しています。数が大きいほど速くなります。
「this.GetComponent().AddForce((transform.up + transform.right) * speed, ForceMode.VelocityChange); 」は力のかかる方向を定義しています。このプログラムは「void Start()」の{}内に記載されています。

※void Update():スクリプト実行中に毎フレームごとに実行する処理です。ゲームはアニメやパラパラ漫画のように1秒間に何十回、何百回、何千回ものプログラムを実行して成り立っています。その1回1回に実行されるのが「void Update()」です。例えば、攻撃がヒットしたかどうかを判定する当たり判定は毎フレームごとに実行される必要があります。当たり判定を一度だけ実行されるvoid Start()内に記述すると、スクリプト実行の瞬間に一瞬当たり判定が立ち上がり、その後は無敵になります。そうならないようvoid Update()内に記載します。
※ void Start():スクリプト実行時に最初に一度だけ実行する処理です。例えば、ステージ上に敵を配置するスクリプトがあった場合、敵の配置は1回だけ必要なのでvoid Start()内に記述することで1回だけ実行してくれます。これを仮にvoid Update()内に記述すると1秒間に数十体〜数百体が表示されるようになってしまいます。そのため、どのタイミングで動作してほしいのか考えてプログラミングする必要があります。

これでゲームを再生してみると、ボールが右上に進みますが、右上で跳ね返りません。これは右上に対して動こうとする力が働き続けているためです。また、空気抵抗もかかっているので、このままでは少しずつ減速してしまいます。そのため、まず空気抵抗を外し、次に壁に当たったら跳ね返るようにします。

Hierarchy ViewからBallを選択し、Inspector ViewのRigidbodyを以下のように設定します。

 Angular Drag:0(回転する際の抵抗を表します。)
 Constraints:
    Freeze Position:Zにチェックを付ける(方向を制限する軸を選択)
    Freeze Rotation:X,Y,Zにチェックを付ける(回転を制限する軸を選択)

次にボールが跳ね返るための設定をします。

Project ViewのAssets(アセッツ)を右クリックし、「Create」→「Physic Material」を選択します。

Projectに新しく緑のアイコンが出現するので、「Ball Physic Material」と名前を付けます。

次にHierarchy ViewからBallを選択します。Inspector Viewの「Sphere Collider(スフィア コライダー)」の「Material」という項目が「None」になっているので、ここに先ほど作った「Ball Physic Material」を入れていきます。Material右端の二重丸をクリックし、現れたウインドウからBall Physic Scriptを選択します。

これで、Ballに跳ね返りの設定をする項目を追加することができました。
次にBall Physic Scriptを編集して、跳ね返りの設定を加えていきます。

跳ね返りは次の要件とします。
以下を踏まえて、設定を加えていきます。

・摩擦がない
・跳ね返り時にエネルギーの損失がない
・衝突時の跳ね返りは最大

ProjectからBall Physic Scriptを選択し、設定を以下のように変更します。

Dynamic Friction:0
Static Friction:0
Bounciness:1
Friction Combine:Minimum
Bounce Combine:Macimum

これで、ゲームを再生してみましょう。ボールが跳ね返るようになっています。この状態で遊んでみてください。ルールはBallから逃げるだけです。Ballがなかなか速いので逃げるのが大変かもしれません。
ここまでやってきたことを応用すれば、Ballの速さ(speed)を調整することもできます。ぜひ、お好みの速さに変えてみてください。

ゲームスタートの処理を作ろう

さて、ここからはゲームとして楽しめるような機能の追加を行います。
まず、ゲームを再生するといきなりゲームが始まってしまって遊びづらいので、スペースキーを押したらゲームスタートとなるようにします。ゲーム開始までの手順は以下の通りです。

・「スペースキーを押してスタート!」の文字を最初に表示する
・スペースキーを押すと文字が消え、ゲームが開始する

始めに「スペースキーを押してスタート!」の文字を表示させます。表示までの手順はGame Overの画面を作った時と同じです。「ゲームオーバーの処理を作ろう」の手順を見ながら同じように作っていきます。
できあがるとHierarchy ViewにはCanvas→Panel→Textの親子関係が2つできあがります。そして、Inspector ViewのTextが「スペースキーを押してスタート!」に変わっています。

次にスペースキーを押したらゲームが開始されるようにします。
その下準備として、プレイヤーの操作とBallがいきなり動き始めないように止めておきましょう。そして、スペースキーが押されたら「Textの非表示」「playerの操作受付」「Ballを動かす」の3つが行われるようにします。

まず、スペースキーが押されるまでボールが動かないようにするために、スクリプトを書き加えていきます。Hierarchy ViewからBallをクリックし、Inspector ViewからBallScript.csを開きます。
そして、以下のプログラムを書き加えていきます。

bool start = false;
if (Input.GetKey(KeyCode.Space) && !start){
start = true;
}

void Update()内にあったプログラムは毎フレームごとに実行されるプログラムであることは先に紹介した通りです。今回は、新たに「スペースキーが1回押されていたら実行する」という形にプログラムを書き加えました。

bool start = false;でスペースキーが押されたかの判定をfalse(否定)の形で定義しておきます。

そしてif (Input.GetKey(KeyCode.Space) && !start){}が「スペースキーが押されていて、かつstartがtrueになっていない」ことを満たしているか判定するif文です。このif文は2つの条件を満たしている時に、Ballを動かすようにしています。
しかし、スペースキーを押したら実行するなら、条件は「スペースキーが押されたら」という条件一つで良いのではないか、と思われるかもしれません。

void Update()は毎フレームごとに実行されるので、スペースキーが押されると毎フレームごとにBallに力が加わり、移動速後が毎フレームごとに早くなっていきます。興味があればif (Input.GetKey(KeyCode.Space)){}に書き直して実行してみてください。一瞬でボールが画面から消え去り、はるか彼方に飛んでいきます。
これを防ぐために、一度だけ実行するようにstartがtrueではない時だけ実行するようにしています。1度実行するとstartはfalseからtrueに変わるので、2回目以降は実行されなくなります。

※ if文:条件分岐とも呼びます。「もし〜ならば〜」といった条件に応じて処理を行う際に使います。プログラミング言語によって書き方は多少異なりますが「if(条件){正しいときの処理}else{異なる場合の処理}」となります。映画館の料金で例えると大人料金と子供料金があります。仮に13歳以上が大人料金とすると、14歳は大人料金となります。このときif文を作ると「if(年齢が13歳以上){料金=大人料金}else{料金=子供料金}」となります。

これでゲームを再生すると、プレイヤーは動かせますが、Ballはスペースキーを押すまでは動かせなくなりました。

次に、プレイヤーもスペースキーが押されるまでは動かせないようにし、一緒に「スペースキーを押してスタート!」の文字も消すようにします。
今度はHierarchy ViewからPlayerをクリックし、Inspector ViewからPlayController.csを開きます。
そして、先ほどと同様にプログラムを書き加えていきます。
書き加えるのは以下のプログラムです。

public GameObject GameStartPanel;
bool start = false;
if (Input.GetKey(KeyCode.Space))
       {
           start = true;
           GameStartPanel.SetActive(false);
       }

       if (start)
       {
       }

public GameObject GameStartPanel;はゲームオーバーの表示と同じで、ゲームスタート時に消す文字列を登録するためのものです。bool start = false;は先ほどのBallScript.csで書いたものと同じです。if (Input.GetKey(KeyCode.Space)) {start = true;GameStartPanel.SetActive(false);}がスペースキーが押された時に動作するものです。startをtrue(肯定)に変え、GameStartPanel.SetActive(false);で「スペースキーを押してスタート!」の文字列を非表示しています。
そして、次のif(start){}でstartがtrueならプレイヤー操作を受け付けるようにしています。

ここまでのプログラムを一度保存します。この状態だと「スペースキーを押してスタート!」の文字列がまだ消えませんので、消えるようにUnity側の設定をします。
Hierarchy ViewからPlayerをクリックし、Inspector ViewからPlayerControllerを見ると「Game Start Panel」が新しく出現しているので、ここに「スペースキーを押してスタート!」のPanelを追加します。追加の方法はゲームオーバーのPanelを追加した時と同じです。
ここで分かったかと思いますが、同じPanelという名前のオブジェクトが2つ存在しており、片方がスタートのText、片方がゲームオーバーのTextです。このような同じ名前のものが混在していると分かりづらいので、「GameStartPanel」「GameOverPanel」といった名前に変更しましょう。最初に「ball」を「Ball」に変えたのと同じ手順でできます。

これでゲームを再生すると、スペースキーを押すまでは「スペースキーを押してスタート!」の文字列が表示され続けるようになり、スペースキーを押すと、文字列が消え、BallとPlayerが動くようになります。

まとめ

今回は、ボールから逃げるゲームを作っていきました。
かなりの作業量でしたが、ゲームを作ることの楽しさが詰まっていると思います。
しかし、このゲームはまだ完成ではありません。ゲームとして楽しむことはできますが、一度ゲームオーバーになるとやり直すことができません。また、Unity内で遊ぶことができても、実際に遊ぶのはスマホやゲーム機、Webサイト上になります。それぞれで遊べる形にすることをビルドといいますが、まだそれができていません。
次回は、実際にゲームとして遊べるようにします。
ぜひ、楽しみにしてください!

今回作ったプログラムの完成例はこちら((WebGLのページ))で公開しています。

ここまでの制作データを希望する方はN Code Laboまでお問い合わせください。
お問い合わせはこちらよりお願いいたします。

プログラミング未経験者がUnity(ユニティ)を体験できるプログラミング教室、N Code Labo(Nコードラボ)とは?

N Code Laboは、小学生・中学生・高校生に実践的なプログラミング教育を提供しているプログラミング教室です。新宿・秋葉原・横浜・大阪梅田の4教室で開講している通学コースと、オンラインで学ぶネットコースがあります。
カリキュラムはIT業界で活躍する人材を輩出しているN/S高等学校のプログラミング教育がベースとなっており、作品を作り上げる大切さや楽しさを味わいながら、一人ひとりの速度に合わせた少人数制でプログラミングが学べます。

パソコンやタブレットなど好きなツールで始められるため、プログラミング未経験者や、子どもでも自分オリジナルの作品が作れます。プログラミングをより実践的に学べるのがUnity。プログラミング教育の必要性が高まる今こそ、Unityの世界を体験してみてください。

ネットでも通学でも ゲームプログラミングなら N Code Labo

N Code Labo では、無料説明会を開催しています。
プログラミングを全くしたことがなくても、少しでもUnityに興味を持ったなら、ぜひ、無料説明会にお越しください。そして、プログラミングの楽しさを一緒に共有しましょう。

↓無料説明会の詳細、お申し込みは下のボタンから↓

無料説明会へのお申し込みはこちら