スイカゲーム風「ベジタブルゲーム」の作り方、このフェーズでは同じ種類の野菜が接触した際に、結合し次の野菜に進化する動きを作成します。
ユニティルーム サンプルの投稿ゲーム
6,野菜の進化
6.1,大きさの配列
野菜の大きさは配列を使って管理していきます。配列はGameManagerクラスで管理します。
配列名 | 型 | アクセス | 説明 |
v_size | float | public | 野菜の大きさを順番に格納 |
GameManager.cs を立ち上げて配列の宣言と初期値の指定を行います。
サンプルでは以下のコードの順番で大きさを指定しましたが、各自お好みに合わせ、大きさを調整してみてください。
GameManager.cs
public float[] v_size = new float[12]; //野菜の大きさを管理する配列
void Start()
{
//記述済みコード省略
v_size = new float[] { 0.2f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f,
0.8f, 1.0f, 1.2f, 1.4f, 1.6f, 1.8f }; //大きさの初期値を格納
}
6.2,大きさの指定
クレーンに配置されたタイミングで、野菜の大きさを更新します。
vegetableManager クラスで作成済みの関数:SetCrane() を以下のように修正します。
vegetableManager.cs
public IEnumerator SetCrane()
{
/*if (type == MOVETYPE.NEXT) //記述済み
{
yield return new WaitForSeconds(0.8f); //記述済み
type = MOVETYPE.READY; //記述済み */
//野菜の大きさを指定した大きさに変更
transform.localScale = Vector3.one * gm.v_size[index];
/*transform.SetParent(crane.transform); //記述済み
Invoke("SetIsReady", 0.2f); //記述済み
} */
}
Craneの子要素になる前 に大きさの変更を記述します。
※Craneの子要素になった後に指定した場合、Craneに対するローカルサイズになってしまいます。現状 Crane の Transform.Scale が0.2倍になっているので、より小さく表示されてしまいます。
トレイからクレーンに移動したタイミングで、野菜それぞれ指定した大きさに変更することを確認しておきましょう。
6.3,野菜生成プログラムの修正
GameManagerクラスに野菜を生成するプログラムを作成していますが、現段階で初期生成(トレイ上に生成)のパターンのみ作ってあります。ここで進化版も作成しておきましょう。
GameManager.cs を立ち上げて、関数:CreateVegetable() を以下のように修正します。
GameManager.cs
public void CreateVegetable(int t, int v, Vector3 p)
{ /*
GameObject vege = Instantiate(v_Prefab[v], p, Quaternion.identity);
VegetableManager vm = vege.GetComponent<VegetableManager>();
vm.index = v;
if (t == 0)
{
vm.type = VegetableManager.MOVETYPE.NEXT;
vege.transform.SetParent(tray.transform);
} ここまで記述済み*/
else if(t == 1) //進化モードなら
{
vm.type = VegetableManager.MOVETYPE.STAY; //typeをSTAYに指定
vege.transform.localScale = Vector3.one * v_size[v]; //大きさを変更
vege.transform.SetParent(vegetables.transform); //Vegetablesの子要素に指定
vege.GetComponent<Rigidbody2D>().AddForce(Vector2.up * 80); //ジャンプ
}
}
この関数は、野菜が同じタイプの野菜と接触したタイミングで呼び出されます。
6.4,野菜の当たり判定
まずは VegetableManagerクラス に、2つの野菜が結合して進化をした際に呼び出される関数を作成します。ここで行うことは次の4つです。
❶ 2つの野菜の中間となる座標を取得 ❷ 当たった相手の野菜を削除 ❸ 自分自身(関数を呼び出す側)を削除 ❹ GameManagerクラスの CreateVegetable()関数を進化モードで呼び出す
この関数を衝突した野菜それぞれが呼び出してしまうと、進化した野菜が2つできてしまいます。そこでそれぞれの野菜のオブジェクトが持つ固有のIDの小さい方が、この関数を呼び出すということを発動条件に追加しておきます。
では VegetableManager.cs に、次のコードを追記します。
VegetableManager.cs
void Evolution(Collision2D col) //Collider2D型の引数 col をもつ関数
{
//2つの野菜の名前が同じで、ID大きい方が発動
if(col.gameObject.name == gameObject.name &&
col.transform.GetInstanceID() < GetInstanceID())
{
Vector3 pos = (transform.position + col.transform.position) / 2; //❶2つの中間点を取得
Destroy(col.gameObject); //❷当たった相手を削除
Destroy(gameObject); //❸自分自身を削除
gm.CreateVegetable(1, index + 1, pos); //進化モードで進化した野菜生成
}
}
続いてイベント関数:OnCollisionEnter2D() の中で、上で作成した 関数:Evolution() を呼び出す動きを作成します。
この当たり判定内では、次の2つの処理を行います。
❶ 関数:Evolution()の発動 ❷ 落下直後のオブジェクトのMOVETYPEを STAY に変更
VegetableManager.cs
void OnCollisionEnter2D(Collision2D col)
{
Evolution(col); //❶関数:Evolution()の発動
if(type==MOVETYPE.FALL) //もしMOVETYPEがFALLなら
{
//相手がVegetableタグでMOVETYPEがSTAY、または相手がWallタグなら
if((col.gameObject.tag=="Vegetable" && col.gameObject.GetComponent<VegetableManager>().type==MOVETYPE.STAY)
|| col.gameObject.tag == "Wall")
{
type = MOVETYPE.STAY; //❷MOVETYPEを STAY に変更
}
}
}
ここまでの動きで、一連のフローが完成しました。
6.5,最終進化(素材作成)
現段階で最終進化のかぼちゃ同士が結合した場合、その先の配列を用意していないのでエラーになってしまいます。このフェーズではかぼちゃ同士が結合した場合、肉に進化するというシナリオでプログラムを作っていきます。
まずは下の図の様に、取得済みの素材から牛の画像(cow.png)をHierarchy上、またはScene上にドラッグ&ドロップで素材のもとを作成します。
続いて作成した素材をInspectorから以下のように修正します。
❶ 名前:Meat に指定 ❷ CircleColliderコンポーネント 追加 Edit Collider で大きさを調整しておきましょう ❸ Rigidbody2Dコンポーネント 追加 Gravity Scale:重力の大きさを 0.5 に指定します
素材にはプログラムは不要なので、これで完成です。
[03_Prefabs]フォルダにドラッグ&ドロップで、プレハブ化しておきます。Hierarchy上素材は不要なので、削除しておきましょう。
6.6,最終進化(プログラム)
続いて最終進化のプログラムを作成します。このプログラムで行うことは次の2つです
❶ かぼちゃ同士が結合した時、Meatプレハブから1つのオブジェクトを生成❷ 生成したMeatの画像をランダムで牛、豚、鶏のいずれかに指定
では GameManagerクラス で新たに使用する配列、変数を確認します。
配列名 | 型 | アクセス | 説明 |
neatImg | Sprite | [SerializeField] | 牛、豚、鶏の画像を入れる配列 |
また使用する変数は以下の通りです。
変数名 | 型 | アクセス | 説明 |
meatPrefab | GameObject | [SerializeField] | 肉のプレハブ |
では 「GameManager.cs」 を立ち上げて、以下のコードを追記します。
GameManager.cs
[SerializeField] Sprite[] neatImg; //3種類の肉の画像を管理する配列
[SerializeField] GameObject meatPrefab; //肉のプレハブ
Inspectorから宣言した変数に取得済みの牛、豚、鶏の画像、及び上で作成したMeatプレハブをAssignします。
続いて作成済みの関数:CreateVegetable(int t, int v, Vector3 p) を以下のように修正します。
GameManager.cs
public void CreateVegetable(int t, int v, Vector3 p)
{
if (v == 12) //かぼちゃからの進化の場合
{
//meatPrefab を生成
GameObject meat= Instantiate(meatPrefab, p, Quaternion.identity);
//meatPrefab の画像をランダムで指定
meat.GetComponent<SpriteRenderer>().sprite = neatImg[Random.Range(0, 3)];
return; //以下の処理を強制終了
}
/* 以下記述済み
GameObject vege = Instantiate(v_Prefab[v], p, Quaternion.identity);
VegetableManager vm = vege.GetComponent<VegetableManager>();
vm.index = v;
if (t == 0)
{
vm.type = VegetableManager.MOVETYPE.NEXT;
vege.GetComponent<CircleCollider2D>().enabled = false;
vege.transform.SetParent(tray.transform);
}
else if (t == 1)
{
vm.type = VegetableManager.MOVETYPE.STAY;
vege.transform.localScale = Vector3.one * v_size[v];
vege.transform.SetParent(vegetables.transform);
vege.GetComponent<Rigidbody2D>().AddForce(Vector2.up * 80);
}*/
}
これでかぼちゃ同士が結合した場合でも、エラーにならずどれかの肉が表示されるという演出ができました。
「VegetablGameの作り方」その他の記事はこちらから
ファイブボックスでは、Unityの個別指導のオンラインレッスンを行っています。
ご興味のある方は当サイト、オンラインレッスンから、無料体験授業へお問い合わせ下さい。
Komentarze