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

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

ただいまの
回答率

87.59%

プレイヤー弾がプレイヤーの後ろから出て、プレイヤーが押される

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,194

score 21

プレイヤーに弾を発射させる設定をしており、プレイヤーと弾自体につけるスクリプトが出来た時点で動作確認をしたところ、弾がプレイヤーの後ろで生成され、プレイヤーが押されてしまいました。
弾をプレイヤーの前方から発射するには、どこを変えたら良いでしょうか?

イメージ説明
※座標は弾が生成された座標で、x座標がプレイヤーの初期位置である「StartPos」のものと同じになっている様です。

また、弾とプレイヤーが衝突しない様にProjectSettingsで設定したのにプレイヤーが押されるのも、よく分かりません。
↓参考サイト
https://yokubari.online/unity/how-to-prefab-and-layer/

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

↓弾のインスペクター
イメージ説明
イメージ説明
イメージ説明

※弾はプレイヤーの子オブジェクトにしたり、Hierarchyに設置したりせず、プレイヤーにつけたスクリプトからProjectにあるプレハブのBulletを選択している状態です。

↓弾のスクリプト

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;

    void Start()
    {
        // オブジェクトのRigidbody2Dを取得
        rb2d = GetComponent<Rigidbody2D>();
        // 弾オブジェクトの移動係数を初期化
        bulletSpeed = 10.0f;
        // 出現から3秒後に弾オブジェクトを消滅させる(メモリの節約)
        Destroy(gameObject, 3.0f);
    }

    void Update()
    {
        // 弾オブジェクトの移動関数
        BulletMove();
    }

    // 弾オブジェクトの移動関数
    void BulletMove()
    {
        // 弾オブジェクトの移動量ベクトルを作成(数値情報)
        Vector2 bulletMovement = new Vector2(1, 0).normalized;
        // Rigidbody2D に移動量を加算する
        rb2d.velocity = bulletMovement * bulletSpeed;
    }

    // ENEMYと接触したときの関数
    void OnCollisionEnter2D(Collision2D collision)
    {
        // ENEMYに弾が接触したら弾は消滅する
        if (collision.gameObject.tag == "Enemy")
        {
            Destroy(gameObject);
        }
    }
}


↓プレイヤーのインスペクター
イメージ説明
イメージ説明
イメージ説明

↓プレイヤー側のスクリプト
(字数制限で、「Player」のコードが貼れず、画像も反映されなくなったため省略しましたが、解決に必要とあれば、後で追記します。すみません。)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerBullet : MonoBehaviour
{
#pragma warning disable 0649
    // InspectorでPrefab化したBulletを指定する
    [SerializeField]
    private GameObject bullet;

    void Update()
    {
        // 弾オブジェクトを生成して飛ばす関数を呼び出す
        ShotAction();
    }

    // 弾オブジェクトを生成して飛ばす関数
    void ShotAction()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            Instantiate(bullet, transform.position, transform.rotation);
            Debug.Log(transform.position);
        }
    }
}

Unityバージョン:Unity 2019.2.15f1 (64-bit)

追記:5/13に教えて頂いたスクリプトについて

スクリプトを教えて頂いたものに変更したところ、弾がプレイヤーの後ろに飛んで行く様になりました。
やはりプレイヤーの向きが変わっても、弾の方向は変わっていません。
足りていないと思って、私が自分で足した部分が原因でしょうか?

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);
        }

    }
}
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);
        }
    }
}

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

こんにちは。
PlayerBulletクラスのShotAction()関数を見る限り、
弾の生成にはInstantiate()関数を使っているようですので、生成する座標を前方分足してあげれば、解決できると思います。
Object.Instantiate

現在記述しているInstantiate(bullet, transform.position, transform.rotation);
の第2引数としてしているtransform.positionが弾の生成される座標になります。
transform.positionPlayerBulletのGameObjectの座標ですから、このままでは同じ位置に生成されてしまいます。
この部分をプレイヤーが右方向なら x座標に+1, 左方向なら-1することで、プレイヤーの前方に弾のGameObjectが生成できるはずです。

void ShotAction()
{
    if (Input.GetButtonDown("Fire1"))
    {
        // 1.0fは適当な数値です。
        // 前方に出したい分の値を指定してください。
        Vector3 offset = new Vector3(1.0f, 0.0f, 0.0f);

        // isLeft は仮の変数です。現在向いている方向を判定するフラグなどを用意してみてください。
        // 向いている方向が反対ならx座標を反転する
        if (isLeft)
        {
            offset.x = -offset.x;
        }

        // 生成座標をオフセット分足す。
        Instantiate(bullet, transform.position + offset, transform.rotation);
        Debug.Log(transform.position);
    }
}

また、弾とプレイヤーが衝突しない様にProjectSettingsで設定したのにプレイヤーが押されるのも、よく分かりません。

これに関しては実際に作成したレイヤーを各GameObjectに対して設定してあげる必要があります。
PlayerのameObjectにはPlayerを、弾のGameObjectにはBulletのレイヤーを指定すれば、
現在のProjectSettingsの設定を見る限り、コリジョンの衝突が行われなくなるはずです。
イメージ説明

追記:弾について
弾そのものも右方向に進むのか、左方向に進むのかを設定してあげる必要があると思います。
いろいろやり方がありますが、以下の処理ではシンプルに進行方向を設定する関数を用意してそれを生成時に指定するようにしています。
ご参考ください。

public class Bullet : MonoBehaviour
{
    // 弾オブジェクトのRigidbody2Dの入れ物
    private Rigidbody2D rb2d;
    // 弾オブジェクトの移動係数(速度調整用)
    float bulletSpeed;

    private Vector2 direction = Vector2.right;

    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;
    }
}
public class PlayerBullet : MonoBehaviour
{
    // InspectorでPrefab化したBulletを指定する
    [SerializeField]
    private GameObject bullet;

    // ユーザーがどちらを向いているか
    private bool isLeft = true;

    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);
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/16 17:50

    新しいコメントがついていることに気づいていませんでした。すみません。
    私もよく理解できておらず、教えて頂いたスクリプトをそのまま使っているだけでした。
    具体的に、どこにtrue/falseの分岐を作れば良いでしょうか?
    また、trueの時・falseの時に、どんな内容を書けば良いでしょうか?

    キャンセル

  • 2020/05/16 21:39

    質問でアップしている画像を見る限り、キャラクターが移動しているようなので、
    恐らく、キャラクター操作スクリプトは別で用意しているんですよね?
    キャラクター操作スクリプトなら進行方向がどちらかはわかると思います。
    そのキャラクター操作スクリプトから PlayerBullet に対してどちらに向いているかを設定してあげればよいのではないでしょうか。

    キャンセル

  • 2020/05/17 01:48

    ありがとうございます。
    解決済みの質問のコメント欄でのやり取りが長くなってきているので、情報整理のために新しい質問として投稿しました。
    良ければ、ご確認下さい。

    キャンセル

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る