UnityでARシューティングゲームを作った②
前回の続きです。長い。
前置き
作成手順
⑴ARでゲームステージを制作・出現させる
⑵マトを配置して球を発射(シュート)できるようにする
⑶マト破壊時や球発射時の音・パーティクルをつける
⑷制限時間・残マトゲージを作る
⑸スタート画面やゲームクリア・ゲームオーバー画面等を作って繋げる
それぞれまとめる!といっても、検索すると、大体やりたいことを素晴らしくわかりやすく書いてくださっている方がいらして...とても助かりました。なので、ほぼ記事をまんま参考にしました!というところは引用のみで。
早速⑴と⑵についてメモ。
⑴ARでゲームステージを制作・出現させる
AR表現にVuforiaというライブラリを使用。
ARマーカーの登録やUnity諸々の設定が必要ですが、これは、勝手に大変お世話になっているおもちゃラボ様がとってもわかりやすく書いているので、そちらを載せます↓
https://nn-hokuson.hatenablog.com/entry/2018/08/28/192028
とりあえずARを出したら、今出してるARをゲームステージに変更する...為にまずはそのゲームステージをつくります。
今回はTettainというUnityの機能を使用しました。ここから選べます↓
ImageTargetの子オブジェクトにし、思い思いにステージをつくりました。ただ、デフォルトの設定のTerrainはサイズが大きすぎるので、Inspector>Terrainの歯車マークをポチッと押して、MeshResolution(On Terrain Data)のWidth,Length,Heightをちょうどいいサイズに変更します。
⑵マトを配置して球を発射(シュート)できるようにする
次にマト作成です。マトはGameObject>3DObject>Cylinderをサイズ調整していい感じの形にしました。
マトに厚みを持たせるかつ、マトの表面のみにマト模様のマテリアルアタッチしたい!ので、マト1つを表面(厚みのない円)とそれ以外(少し厚みのある円柱)の2パーツでつくりました。
しかし、マトは動いた方がシューティングゲームとしては絶対面白い..ので、まずは上下にスクリプトで動かしてみました。
using UnityEngine;
public class MoveObject : MonoBehaviour //y軸方向に往復して動かす
{
private Rigidbody rigid;
private Vector3 Pos;
public float num;
void Start()
{
rigid = GetComponent<Rigidbody>();
Pos = transform.position;
}
void Update()
{
rigid.MovePosition(new Vector3(Pos.x, Pos.y + Mathf.PingPong(Time.time/4, num), Pos.z));
}
}
▷PingPong関数
Mathf.PingPong(時間, 上下差)で、0から”上下差”の間の数値を行ったり来たりできる
今回は上下差をinspectorからいじれるようにしてます(num)。これを、y座標に入れます。拝見したサイト様↓
そして、上下に揺らすだけでなく、回転させてみたり、上からマトを落としてみたりもしました。
using UnityEngine;
public class MoveObject03 : MonoBehaviour //回転させる
{
void Update()
{
transform.Rotate(1.0f, 0, 0);
}
}
▷transform.Rotate関数
transform.Rotate(x軸周りの角度、y軸周りの角度、z軸周り角度)、で現在のゲームオブジェクトの角度に指定したそれぞれの角度を足すことで回転させることができる
上からマトを落とす動きは、ちょっと山がありました。
⑴Rigidbody componentのUse Gravity / IsKinematicの切り替え
⑵落下中の力の加え方
⑶落下着地点の床(マグマ)すり抜けの為のコライダのON/OFF
▷IsKinematic
ONになると物理演算の影響がなくなる
⑴落下させたいのでUseGravityをONにしたかったのですが、それだけだとゲームシーンが実行されてARマーカーを認識していない段階からマトが落下を始めてしまう為、プレイヤーに違和感を与えてしまいます。そこで、実行時にIsKinematicをONにし重力の影響をなくし、マーカー認識してからOFFにして重力を使うようにしました。マーカー認識時の動きを変えるのに、以下をお借りしました。↓
⑵Unityは本当便利で、useGravityにレ点入れるだけで重力使えるのすごいありがたい...!のですが、マト落下速度もあり、レ点だけだとステージ中の火山にぶつかった時に跳ね返りでどこかにマトが飛んでいきます。飛んでどこかにいかないために、Update関数内でマトの高さによって力を加えたり加えなかったり微調整が必要でした。後の方でスクリプトをまとめて載せます。
⑶マグマステージを作ったので、落下してきたマトをマグマの中にドボンさせて、すり抜けさせようとしました。コライダ(当たり判定に使う)をオフにしないとすり抜けることができないので、マグマが当たる高さの時にステージ(Terrain)のコライダをオフに。
また、マトを初期位置に戻すのはコルーチンを呼び出すことで実装しました。
以下、落下させるスクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveObject02 : MonoBehaviour //マトを上から落下させて動かす
{
Rigidbody rb;
public GameObject magma;
public GameObject terrain;
Vector3 start_pos;
void Start()
{
rb = this.GetComponent<Rigidbody>();
rb.useGravity = true;
rb.isKinematic = true;
start_pos = transform.position;
}
public void MarkerTracking() //マーカー認識したらマトを動かす
{
rb.isKinematic = false;
}
void Update()
{
if(transform.position.y < 0.4f)
{
StartCoroutine("restart"); //magmaに当たったらすり抜けて初期位置にマトを戻す
}
else if(transform.position.y < 2.0f)
{
rb.AddForce(-2.0f, 0, 0); //山にへばりつくようにx軸負の方向に力を加える
}
rb.AddForce(0, 7.4f, 0); //重力加速度調整
}
IEnumerator restart() //マトが画面外に消えたら初期位置へ
{
Vector3 pos_update = transform.position;
//当たり判定を無くしてmagmaをすり抜けさせる
TerrainCollider terrain_col = terrain.GetComponent<TerrainCollider>();
BoxCollider magma_col = magma.GetComponent<BoxCollider>();
terrain_col.enabled = false;
magma_col.enabled = false;
if (transform.position.y < -1.0f)
{
terrain_col.enabled = true;
magma_col.enabled = true;
rb.isKinematic = true;
transform.position = start_pos;
transform.rotation = Quaternion.Euler(-90, 0, 0);
rb.isKinematic = false;
yield return null; //コルーチン終了
}
}
}
実行動画
今回長々と書いたマトの挙動の実行結果の動画は以下です
まとめるのって大変だ..次回以降もっと端的にまとめられるように文字数意識しようかなぁ。弾発射は次にまとめよう!
この記事が気に入ったらサポートをしてみませんか?