スワイプの向きに弾を発射【Android用】【ロックマン風】
今回は、横スクロールアクション等で使えそうな
フリックした方向に弾を発射する仕様を
解説用に1から作ってみたいと思います。
※エミュレータ・実機で動作できるように弾発射以外の部分もたくさん書いたので、
発射部分のみ見たい方は「 目次:弾発射に関するコードの解説 」に飛んでください。
追記
【Unity】Android用フリック対応ボタン作った - のにっき
上記サイトで、フリック角度や方向を簡単に取得できるボタンの
ユニティパッケージ公開してます!この記事と合わせて見てみてください。
画像準備
- キャラ画像
適当にパワポで書きました
発射に合わせてアニメーションを付けようと思ったので
待機・発射用の画像を用意しました。
- ボタン画像
下記サイトの素材をお借りしました。
落とした画像をボタンっぽくして1枚の画像にしてます。
銃弾のフリーアイコン4 | アイコン素材ダウンロードサイト「icooon-mono」 | 商用利用可能なアイコン素材が無料(フリー)ダウンロードできるサイト
- 弾画像
下記サイトの「メテオ」の素材をお借りしました。
落とした画像をパワポでまとめて1枚の画像にしてます。
フリーエフェクト素材 - ゲーム素材 | ランスタのフリーBGM、効果音、ゲーム素材、3DCG
オブジェクト作成
- オブジェクト作成・配置
弾を発射するように適当にステージ・キャラ・ボタンを作成していきます
下図で注意が必要なことは、画面枠外にオレンジ色の枠を作っていることです。
これは、発射した弾が消えないと画面外で無限に動き続けるので、
弾の消える範囲を作っています。
画面外に作ったのは、画面外の敵にもある程度影響を与えたいためです。
- 弾丸オブジェクトについて
今回は、弾丸のプレハブを事前に10個作っています。
この理由は、発射時に「Resources.Load」で弾丸プレハブを作成するより、
オブジェクトを作っておいて、表示の切り替えでやりくりする方が処理が早いからです。
あと、見やすくて管理が楽です。
- Tagの追加
各オブジェクトがぶつかった際の種類を判別する「Tag」
このTagを追加していきます。※テスト用なので大雑把に追加してます。
Tag 0:Ground・・・・・地面
Tag 1:Wall・・・・・・壁
Tag 2:Bullet・・・・・・弾
Tag 3:Chara_Main・・・メインキャラ
Tag 4:OutLine・・・・・外枠
- 各オブジェクトの設定内容
オブジェクトに中身を設定していきます。
※赤枠の部分が追加した内容になります。
- キャラ、弾丸のアニメーション管理
キャラ:基本は待機アニメがループで流れて、発射時に発射アニメが流れる
弾丸:弾丸アニメが無限ループで流れる
スクリプト作成【ファイル作成】
いよいよ、弾を発射させる処理の部分を解説していきます。
まずは、スクリプトファイルを作成していきましょう。
▼作成するファイル名と、設定するオブジェクト名
・Ply_Bullet_Cntrl・・・「Nd_Bullet_0~9」に設定
→弾丸の衝突処理を記入
・Ply_Main・・・「ScriptCntrl」に設定
→エディター上で設定する変数、割り込みイベント等を記入
・Ply_TapEv・・・「Btn_Shot」に設定
→ユーザー操作(イベント)で呼び出す関数を記入
・Ply_Cns・・・設定しない
→全スクリプトで共通に使われる「変数・定数・クラス・関数」を記入
・Ply_Timer・・・設定しない
→タイマー系のイベントで呼ばれる関数を記入
スクリプト作成【コード記入】
説明がいる部分と要らない部分があってややこしいので、
とりあえず説明なしでソースコードを全部記入します。
必要な説明は後ろで行います。
・Ply_Bullet_Cntrl
using System.Collections; using System.Collections.Generic; using UnityEngine; using static Nm_Play.Ply_Cns; public class Ply_Bullet_Cntrl : MonoBehaviour { //******************************************************************************* // 衝突時に呼ばれるイベント //******************************************************************************* private void OnTriggerEnter2D(Collider2D col_Get) { //============================================================ // 衝突判定 ※衝突オブジェクトのタグで判定している //============================================================ if ((col_Get.gameObject.tag == Df_TagName[Df_Tag_No]) || (col_Get.gameObject.tag == Df_TagName[Df_Tag_MainC])) { return; } //============================================================ // 変数定義 //============================================================ SceneOneIf SceneIf = Cls_SceneOneIf; Obj_All ObjIf = Cls_ObjAll; //============================================================ // 衝突した弾丸オブジェクトを非表示 //============================================================ int i_SetId = 0; i_SetId = int.Parse(this.name.Replace(Df_Bullet_Name, "")); ObjIf.BulletIf.SetBulletNd_End(i_SetId); } }
・Ply_Main
using System.Collections; using System.Collections.Generic; using UnityEngine; using static Nm_Play.Ply_Cns; using static Nm_Play.Ply_Timer; public class Ply_Main : MonoBehaviour { // ■□■□■□■□■□■□■□■□■□■□■□■□■□ // // 変数定義 // // ■□■□■□■□■□■□■□■□■□■□■□■□■□ public GameObject Obj_Canvas_UI; public GameObject Obj_Canvas_Back; public GameObject Obj_Back; public Sprite[] Spr_Btn_On; public Sprite[] Spr_Btn_Off; // ■□■□■□■□■□■□■□■□■□■□■□■□■□ // // 【イベント】関数一覧 // // ■□■□■□■□■□■□■□■□■□■□■□■□■□ //***************************************************** // 開始時 //***************************************************** void Start() { //================================================= // オブジェクトクラス初期化 //================================================= // クラス初期化 Cls_ObjAll = new Obj_All(Obj_Canvas_UI, Obj_Canvas_Back, Obj_Back, Spr_Btn_On, Spr_Btn_Off); Cls_SceneOneIf = new SceneOneIf(); } //**************************************************** // 割り込み関数 //**************************************************** void FixedUpdate() { //------------------------------------------------ // 弾丸管理 //------------------------------------------------ if (Cls_SceneOneIf.cls_BtnIf[Df_BtnId_Shot] != null) { SetBullet_Shot(); } } }
・Ply_TapEv
using System.Collections; using System.Collections.Generic; using UnityEngine; using static Nm_Play.Ply_Cns; using static Nm_Play.Ply_Timer; public class Ply_TapEv : MonoBehaviour { /***************************************************************************** モジュール名: Tap_Shot_ 概要 : ショットボタン押下・離す処理 *****************************************************************************/ public void Tap_Shot_On() { //================================================================== // 変数定義 //================================================================== SceneOneIf SceneIf = Cls_SceneOneIf; Obj_All ObjIf = Cls_ObjAll; //================================================================== // ボタン押下処理 //================================================================== // ボタン変数を設定 ObjIf.BulletIf.i_ShotWait = 0; SceneIf.cls_BtnIf[Df_BtnId_Shot] = new BtnTapIf(Df_BtnId_Shot); // 画像設定 ObjIf.SetBtnImage(true, Df_BtnId_Shot); } public void Tap_Shot_Off() { //================================================================== // 変数定義 //================================================================== SceneOneIf SceneIf = Cls_SceneOneIf; //================================================================== // ボタン離す処理 //================================================================== // ボタン情報を変数に格納 SceneIf.cls_BtnIf[Df_BtnId_Shot] = null; // 画像設定 Cls_ObjAll.SetBtnImage(false, Df_BtnId_Shot); } }
・Ply_Cns
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace Nm_Play { public class Ply_Cns : MonoBehaviour { // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□ // // 変数定義 // // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□ //======================================================================= // 変数 //======================================================================= public static Obj_All Cls_ObjAll; public static SceneOneIf Cls_SceneOneIf; //======================================================================= // 定数 //======================================================================= //----------------------------------------------------------------- // ボタン管理系 //----------------------------------------------------------------- // ボタン管理用ID public static int Df_BtnId_Shot = 0; public static int Df_BtnId_Max = 1; //----------------------------------------------------------------- // 弾丸管理系 //----------------------------------------------------------------- // 弾丸プレハブ名 public static string Df_Bullet_Name = "Nd_Bullet_"; // 弾プレハブ最大数 public static int Df_Bullet_Max = 10; // 弾発射ウェイト public static int Df_Bullet_Wait = 10; public static int Df_Bullet_Wait2 = 20; //----------------------------------------------------------------- // アニメータートリガー管理系 //----------------------------------------------------------------- // メインキャラ public static string Df_Trg_Main_Gun = "Trg_Shot"; //----------------------------------------------------------------- // 管理 //----------------------------------------------------------------- public static int Df_Tag_No = 0; public static int Df_Tag_Grnd = 1; public static int Df_Tag_Wall = 2; public static int Df_Tag_Blet = 3; public static int Df_Tag_MainC = 4; public static int Df_Tag_OutL = 5; public static string[] Df_TagName = new string[] { "Untagged", "Ground", "Wall", "Bullet", "Chara_Main", "OutLine" }; // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■■□■□■□ // // クラス定義 // // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■■□■□■□ /************************************************************************** * クラス名 : Obj_All 概要 : 全オブジェクト情報 **************************************************************************/ public class Obj_All { //===================================================================== // 変数定義 //===================================================================== //--------------------------------------------------------------- // ホーム画面 //--------------------------------------------------------------- public GameObject MainChara_Obj; public Transform MainChara_Posi; public Animator MainChara_Ani; public Image[] Btn_Sprite_Set; public Sprite[,] Btn_Sprite_Get; public BulletIf BulletIf; /************************************************************************** コントラクタ **************************************************************************/ public Obj_All ( GameObject Canvas_UI, GameObject Canvas_Back, GameObject Obj_Back, Sprite[] Spr_Btn_On, Sprite[] Spr_Btn_Off ) { //================================================================== // オブジェクト設定 //================================================================== //------------------------------------------------------------ // キャラ関係 //------------------------------------------------------------ MainChara_Obj = Obj_Back.transform.Find("Material/Chara_Main").gameObject; MainChara_Posi = MainChara_Obj.GetComponent<Transform>(); MainChara_Ani = MainChara_Obj.GetComponent<Animator>(); //------------------------------------------------------------ // バレット関係 //------------------------------------------------------------ BulletIf = new BulletIf(Obj_Back); //------------------------------------------------------------ // ボタン関係 //------------------------------------------------------------ // オブジェクト変数 Btn_Sprite_Set = new Image[Df_BtnId_Max]; Btn_Sprite_Set[Df_BtnId_Shot] = Canvas_UI.transform.Find("Panel_Btn/Btn_Shot").GetComponent<Image>(); // 貼り付け用ボタン画像 Btn_Sprite_Get = new Sprite[2, Df_BtnId_Max]; for (int i_Flg = 0; i_Flg < 2; i_Flg++) { // 貼り付ける画像配列取得 Sprite[] Spr_Set; if (i_Flg == 0) { Spr_Set = Spr_Btn_On; } else { Spr_Set = Spr_Btn_Off; } // 画像を変数に格納 for (int i_Type = 0; i_Type < Df_BtnId_Max; i_Type++) { Btn_Sprite_Get[i_Flg, i_Type] = Spr_Set[i_Type]; } } } /******************************************************************** メソッド名 : SetBtnImage 概要 : ボタン画像設定 ********************************************************************/ public void SetBtnImage(bool bl_IsOn, int i_BtnId) { int i_Flg = 0; if (bl_IsOn == false) { i_Flg = 1; } Btn_Sprite_Set[i_BtnId].sprite = Btn_Sprite_Get[i_Flg, i_BtnId]; } } /******************************************************************** * クラス名 : BulletIf 概要 : 弾丸情報 ********************************************************************/ public class BulletIf { //=============================================================== // 変数定義 //=============================================================== public int i_SetId = 0; public int i_BltCnt = 0; public int i_ShotWait = 0; public Dictionary<string, int> Dic_NameId = new Dictionary<string, int>(); public List<GameObject> l_Obj_Object; public List<Rigidbody2D> l_R2d_Vctl; /********************************************************************* コントラクタ *********************************************************************/ public BulletIf(GameObject Obj_Base) { // 変数初期化 i_SetId = 0; i_BltCnt = 0; i_ShotWait = 0; Dic_NameId = new Dictionary<string, int>(); l_Obj_Object = new List<GameObject>(); l_R2d_Vctl = new List<Rigidbody2D>(); // 変数設定 for (int i_LpCnt = 0; i_LpCnt < Df_Bullet_Max; i_LpCnt++) { // 事前に作成していた10個のプレハブオブジェクトを変数に格納 string str_Name = "Material/Bullets/" + Df_Bullet_Name + i_LpCnt.ToString(); Dic_NameId.Add(str_Name, i_LpCnt); l_Obj_Object.Add(Obj_Base.transform.Find(str_Name).gameObject); l_R2d_Vctl.Add (l_Obj_Object[i_LpCnt].transform.GetComponent<Rigidbody2D>()); // 発射までは非表示 l_Obj_Object[i_LpCnt].SetActive(false); } } /*********************************************************************** メソッド : SetBulletNd_Stat 概要 : 弾丸発射処理 ***********************************************************************/ public void SetBulletNd_Stat() { //================================================================== // 変数定義 //================================================================== Obj_All ObjIf = Cls_ObjAll; //================================================================== // 表示開始処理 //================================================================== // 弾数カウンタ加算 i_BltCnt = i_BltCnt + 1; // 表示ID設定 i_SetId = i_SetId + 1; if (i_SetId >= 10) { i_SetId = 0; } // 位置をキャラに合わせて表示ON l_Obj_Object[i_SetId].transform.position = ObjIf.MainChara_Obj.transform.position; l_Obj_Object[i_SetId].SetActive(true); // 速度追加 SetBulletSpeed(l_Obj_Object[i_SetId], l_R2d_Vctl[i_SetId]); } /************************************************************************ メソッド : SetBulletNd_End 概要 : 弾丸消去処理 ************************************************************************/ public void SetBulletNd_End(int i_EndId) { // ぶつかったオブジェクトを非表示にする l_Obj_Object[i_EndId].SetActive(false); } /************************************************************************ メソッド : SetBulletSpeed 概要 : 弾丸速度設定 ************************************************************************/ public void SetBulletSpeed(GameObject Obj_Set, Rigidbody2D R2d_Set) { //===================================================================== // 変数定義 //===================================================================== float f_Speed = 10f; float f_Kakudo = 0f; Vector2 Vct2_Stat, Vct2_End; Vector2 Vct2_Cal_S, Vct2_Cal_E, Vct2_Cal_Set; SceneOneIf SceneIf = Cls_SceneOneIf; Obj_All ObjIf = Cls_ObjAll; //===================================================================== // 速度追加 //===================================================================== //--------------------------------------------------------------- // 角度設定 //--------------------------------------------------------------- // 開始・終点座標から角度計算 Vct2_Stat = SceneIf.cls_BtnIf[Df_BtnId_Shot].GetNowTapPoint(); Vct2_End = SceneIf.cls_BtnIf[Df_BtnId_Shot].vct3_StatPosi; Vct2_Cal_S = new Vector2(1, 0); Vct2_Cal_E = Vct2_Stat - Vct2_End; f_Kakudo = Vector2.Angle(Vct2_Cal_S, Vct2_Cal_E); // 座標から向き設定 if (Vct2_Stat.y - Vct2_End.y < 0f) { f_Kakudo = f_Kakudo * (-1f); } // 座標が同じなら前に発射書き換え if (Vct2_Stat == Vct2_End) { f_Kakudo = 0; } //--------------------------------------------------------------- // 速度追加 //--------------------------------------------------------------- Vct2_Cal_Set.x = Mathf.Cos(Mathf.Deg2Rad * f_Kakudo) * f_Speed; Vct2_Cal_Set.y = Mathf.Sin(Mathf.Deg2Rad * f_Kakudo) * f_Speed; R2d_Set.velocity = Vct2_Cal_Set; //========================================================= // オブジェクト設定 //========================================================= //--------------------------------------------------- // キャラ角度、アニメ設定 //--------------------------------------------------- ObjIf.MainChara_Ani.SetTrigger(Df_Trg_Main_Gun); if ((-90 <= f_Kakudo) && (f_Kakudo <= 90)) { ObjIf.MainChara_Posi.eulerAngles = new Vector3(0, 0, 0); } else { ObjIf.MainChara_Posi.eulerAngles = new Vector3(0, 180, 0); } //---------------------------------------------------------------- // バレット角度 //---------------------------------------------------------------- Quaternion Quat_Set = Quaternion.identity; Quat_Set.eulerAngles = new Vector3(0, 0, f_Kakudo + 90); Obj_Set.transform.rotation = Quat_Set; } } /*********************************************************************** * クラス名 : SceneOneIf 概要 : シーン内情報 ***********************************************************************/ public class SceneOneIf { //================================================================== // 変数定義 //================================================================== public BtnTapIf[] cls_BtnIf; /*********************************************************************** コントラクタ ***********************************************************************/ public SceneOneIf() { cls_BtnIf = new BtnTapIf[2]; } } /*********************************************************************** クラス名 : BtnTapIf 概要 : ボタンタップ情報 ***********************************************************************/ public class BtnTapIf { //================================================================== // 変数定義 //================================================================== public int i_BtnType = 0; public Vector3 vct3_StatPosi; /*********************************************************************** コントラクタ ***********************************************************************/ public BtnTapIf(int i_TypeSet) { // タップID設定 i_BtnType = i_TypeSet; // 現在のタップ位置取得 vct3_StatPosi = GetNowTapPoint(); } /*********************************************************************** モジュール名: GetNowTapPoint 概要 : タップ座標取得 引数 : なし 戻り値 : Vector2:タップ中の座標 ***********************************************************************/ public Vector2 GetNowTapPoint() { //============================================================ // エディター・実機ごとにタップ位置取得 //============================================================ Vector2 Vct2_Ret = new Vector2(); // エディター if (AppConst.IsEditor == true) { Vct2_Ret = Camera.main.ScreenToWorldPoint(Input.mousePosition); } // Android実機 else { for (int i_LpCnt = 0; i_LpCnt < Input.touchCount; i_LpCnt++) { Touch touch_One = Input.GetTouch(i_LpCnt); Vct2_Ret = Camera.main.ScreenToWorldPoint(touch_One.position); // 複数タップされる可能性があるので、適切なタップ位置を取得 // ※ここの判定は機種固有のものだと思われます if ((i_BtnType == Df_BtnId_Shot) && (Vct2_Ret.x > 0)) { break; } } } //================================================================ // 2828 デバッグ用テキスト ※後で消す! //================================================================ Text Txt_Set = GameObject.Find("Canvas_Back/Text").GetComponent<Text>(); Txt_Set.text = "開始:「 " + vct3_StatPosi.x + " , " + vct3_StatPosi.y + " 」\r\n"; Txt_Set.text = Txt_Set.text + "終了:「 " + Vct2_Ret.x + " , " + Vct2_Ret.y + " 」\r\n"; Txt_Set.text = Txt_Set.text + "弾数:" + Cls_ObjAll.BulletIf.i_BltCnt + ""; //================================================================= // 戻り値設定 //================================================================= return Vct2_Ret; } } /**************************************************************************** * クラス名 : AppConst 概要 : App作成前提の定義 ****************************************************************************/ public class AppConst { //======================================================================= // エディター用コンパイルかどうか //======================================================================= #if UNITY_EDITOR public static bool IsEditor = true; #else public static bool IsEditor = false; #endif } } }
・Ply_Timer
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using static Nm_Play.Ply_Cns; namespace Nm_Play { public class Ply_Timer : MonoBehaviour { // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□ // // 【発射系】関数定義 // // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□ /*************************************************************************** メソッド : SetBullet_Shot 概要 : バレット発射処理 ***************************************************************************/ public static void SetBullet_Shot() { //====================================================================== // 変数定義 //====================================================================== SceneOneIf SceneIf = Cls_SceneOneIf; Obj_All ObjIf = Cls_ObjAll; //====================================================================== // ショットボタン押下中判定 //====================================================================== if (SceneIf.cls_BtnIf[Df_BtnId_Shot] == null) { return; } //====================================================================== // 弾丸発射処理 //====================================================================== //---------------------------------------------------------------- // タイマー完了判定 //---------------------------------------------------------------- ObjIf.BulletIf.i_ShotWait--; if (ObjIf.BulletIf.i_ShotWait > 0) { return; } //---------------------------------------------------------------- // 弾丸発射 //---------------------------------------------------------------- ObjIf.BulletIf.SetBulletNd_Stat(); //---------------------------------------------------------------- // タイマー値初期化 //---------------------------------------------------------------- if (ObjIf.BulletIf.i_BltCnt >= 3) { ObjIf.BulletIf.i_BltCnt = 0; ObjIf.BulletIf.i_ShotWait = Df_Bullet_Wait2; } else { ObjIf.BulletIf.i_ShotWait = Df_Bullet_Wait; } } } }
以上が、今回組み込んだソースコードになります。
別プロジェクトでゲームを作ってるものからブログ用に抜粋したものなので、
余計なコードが入っているかもしれませんが気にしないでください。
弾発射に関するコードの解説
上記のコードは実行できるように弾以外の部分が
弾を発射する部分について掘り下げていきます。
・弾発射時の仕様フロー
1.「発射」ボタンを押す
↓
2.ボタンをタップされている間、一定間隔で弾を発射する
↓
3.フリックの方向に弾プレハブを発射
↓
4.弾が何かとぶつかったら消える
・仕様解説
1.「発射」ボタンを押す
「Ply_TapEv」ファイルの「Tap_Shot_On()」関数
この関数で、ボタン押下開始時の座標を保持します。
/*********************************************************************** モジュール名: GetNowTapPoint 概要 : タップ座標取得 引数 : なし 戻り値 : Vector2:タップ中の座標 ***********************************************************************/ public Vector2 GetNowTapPoint() { //============================================================ // エディター・実機ごとにタップ位置取得 //============================================================ Vector2 Vct2_Ret = new Vector2(); // エディター if (AppConst.IsEditor == true) { Vct2_Ret = Camera.main.ScreenToWorldPoint(Input.mousePosition); } // Android実機 else { for (int i_LpCnt = 0; i_LpCnt < Input.touchCount; i_LpCnt++) { Touch touch_One = Input.GetTouch(i_LpCnt); Vct2_Ret = Camera.main.ScreenToWorldPoint(touch_One.position); // 【A】複数タップされる可能性があるので、適切なタップ位置を取得 // ※ここの判定は機種固有のものだと思われます if ((i_BtnType == Df_BtnId_Shot) && (Vct2_Ret.x > 0)) { break; } } } //================================================================= // 戻り値設定 //================================================================= return Vct2_Ret; }
このコードで、現在タップしている座標を取得できます。
エディターではマウスのクリック位置、
Android実機ではTouchクラスの「position」という要素を取得しています。
この時、「Input.GetTouch(番号)」で取得できるTouch情報は、
ボタンのタップ情報に限らず、
5か所タップされていた場合は5つのタップ情報が格納されています
なので、機種仕様に合わせて判定で適切なTouchクラスを取得してください
※ソースの【A】部分を編集する
例としては、「タップ座標がボタンの画像範囲内の座標なら取得」とかだといいと思います。
2.ボタンをタップされている間、一定間隔で弾を発射する
割り込み処理でタイマー値を減算させることで
一定時間で弾を発射する仕様になります。
//**************************************************** // 割り込み関数 //**************************************************** void FixedUpdate() { //------------------------------------------------ // 弾丸管理 //------------------------------------------------ if (Cls_SceneOneIf.cls_BtnIf[Df_BtnId_Shot] != null) { SetBullet_Shot(); } } /*************************************************************************** メソッド : SetBullet_Shot 概要 : バレット発射処理 ***************************************************************************/ public static void SetBullet_Shot() { //====================================================================== // 変数定義 //====================================================================== SceneOneIf SceneIf = Cls_SceneOneIf; Obj_All ObjIf = Cls_ObjAll; //====================================================================== // ショットボタン押下中判定 //====================================================================== if (SceneIf.cls_BtnIf[Df_BtnId_Shot] == null) { return; } //====================================================================== // 弾丸発射処理 //====================================================================== //---------------------------------------------------------------- // タイマー完了判定 //---------------------------------------------------------------- ObjIf.BulletIf.i_ShotWait--; if (ObjIf.BulletIf.i_ShotWait > 0) { return; } //---------------------------------------------------------------- // 弾丸発射 //---------------------------------------------------------------- ObjIf.BulletIf.SetBulletNd_Stat(); //---------------------------------------------------------------- // タイマー値初期化 //---------------------------------------------------------------- if (ObjIf.BulletIf.i_BltCnt >= 3) { ObjIf.BulletIf.i_BltCnt = 0; ObjIf.BulletIf.i_ShotWait = Df_Bullet_Wait2; } else { ObjIf.BulletIf.i_ShotWait = Df_Bullet_Wait; } }
毎割り込みでタイマー変数(ObjIf.BulletIf.i_ShotWait)を減算して、
0になったら弾発射関数を呼び出しています。
関数呼び出し後、変数にウェイト定数(Df_Bullet_Wait、_Wait2)を再設定します。
発射した弾数(ObjIf.BulletIf.i_BltCnt)が3個になったら大ウェイト(Df_Bullet_Wait2)
を設定する仕様になっています。
3.フリックの方向に弾プレハブを発射
//--------------------------------------------------------------- // 角度設定 //--------------------------------------------------------------- // 開始・終点座標から角度計算 Vct2_Stat = SceneIf.cls_BtnIf[Df_BtnId_Shot].GetNowTapPoint(); Vct2_End = SceneIf.cls_BtnIf[Df_BtnId_Shot].vct3_StatPosi; Vct2_Cal_S = new Vector2(1, 0); Vct2_Cal_E = Vct2_Stat - Vct2_End; f_Kakudo = Vector2.Angle(Vct2_Cal_S, Vct2_Cal_E); // 座標から向き設定 if (Vct2_Stat.y - Vct2_End.y < 0f) { f_Kakudo = f_Kakudo * (-1f); } // 座標が同じなら前に発射書き換え if (Vct2_Stat == Vct2_End) { f_Kakudo = 0; } //========================================================= // 弾オブジェクトを設定 //========================================================= //--------------------------------------------------------------- // 速度ベクトルを設定 //--------------------------------------------------------------- Vct2_Cal_Set.x = Mathf.Cos(Mathf.Deg2Rad * f_Kakudo) * f_Speed; Vct2_Cal_Set.y = Mathf.Sin(Mathf.Deg2Rad * f_Kakudo) * f_Speed; R2d_Set.velocity = Vct2_Cal_Set; //--------------------------------------------------------------- // 画像の角度を合わせる //--------------------------------------------------------------- Quaternion Quat_Set = Quaternion.identity; Quat_Set.eulerAngles = new Vector3(0, 0, f_Kakudo + 90); Obj_Set.transform.rotation = Quat_Set; }
上記のソースでタップの方向に弾を発射できます。
・変数概要
Vct2_Stat:現在タップしている座標
Vct2_End:ボタンタップ開始時の座標
f_Kakudo:計算後の角度
f_Speed:弾の速さ
R2d_Set.velocity:設定する弾のRigidbody2Dクラス変数
Obj_Set.transform.rotation:設定する弾の画像の角度
・処理概要
「// 角度設定」
フリック角度を計算
「// 速度ベクトルを設定」
弾画像に計算した角度に向かって進む力を設定
※.タップ座標が開始・現在どちらも同じなら前に飛ばす仕様
「// 画像の角度を合わせる」
画像が進行方向に向くように設定
4.弾が何かとぶつかったら消える
//*************************************************************************** // 衝突時に呼ばれるイベント //*************************************************************************** private void OnTriggerEnter2D(Collider2D col_Get) { //========================================================================= // 衝突判定 ※衝突オブジェクトのタグで判定している //========================================================================= if ( (col_Get.gameObject.tag == Df_TagName[Df_Tag_No]) || (col_Get.gameObject.tag == Df_TagName[Df_Tag_MainC]) ) { return; } //========================================================================= // 変数定義 //========================================================================= SceneOneIf SceneIf = Cls_SceneOneIf; Obj_All ObjIf = Cls_ObjAll; //========================================================================= // 衝突した弾丸オブジェクトを非表示 //========================================================================= int i_SetId = 0; i_SetId = int.Parse(this.name.Replace(Df_Bullet_Name, "")); ObjIf.BulletIf.SetBulletNd_End(i_SetId); } /************************************************************************ メソッド : SetBulletNd_End 概要 : 弾丸消去処理 ************************************************************************/ public void SetBulletNd_End(int i_EndId) { // ぶつかったオブジェクトを非表示にする l_Obj_Object[i_EndId].SetActive(false); }
上記ソースで弾がぶつかった時に消去されるようになります。
「// 衝突判定」部分は、「未定義、メインキャラ」のタグでは消えない判定を行っています。
理由は、弾発射時に必ずキャラにぶつかってしまうからです。
このTAG判定部分を変更することで、弾が貫通するオブジェクトを作ったりできます。
「// 衝突した弾丸オブジェクトを非表示」では、
オブジェクト名から、何番目のプレハブを非表示にするのか判別する仕様です。
以上が、フリック角度に合わせて弾を発射する仕様です。
言いたいこと以外の部分がめちゃくちゃ多かったので異常な長さに・・・
昨日書き始めたのですが予想以上に書くことが多すぎて2日かかりました。
相手がどこまで知っている前提で書くのか。
この要素ってものすごい大事ですね・・・