弾を発射する【Unityで2Dのシューティングゲームを作る③】
こんにちは、シロウです。
前回の記事ではプレイヤーを動かす処理を実装しました。
今回は『2Dプレイヤーが銃弾を発射する処理』と『オブジェクト(銃弾)が画面のカメラの範囲外に出たら削除する処理』を実装していきます。
さて、今回もサクサクといきましょう!
銃弾とアタックポイントの作成
まずは銃弾と銃弾を発射ポイントを指定するオブジェクトを作成しましょう。
今回は銃弾の代わりにレーザーを配置。場所はどこでもOKですので、ヒエラルキーからプロジェクトウィンドにドラッグ&ドロップしてプレハブ化しておきましょう。
プレハブ化できたらレーザーを削除しておきます。
発射ポイントは ヒエラルキー > Create > CreateEmpty の順で空のオブジェクト(AttackPoint)を作成し、銃の子オブジェクトにしてください。
また、inspector > オブジェクトの名前の横にあるイメージをクリック > 色を選択 とすることで、空のオブジェクトにも色を付けることができて見やすくなるのでぜひ使ってみてください。
あとは AttackPoint を銃の前に来るように座標を調整すれば完了です。
銃弾を発射するスクリプト
まずはレーザーを動かすスクリプトを書いていきます。
新しく「LazerController」というスクリプトを作成して、下記のコードを記述してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LazerController : MonoBehaviour
{
[SerializeField] private float speed = 5; //銃弾のスピード
void Start()
{
}
// Update is called once per frame
void Update()
{
Move();
}
public void Move()
{
Vector3 lazerPos = transform.position; //Vector3型のplayerPosに現在の位置情報を格納
lazerPos.x += speed * Time.deltaTime; //x座標にspeedを加算
transform.position = lazerPos; //現在の位置情報に反映させる
}
コード自体はとても単純で、シンプルにx軸方向に speed * deltaTime 分を毎フレームごとに動かしているだけです。
前回の記事でも解説したように、 Transform.position.x などのように x,y,z座標は一度、他の変数に格納してからでないと変更できないのでこのような処理になっています。
これをレーザープレハブにアタッチしてください。
次に銃弾を発射するスクリプトを作っていきます。
前回の記事で作った「PlayerControllerスクリプト」にいくつか処理を追加します。
[SerializeField] private GameObject lazer; //レーザープレハブを格納
[SerializeField] private Transform attackPoint;//アタックポイントを格納
[SerializeField] private float attackTime = 0.2f; //攻撃の間隔
private float currentAttackTime; //攻撃の間隔を管理
private bool canAttack; //攻撃可能状態かを指定するフラグ
まずは上記の5つの変数を作ります。
次に Attackメソッドを追加していきます。
void Start()
{
currentAttackTime = attackTime; //currentAttackTimeにattackTimeをセット。
}
void Update()
{
//~省略~
Attack();
}
//〜〜〜省略〜〜〜〜
void Attack()
{
attackTime += Time.deltaTime; //attackTimeに毎フレームの時間を加算していく
if(attackTime > currentAttackTime)
{
canAttack = true; //指定時間を超えたら攻撃可能にする
}
if (Input.GetKeyDown(KeyCode.K)) //Kキーを押したら
{
if (canAttack)
{
//第一引数に生成するオブジェクト、第二引数にVector3型の座標、第三引数に回転の情報
Instantiate(lazer, attackPoint.position, Quaternion.identity);
canAttack = false; //攻撃フラグをfalseにする
attackTime = 0f; //attackTimeを0に戻す
}
}
}
上記のコードもそこまで難しくありませんので、ポイントだけ解説していきます。
まず Start関数内で currentAttackTime に attackTime をセットすることで、 if(attackTime > currentAttackTime) の条件分岐を可能としています。
そして、 if(attackTime > currentAttackTime) が満たされると canAttack がtrueになるのでKキーを押した時に if (canAttack) が満たされて、その中の処理が呼び出されます。
Instantiateは、第1引数に生成したいオブジェクト、第2引数にオブジェクトを生成する位置、第3引数に生成するオブジェクトの向きを指定してあげます。
第3引数の Quaternion.identity は向きを変えないというおまじないなので、向きを変えないでいい場合はとりあえずこれを指定しておけばOKです。
PlayerControllerにインスペクター上からLazerやAttackPointをドラッグ&ドロップしてあげてください。
すると、Kキーを押せばいい感じに弾を発射することができると思います。
ただこれだとオブジェクトが永遠に残り続けてしまうので、次にカメラから見えなくなったらオブジェクトを削除する処理を追加していきましょう。
カメラから見えなくなったらオブジェクト(銃弾)を削除
「LazerControllerスクリプト」に下記のコードを追加してください。
private void OnBecameInvisible()
{
Destroy(this.gameObject);
}
OnBecameInvisible() はカメラからアタッチされているオブジェクトが見えなくなった時に呼び出される処理です。
なので、この処理内で Destroyの引数にgameObject を呼び出してあげれば銃弾がカメラから見えなくなったら消えるという処理が実装できます。
ただ、この処理の注意点としては「Gameウインドウ」だけでなく「Sceneウインドウ」からも見えなくならないと削除されません。
つまり、再生中にGameとSceneを同時に開いていると「あれ、Gameウインドウで見えなくなったのにまだ削除されないぞ?」という勘違いをする可能性がありますので注意してください。
さて、これでとりあえず銃弾の発射と削除は実装が出来ました。
次はいよいよ敵を出現させたりする処理を書いていきましょう!
ということで、今回はここまでです。それではまたっ(*・ω・)ノ
Unityスキルをもっと上達させたい方へ
僕も最初の頃はUnityを独学でやっていたのですが、その頃は全くダメでした。笑
でもテックアカデミーの「Unityコース」を受講してから一気に色々なことができるようになりました。(メンターさんにいつでも質問できるのが大きかったです。)
もっとUnityで色々なアプリを作れるようになりたい!という方はぜひUnityコースを受講することを考えてみてください!
確実に今よりは成長しますので!
興味のある方は下記の記事にUnityコースの詳細をまとめていますので、そちらもどうぞ!