Unityで簡易的なドミノ倒しゲームの作成
今回は,以前作成したUnityの自動生成ドミノについて紹介したいと思います。Unityに組み込まれている物理エンジンを用いて,現実で行うのと同じようなドミノを配置して,実際にUnity内でそれらを連続的に倒していくことが可能です。
実際的な方法としては、Cubeを配置してそれらをドミノの平板のような形に調整して,あとはこの作った平板を作りたいドミノの配列に並べて行って,初期位置にあるドミノを倒して,並べたドミノが倒れていくのを見届けることになります。
- 平板dominocubeの作成
- dominocubeを列ごとに自動生成するスクリプト
- dominocubeのPrefabの作成
- addcubescriptの組み込みなど
- ドミノを倒す方法(無理やり)
- 途中からドミノを曲げる場合のスクリプト
平板dominocubeの作成
平板を作成していくのですが,その前にPlaneを設定します。適当な大きさのPlaneを設定して,配置します。ComponentからPhysics>Mesh Colliderを設定しました。
UnityのGameObjectからCubeを作成します。つくったCubeを平板にしていきます。平板のscaleは以下のInspectorのように設定しました。Positionは今は気にしないでください。
これによってできるdominocubeを一方向から見たものが以下です。ちょっと縦に細長い感じもしますが,ドミノ倒しをするにはちょうどよさそうな平板って感じがしますね。
dominocubeを列ごとに自動生成するスクリプト
しかし,どうにもドミノをいちいち配置していくのは面倒ですね。そこで平板を自動配置するスクリプトを書いてしまおうと思います。
スクリプトの名前はaddcubescriptになってます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class addcubescript : MonoBehaviour {
public GameObject obj;
public int createNumbers = 200;
public int space = 1;
public Vector3 createPos;
// Use this for initialization
void Start () {
CreateObject();
}
void CreateObject()
{
for(int i = 0; i < createNumbers; i++)
{
Instantiate(obj, createPos + new Vector3(0, 2, -i - space * i), Quaternion.identity);
transform.GetComponent();
}
}
// Update is called once per frame
void Update () {
}
}
dominocubeのPrefabの作成
つくったdominocubeをAssetsの方へドラッグしてdominocubeのPrefabを作成しました。
これにより,スクリプトによるdominocubeの自動生成が可能となります。
上のスクリプトで注意してほしいのが,GameObject objを初期の基準としてcubeが自動生成されるということです。
addcubescriptの組み込みなど
dominocubeへaddcubescriptをドラッグして,objのところをdominocubeに設定する。
dominocubeへRigidbodyを組み込み,dominocubeの設定のPositionなどを以下のように設定します。これのうち,Yの位置が微妙に下だとdominocubeがPlaneより下へ沈んで行ってしまったり,上側だと生成した後に不安定になって勝手に倒れてしまうなどが起きるので注意してください。
ドミノを倒す方法(無理やり)
次にドミノの最初の倒し方ですが,これは以前ビリヤードの球を動かすのに用いたスクリプトを弾の形にしたcube(名前はbullet)に組み込んで,平板の狙ったところに力を加えられるように初期位置を選ぶことができます。Positionをいじることによって可能です。
スクリプトは以下です。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class study3_11 : MonoBehaviour
{
float dgr = 0;
int power = 0;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 pos = transform.position;
if (Input.GetKeyDown(KeyCode.Space))
{
power = 0;
}
if (Input.GetKey(KeyCode.Space))
{
power++;
}
if (Input.GetKeyUp(KeyCode.Space))
{
Vector3 v = Camera.main.transform.position;
v -= pos;
v *= power * -1;
v.y = 0;
transform.GetComponent().AddForce(v);
}
if (Input.GetKey(KeyCode.Q))
{
power++;
}
if (Input.GetKeyUp(KeyCode.Q))
{
Vector3 V = Camera.main.transform.position;
V -= pos;
V *= power * 1;
V.y = 0;
transform.GetComponent().AddForce(V);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
Camera.main.transform.RotateAround(pos, new Vector3(0, 10, 0), -0.1f);
dgr += 0.1f;
}
if (Input.GetKey(KeyCode.RightArrow))
{
Camera.main.transform.RotateAround(pos, new Vector3(0, 10, 0), 0.1f);
dgr -= 0.1f;
}
float d = (2 * Mathf.PI) * (dgr / 360);
float x = Mathf.Sin(d);
float y = Mathf.Cos(d);
x *= 10f;
y *= 10f;
pos.x += x;
pos.y += 10f;
pos.z -= y;
Camera.main.transform.position = pos;
}
}
このスクリプトは以下の本で載っていたものを参考にしています。
見てわかるUnity5 C#超入門 (Game Developer Books)
- 作者: 掌田津耶乃
- 出版社/メーカー: 秀和システム
- 発売日: 2015/10/30
- メディア: 単行本
- この商品を含むブログを見る
このスクリプトにより,スペースキーを押した時間だけ強くbulletを発射することができます。
ここでbulletに対する注意としては,組み込んだRigidbodyのうちUse Gravityをオフにしていることです。これがオンになっているとbulletが重力で落ちてしまうので決まった高さに当てることができません。
これらからドミノ倒しをやってみたときの画像たちが以下です。
ドミノの初期位置に当たらんとするbullet。待ち構えるは無数のドミノ達。
…無限に続くドミノ。
(1分20秒後)終わりが見えてきた。
200個のドミノを自動生成したので,終わりまでいくのに1分半近くかかりました。ドミノの倒れるスピードは形によって変えられると思うので,もっと倒れるのを早くしてやってみるのもいいかもですね。
途中からドミノを曲げる場合のスクリプト
直線では面白味に欠けると思い,途中から斜めにできないかと思って作成したのが以下のスクリプトです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class addcubescript : MonoBehaviour {
public GameObject obj;
public int createNumbers = 200;
public int space = 1;
public Vector3 createPos;
// Use this for initialization
void Start () {
CreateObject();
}
void CreateObject()
{
for(int i = 0; i < createNumbers; i++)
{
Instantiate(obj, createPos + new Vector3(0, 2, -i - space * i), Quaternion.identity);
transform.GetComponent();
}
for (int i = 0; i < createNumbers; i++)
{
Instantiate(obj, createPos + new Vector3(-i*0.3f, 2, i + space * i), Quaternion.identity);
transform.GetComponent();
transform.Rotate(new Vector3(0, 10, 0));
}
}
// Update is called once per frame
void Update () {
}
}
こんな感じで途中から曲がったドミノの列になります。もうちょっと微調整するべきポイントはいくつかありますが...。
これをうまく組み合わせれば,もっと色々な形のドミノ倒しを自動生成できるかもしれないですね。
もっとちゃんとやるってなったときには改善しなきゃいけないポイントが山ほどあるので,それを改善できたらな,と思います。(やってみればわかるのですが,実行時に注意しなきゃいけない点が結構山積みです...。)