質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

5886閲覧

プレイヤーの弾が後ろに飛んで行く、向きが変わらない

unity_user_a

総合スコア23

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/05/16 16:44

編集2020/05/18 09:33

Unity初心者です。「プレイヤーの弾が後ろに飛んで行く」、「プレイヤーの向きが変わっても、弾の向きが変わらない」のを修正したいです。

イメージ説明
イメージ説明

字数制限のため、プレイヤーのスクリプトは画像になります。分かり辛くてすみません。

プレイヤーのスクリプト
イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明

プレイヤーについている弾発射用スクリプト

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerBullet : MonoBehaviour { #pragma warning disable 0649 // InspectorでPrefab化したBulletを指定する [SerializeField] private GameObject bullet; // ユーザーがどちらを向いているか private bool isLeft = true; void Update() { // 弾オブジェクトを生成して飛ばす関数を呼び出す ShotAction(); } void ShotAction() { Vector3 offset = new Vector3(1.0f, 0.0f, 0.0f); // isLeft は仮の変数です。現在向いている方向を判定するフラグなどを用意してみてください。 // 向いている方向が反対ならx座標を反転する if (isLeft) { offset.x = -offset.x; } if (Input.GetButtonDown("Fire1")) { // Bulletコンポーネントがアタッチしている前提 var bulletObj = Instantiate(bullet, transform.position + offset, transform.rotation); bulletObj.GetComponent<Bullet>().SetDirection(isLeft); } } }

弾のスクリプト

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bullet : MonoBehaviour { // 弾オブジェクト(Inspectorでオブジェクトを指定) [SerializeField] // Inspectorで操作できるように属性を追加します private GameObject bullet; // 弾オブジェクトのRigidbody2Dの入れ物 private Rigidbody2D rb2d; // 弾オブジェクトの移動係数(速度調整用) float bulletSpeed; private Vector2 direction = Vector2.right; void Start() { // オブジェクトのRigidbody2Dを取得 rb2d = GetComponent<Rigidbody2D>(); // 弾オブジェクトの移動係数を初期化 bulletSpeed = 10.0f; // 出現から3秒後に弾オブジェクトを消滅させる(メモリの節約) Destroy(gameObject, 3.0f); } void Update() { // 弾オブジェクトの移動関数 BulletMove(); } public void SetDirection(bool isLeft) { // 左方向なら(-1.0, 0.0)方向に、右方向なら(1.0, 0.0)方向に進む direction = isLeft ? Vector2.left : Vector2.right; // スプライト画像の反転処理(画像のデフォルトが右方向の向いているもの前提) var sprite = GetComponent<SpriteRenderer>(); if (sprite != null) { sprite.flipY = isLeft; } } void BulletMove() { // Rigidbody2D に移動量を加算する rb2d.velocity = direction * bulletSpeed; } // ENEMYと接触したときの関数 void OnCollisionEnter2D(Collision2D collision) { // ENEMYに弾が接触したら弾は消滅する if (collision.gameObject.tag == "Enemy") { Destroy(gameObject); } if (collision.gameObject.tag == "Ground") { Destroy(gameObject); } if (collision.gameObject.tag == "MoveFloor") { Destroy(gameObject); } if (collision.gameObject.tag == "JumpStep") { Destroy(gameObject); } if (collision.gameObject.tag == "GroundPlatform") { Destroy(gameObject); } } }

弾はプレイヤーの子オブジェクトにせず、Project上にあるPrefabをInspectorから指定しています。

追記(5/17)
PlayerBulletのprivate bool isLeft の = true; を消したところ、弾が前方(左方向)に飛んで行く様になりました。当然かも知れませんが、プレイヤーの向きが変わっても左に飛んで行きます。

追記(5/18)
PlayerBulletとBulletのコードは、以前投稿した「プレイヤー弾がプレイヤーの後ろから出て、プレイヤーが押される」で、回答として頂いたコードをもとにしています。「isLeft は仮の変数です」といった所々の書き込みもそのまま残してあります。

追記_2
頂いたアドバイスをもとに下記まで進みました。

private float GetXSpeed() { float horizontalKey = Input.GetAxis("Horizontal"); float xSpeed = 0.0f; if (horizontalKey > 0) { transform.localScale = new Vector3(1, 1, 1); isRun = true; dashTime += Time.deltaTime; xSpeed = speed; isLeft = true; //New } else if (horizontalKey < 0) { transform.localScale = new Vector3(-1, 1, 1); isRun = true; dashTime += Time.deltaTime; xSpeed = -speed; isLeft = false; //New } else { isRun = false; xSpeed = 0.0f; dashTime = 0.0f; }

※プライベート変数をまとめてある部分に「public bool isLeft = false;」も追加してあります。

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerBullet : MonoBehaviour { // InspectorでPrefab化したBulletを指定する [SerializeField] public GameObject bullet; public GameObject player; //New private bool isLeft; // ユーザーがどちらを向いているか void Start() { isLeft = player.GetComponent<Player>().isLeft; } void Update() { // 弾オブジェクトを生成して飛ばす関数を呼び出す ShotAction(); } void ShotAction() { Vector3 offset = new Vector3(1.0f, 0.0f, 0.0f); //New if(isLeft == true) { } if(isLeft == false) { } if (Input.GetButtonDown("Fire1")) { // Bulletコンポーネントがアタッチしている前提 var bulletObj = Instantiate(bullet, transform.position + offset, transform.rotation); bulletObj.GetComponent<Bullet>().SetDirection(isLeft); } } }

あと少しだと思うのですが、PlayerBulletのコードで ==trueと==false の中身をどう書いたら良いのかで悩んでいます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakura_hana

2020/05/18 00:18

「isLeft は仮の変数です。現在向いている方向を判定するフラグなどを用意してみてください。」とコメントに書いてあります。 「プレイヤーの向きを決めている部分」がどこかを把握していれば向きが分かると思いますが、自分で書いたコードですか? もし書籍やサイトを元にしているコードなら出典を記載すべきです。
unity_user_a

2020/05/18 04:44

ご指摘ありがとうございます。 私が自分で書いたコードではありません。 以前投稿した「プレイヤー弾がプレイヤーの後ろから出て、プレイヤーが押される」という質問で頂いた回答のコードをもとにしています。 そこに少し書き加えている状態だと思いますが。
guest

回答2

0

ベストアンサー

初心者さんらしいので考え方から記載します。
(本当は全てのコードの意味を把握すべきですが、重要な部分から理解していってください)

今回必要なのは「プレイヤーの方向を取得すること」です。
では「どのタイミングでプレイヤーの方向が変わる」でしょうか。
外的要因では変わらないという仕様なら「ユーザーが左右の入力をした時」ですね。
つまりInput.GetAxis("Horizontal")がある場所が怪しいです。

これを元にコードを見ていくと、PlayerクラスのGetXSpeedメソッドのhorizontalKeyの分岐がそれに該当すると分かります。
transform.localScale = new Vector3(-1, 1, 1);という記載からも、ここで画像を左右反転させている=方向が変わっている、と分かります)

ということは、Playerクラスにpublicな変数isLeftを作り、上記部分でtrue/falseを切り替え。
あとはPlayerBulletクラスからPlayerクラスのisLeftにアクセスして、その値により弾の向きを判定すれば想定通りの動きになります。
(別クラスの変数の取得は既に使っているので理解済みだと思うので割愛)


ちなみに別解。
上記のように「localScaleで左右表示を切り替えている」と分かれば、変数を挟まずに
if (transform.localScale.x == 1) {}
と直で調べてしまうことも出来ます。(これは右向きの時に条件を満たす)(transformの参照は適宜正しく取ってください)

これは「"右向き"というのはどういうことか?」を考えて、それぞれのコードが意味するところが分かっていれば導けます。
最初は難しいかもしれませんが理解すると色々出来るので頑張ってみてください。


(質問文編集を受けて追記)

質問文には元々方向反転の記述がありますよね。
何故消してしまったのでしょうか。そのまま利用すればいいです。

また、これは動かしてみれば分かりますが、boolは値型の変数なので「代入したタイミングの値をコピー」します。
つまりStartメソッド内にisLeft = player.GetComponent<Player>().isLeft;がありますが、
これだと「StartしたタイミングでのPlayerクラスのisLeft」しか反映されません。
必要なタイミング(今回は発射ボタンを押したタイミング)で代入しましょう。

更にこれはオマケですが、負荷についても考慮しましょう。
Updateはそのままだと毎フレーム実行されます。向き情報(offsetの用意)が必要なのは弾が発射された時だけなので、if (Input.GetButtonDown("Fire1"))の中に入れると余計な実行が減らせます。
また、出来るだけGetComponentの回数は減らした方が負荷が減るので、(今回はそう大差無いでしょうが)そういう風に書く癖を付けておきましょう。

という訳でPlayerBulletクラスを以下のように書くと上手くいくと思います。

C#

1public class PlayerBullet : MonoBehaviour 2{ 3 // InspectorでPrefab化したBulletを指定する 4 [SerializeField] 5 public GameObject bullet; 6 public Player player; //編集:Playerクラスをそのまま受け取ります 7 8 //private bool isLeft; //編集:1つのメソッドの中でしか使わないので不要です 9 10 // ユーザーがどちらを向いているか 11 void Start() 12 { 13 //isLeft = player.GetComponent<Player>().isLeft; //ここも不要 14 } 15 16 void Update() 17 { 18 // 弾オブジェクトを生成して飛ばす関数を呼び出す 19 ShotAction(); 20 } 21 22 void ShotAction() 23 { 24 //offsetの用意はボタンを押した時の処理内に移動します 25 26 if (Input.GetButtonDown("Fire1")) 27 { 28 Vector3 offset = new Vector3(1.0f, 0.0f, 0.0f); //移動してきました 29 bool isLeft = player.isLeft; //ここで受け取り・Playerクラスをそのまま受け取っているのでGetComponentは要りません 30 if (isLeft) 31 { 32 offset.x = -offset.x; //元コードと同じです 33 } 34 35 // Bulletコンポーネントがアタッチしている前提 36 var bulletObj = Instantiate(bullet, transform.position + offset, transform.rotation); 37 bulletObj.GetComponent<Bullet>().SetDirection(isLeft); 38 } 39 } 40} 41

投稿2020/05/18 05:15

編集2020/05/18 11:04
sakura_hana

総合スコア11427

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

unity_user_a

2020/05/18 09:35

頂いたアドバイスをもとに進めてみました。 追記を更新しましたので、宜しければご確認ください。
unity_user_a

2020/05/18 10:30

ありがとうございます。 コードを追記して頂いたものに変更しました。 動かしてみると、弾がプレイヤーの向きと反対に飛んで行ってしまうのですが、どこの数値を修正すれば良いでしょうか? プレイヤーがスタート地点から動いていない状態だと、プレイヤーと同じ向きに飛んで行きます。
unity_user_a

2020/05/18 10:34

playerのコードでtrueとfalseを逆にしたら、飛んで行く方向は一致する様になりました。 ですが、弾の画像の向きが変わりません。
sakura_hana

2020/05/18 11:05

読み間違えてましたが画像自体の向きは変わってないんですねこのコード。 であればPlayerと同じことをすればいいので、 var bulletObj = 〜 の次の行あたりに、 bulletObj.transform.localScale = new Vector3( isLeft ? -1 : 1, 1, 1); とするとどうでしょうか。 (この書き方を「三項演算子」といいます。Bulletクラスでも使われています。 Vector3のX値を、isLeftがtrueなら-1、falseなら1にしています。もし逆だったら値を反対にしてください)
unity_user_a

2020/05/18 11:26

教えて頂いたコードで、無事に解決出来ました。 とても丁寧に教えて頂き、本当にありがとうございました! また、一日がかりでお時間を使わせてしまいすみませんでした。 これからも、ゲーム制作を通して学習を続けていきます。
guest

0

プレイヤーの向きに関わらず、isLeftがtrueになっているからではないですか?
向きに応じてisLeftの値を切り替える必要があると思います。

投稿2020/05/16 17:52

mattrick

総合スコア135

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

unity_user_a

2020/05/18 04:49

ご回答ありがとうございます。 頂いたアドバイスだけでは、今のコードをどう変えたら良いのかイメージが難しいです。すみません。 具体的にどの様なコードをどの部分に書き加えたら良いのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問