このサイトは「プログラミング教室・ファイブボックス」の Unity学習カリキュラム ステップ6 「あつ森風、フィッシングゲーム作成」のフェーズ1になります。
他のサンプルカリキュラム
Step1 Unityの基本
Step2 JumpGame
このプロジェクトでは以下のような作品を作ります。
あつ森風、フィッシングゲーム作成 (クリックでゲーム開始)
フェーズ1 仕様確認と環境構築
1-1,ゲームの仕様確認
この作品の通常のフローは以下の通りです。
通常のフロー
❶魚を発生させる(乱数で魚の種類や大きさ、進行方向、ターン回数決定)
❶エサをセット(初期値は10個とし釣れるごとに1つ減少。なくなったら購入)
❷釣り糸を垂らす(エサと釣り竿の先端をRayでつなぐ)
❹魚の口先とエサがぶつかったら、特定の確率でヒットする
❺釣り上げる(釣り竿の先端にエサが触れたら魚を獲得)
❻釣った魚を記録する
さらに次のオプション機能を追加
オプション機能
❶進行中のゲーム内容のセーブとロード(釣った魚、所持金、エサなど)
❷ランキング表示機能(大きさ順、金額順、釣った数の順など)
❸釣った魚の図鑑機能(釣った数、合計金額など)
❹エサの購入
❺釣り竿の購入
❻ステージ管理
これらのフローと機能を順に作成していきます。
1-2,プロジェクトの作成
2D のプロジェクトを指定し、プロジェクト名に 「FishingGame」 などの適当な名前を指定、保存場所に任意の場所を指定し、「プロジェクトを作成」ボタンを押します。
Webブラウザでゲームをプレイできるように、環境を変更します。
上部のメニューから、File => Build Settings をクリック。
「WebGL」 を選択して 「Swich Platform」 をクリック。
さらに 「Player Settings」 のメニューを展開。
「Player」 => 「WebGL」アイコンタグ を選択 => 「Resolution」 の項目から
[Default Canvas Width] = 960
[Default Canvas Height] = 600
に指定されていることを確認します。
作成されたプロジェクトに、初期状態で用意されている「Sceneフォルダ」、フォルダ内の 「SampleScene」 の名前をそれぞれ次のようにに変更しておきます。
フォルダ「Scene」=> 「01_Scenes」
Scene「SampleScene」=> 「GameScene」
Asset 内に次の3つのフォルダを用意しておきます。
「02_Scripts」 => スクリプトファイルを保存するフォルダ
「03_Predabs」 => プレファブを保存するフォルダ
「04_Sprites」 => 画像ファイルを保存するフォルダ
その他の設定やフォルダ作成は、必要に応じて都度行っていきます。
これでプロジェクト作成の準備は完成です。
1-3,魚の配列作成
1-3-1,テキストファイルの用意
素材は こちら から取得してください。
Download後、メニューバーの「Asset」⇒「Import Package」でDownload下ファイルを指定し、取り込みます。
この作品では多くの魚のデータを使用しますので、別途用意するテキストファイルからデータを取り込みます。
取り込むデータは以下の通りです。
データ | 変数名 | 説明 |
---|---|---|
Name | f_Name | 魚の名前 |
Size | f_Scale | 魚の基準の大きさ |
ImgSize | f_ImgScale | 表示上の基準の大きさ |
Speed | f_speed | 魚の泳ぐ速さ |
Price | f_Price | 魚の基準の価格 |
Level | f_Level | 魚をヒットさせる難易度(大きいほど難易度が高い) |
Sprite | f_Img | 魚の画像(別途用意) |
FishData
上のようなイメージで作成します。
Unityの取り込むのは、タイトル行を除いたテキストファイルとなります。
テキストファイルは以下の条件で作成します。
ファイル名 :fish.txt
区切り :タブクリり
文字コード :utf-8
Aseets 内に「Resources」という名前のフォルダを作成し、用意した [fish.txt] を格納します。
画像素材は各自用意して頂くか、教室で用意した素材を取り込んで使ってください。
取り込んだ魚の画像は、事前に作成した「04_Sprits」というフォルダの中に「fish」というフォルダを作成し、その中に保存しておきます。
1-3-2,テキストデータ取り込み
このフェーズでは用意したテキストデータを取り込んで、2次元配列として保管します。
まずは、Aseets 内に配置した「02_Scripts」 フォルダ内に[GameManager] というスクリプトファイルを作成します。
さらにHierarchy上に 「GameManager」 というオブジェクトファイルを作成し、スクリプトファイル 「GameManager.cs」 をアタッチしておきましょう。
データ取り込みで行う処理の流れは以下の通りです。
❶ [fish.txt] 内のテキストデータを全部取り込む
❷ 取り込んだテキスト1行1行を1次配列に入れ込む ⇒ 108個の要素を含む1次配列
❸ テキストの行数と列数を取得して最終的に入れ込む2次配列のサイズを決める
❹ 2で取り込んだ1行1行を、for文を使ってタブ区切りで2次配列に変換する
[GameManager.cs] を立ち上げて、以下のコードを記述します。
まず、NameSpace に使用するシステムを追加します。
using System;
続いて使用する変数を用意します。
string[] textSauce; //テキストの加工前の一行を入れる変数
public string[,] fishdata; //テキストの複数列を入れる2次元配列
int rowLength; //テキスト内の行数を取得する変数
int columnLength; //テキスト内の列数を取得する変数
ここでは最終的なデータが格納される配列、fishdata[,] のみ public変数 にしています。
これは後に他classからも参照したいためです。
さらにデータ取り込みの関数 Initialization() を作成します。
void Initialization() //データ取り込み処理
{
//fish.txtのデータを取得するインスタンスを作成
TextAsset textasset = new TextAsset();
//Resourcesフォルダから対象のテキストファイルを取得
textasset = Resources.Load("fish", typeof(TextAsset)) as TextAsset;
//string型の変数を用意して、上で取得したテキスト全体を入れる
string TextLines = textasset.text;
//Splitで一行づつを代入した1次配列を作成、(改行で分けるので1行の文字列となる)
textSauce = TextLines.Split('\n');
//行数と列数を取得
columnLength = textSauce[0].Split('\t').Length; //タブ区切りで分けられたブロック数⇒6
rowLength = textSauce.Length; //データ数⇒108
fishdata = new string[rowLength, columnLength]; //2次配列を定義 [108,6]
for (int i = 0; i < rowLength; i++)
{
//textMessageをタブごとに分けたものを一時的にtempに代入,
//temp[0]⇒魚名、[1]⇒大きさ、[2]⇒Spritの大きさ、[3]⇒速さ、[4]⇒価格、[5]⇒難易度
string[] temp = textSauce[i].Split('\t');
for (int j = 0; j < columnLength; j++) //Dataの数だけ繰り返す
{
//2次配列fishdata[,]にタブごとに分けたtempを代入していく
fishdata[i, j] = temp[j];
}
}
}
作成した関数を Start関数 内で起動させます。
void Start()
{
Initialization();
}
実際に起動させてみましょう。
Inspector の表示形式を 「Debug」 にすると、詳細を確認することができます。
「GameManager」のInspectorで GameManager(Script) の [TextSouce],[RowLength],[ColumnLength] がそれぞれ取り込んだ値と同じか確認することができます。
Inspector の表示形式を 「Normal」 に戻しておきましょう。
問題1
作成した配列に、正しくデータが格納されているか、foreach()関数を使って表示させてみましょう。
答え1
void Initialization
{
/*省略*/
foreach (string s in fishdata)
{
Debug.Log(s);
}
}
foreach() 文 の記述方法は以下の通りです。
foreach( 型名 オブジェクト名 in コレクション) {
処理文
}
foreach文ではfor文のように、インデックス番号を指定する int型変数 i を定義したり、それをループごとにインクリメント(i++)する必要はありません。
また、コレクションの要素数を取得する必要もありません。ですので、簡潔に記述することができて便利です。
このプロジェクトでは、この後も多くの配列やリストを作っていきます。
リストから任意のデータを取り出す方法や、確認する方法をマスターしておきましょう。
1-3-3,魚のスプライト
魚のスプライトは、GameManagerクラスにスプライト用の配列を作成し、Unity側からセットします。
では 「GameManager.cs」 を立ち上げて、配列を追加します。
public Sprite[] fishSprit; //魚のイラストの配列
「GameManager」 の Inspector に宣言した FishSprite[]が表示されるので、index 数に 108 を入力
後は「fish.txt」と同じ順番で、要素に魚のスプライトをセットしていけばいいだけです。
魚のスプライト名は、fish.text の魚の名前と同じになっていることを確認しながら進めましょう。
順番を間違えたり、スプライト名が違ったりすると、この後作る機能の一部が正しく動かない状態になります。
完成イメージは下のような状態です。
1-4,背景画像作成
ここからステージ上のオブジェクトを作成、配置していきます。
まずは背景画像を作成します。
背景は画面下部に「海」の素材を、上部に「空」の素材をセットします。
1-4-1,素材の準備
「海」の素材
「海」の素材は「フリー素材」を使っています。
ベースとなる画像を1つ、ベースの前面を左右に揺らし画像が動いているように見せる画像を1つ用意します。
「04_Sprits」フォルダの中に「BackGround」 フォルダを作成し、そこに入れておきます。
「空」の素材
「空」の画像は AssetStore から取得します。
「AllSky」 の無料版を選択し、取り込んでおきます。
1-4-2,「海」の背景をセット
まずは、ゲーム画面の表示サイズを設定します。
[1-2]で選択したWebGL上での見え方に統一しておきましょう。
「Game」タブ を選択し、画面サイズ変更メニューから一番下にある 「+ボタン」 を押します。
展開された 「Add」メニュー で以下のように指定。
[Type] => Fixed Resolution
[Width & Height] => 960 × 600
最後に 「OK」ボタン を押して確定。
続いてHierarchy上で、オブジェクトを作成。
UI => Image を選択。
生成された「Image」を Inspector から設定します。
❶名前を 「SeaImage」 にリネーム
❷RectTransformコンポーネントで位置、サイズを下のように指定。
❸Imageコンポーネントで「Source Image」に取り込み済みの 「SeaImg1」 を指定。
この段階では以下のような表示となっているはずです。
1-4-3,「空」の背景をセット
空の背景には、AssetStoreから取得した「AllSkyFree」の「Epic_BlueSunset」フォルダの中の「Epic_BlueSunset_Cam_0_Front+Z」という素材を使用したいと思います。
ただこのままでは使用できないので、選択した画像の Inspector から画像タイプの修正を行います
Texture Type => Sprit(2D and UI)
最後は 「Apply」ボタン で確定。
先程の「海」の画像の追加と同様に、Canvas上に新たな Image のオブジェクトを追加します。
海の画像よりも奥のレイヤーにしたいので、「Canvas」の子要素の一番上に配置します。
生成された「Image」を Inspector から設定します。
❶名前を 「SkyImage」 にリネーム
❷RectTransformコンポーネントで位置、サイズを下のように指定。
❸Imageコンポーネントで「Source Image」に取り込み済みの 「Epic_BlueSunset_Cam_0」 を指定。
以下のようなイメージとなっています。
1-4-4,「波」の背景をセット
波はプログラムから動かしますが、その為には「worldSpace」に指定する必要があります。
Scene上に配置されるオブジェクトと同じ「worldSpaceに位置する」という意味になります。
しかしもともとのCanvasはとても大きいため、ベースの大きさを縮小します。
「Canvas」の Inspector から以下のパラメータを修正します。
❶RectTransformコンポーネント
・PosZ の値を 10 に指定
※今後の課題で作る釣り糸を表示するために必要になります
・Scale の X Y をそれぞれ 0.04 に指定
❷Canvasコンポーネント
・RenderMode を World Space
・EventCamera を Main Camera
Hierarchy上に新たな「image」オブジェクトを作成し、Canvasの子要素の一番下 に配置します。
Inspectorから以下のように設定します。
❶名前を「WaveImage」に指定
❷RectTransformコンポーネント
Width => 1500 左右に揺らすので、画面幅より大きめに指定します
Height => 500
PosY => -91 ちょうど海面と同じ高さになるように調整します
❸Imageコンポーネント
Source Image => 「Wave」 取得した画像を使います
Color => A(Alpha値:不透明度)を 0.5 後ろの海の画像が透けて見えるようにセット
さらに、RigidBody2Dコンポーネントを追加します。
スクリプトファイルでのみ動かすので、Body Type を 「Kinematic」 にしておきます。
続いて波を動かすスクリプトファイルを作成します。
「02_Scripts」フォルダ内に、[ WaveManager ]スクリプトファイルを作成してください。
作成した 「WaveManager.cs」 は 「WaveImage」 にアタッチしておきます。
問題2
RigidBody2D を使って、「WaveImage」 を波のように左右に揺らし続けるプログラムを作ってみましょう。
答え2
Rigidbody2D rb2d;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
rb2d.velocity = new Vector2(Mathf.Sin(Time.time / 2), 0);
//Time.time で周期をとっていますが、早すぎるので2で割って調整しています。
}
これで背景の調整は完了しました。
ではここで、WebGlで正しく表示されるか確認しておきます。
上部メニューの「File」から 「Build And Run」 を選択。
初回のみファイルを保存する場所を聞いてくるので、任意のフォルダを指定します。
初回は特に時間がかかるので、余裕を見て実行します。
成功すると以下のようにブラウザ上でゲームのSceneを確認することができます。
最後までご覧いただき、ありがとうございます。
引き続きカリキュラムを参照したい場合は、「ファイブボックス」までお気軽にお問い合わせください。
https://www.fivebox.info/
Mail:ueda@fivebox.info
Tel:0268-71-7294
© 2020 - 2022 FiveBox CORPORATION.