0 支持
68 閲覧

プレイヤーの操作するオブジェクトが敵オブジェクトを踏んだ時に少し跳ねるコードを書きました。動作には成功したのですが、見返してみて、踏まれているかの判定のフラグを複数の異なる状態のオブジェクトから更新してしまうのではないかと疑問に思いました。正常に動作しているのでそうではないと捉えられますが、これは別のクラスとして扱われているということでしょうか。その場合、なぜそうなっているのか、unityのシステムについてなどご存じの方がいたら教えていただきたいです。

<オブジェクトと親子関係>
① プレイヤーが操作するオブジェクト
② 敵オブジェクトA(1)
     ー③ トリガー状態のコライダーを持つ子オブジェクト
④ 敵オブジェクトA(2)
     ー⑤ トリガー状態のコライダーを持つ子オブジェクト
(④は②のコピーです。)

<スクリプト1:③と⑤にアタッチ。スクリプト2から2つのメソッドを呼び出す>

public class PlayerCheck : MonoBehaviour
{
    private string playerTag = "Player"; //プレイヤー判別タグ//
    private bool underPlayer = false; //オブジェクト①に踏まれているか判定//
    private bool underPlayerEnter, underPlayerStay, underPlayerExit;

    private GameObject gon; //オブジェクト①のデータを格納//

    public bool UnderPlayer() //踏まれているかの判定メソッド//
    {
        if (underPlayerEnter || underPlayerStay)
        {
            underPlayer = true; //踏まれてる//
        }
        else if (underPlayerExit)
        {
            underPlayer = false; //踏まれてない//
        }

        underPlayerEnter = false;
        underPlayerStay = false;
        underPlayerExit = false; //リセット//

        return underPlayer; //判定を返す//
    }

    public GameObject GameObjectName()  //オブジェクト①のデータを渡すメソッド//
    {
        return gon;
    }

    private void OnTriggerEnter2D(Collider2D collision) //入った時のイベント関数//
    {
        if (collision.tag == playerTag)
        {
            underPlayerEnter = true;
            gon = collision.gameObject;
        }
    }

    private void OnTriggerStay2D(Collider2D collision) //入ってる時のイベント関数//
    {
        if (collision.tag == playerTag)
        {
            underPlayerStay = true;
            gon = collision.gameObject;
        }
    }

    private void OnTriggerExit2D(Collider2D collision) //出た時のイベント関数//
    {
        if (collision.tag == playerTag)
        {
            underPlayerExit = true;
            gon = collision.gameObject;
        }
    }
}

<スクリプト2:②と④にアタッチ。
       スクリプト1のメソッドを呼び出して利用する(一部抜粋)>

public class Enemy : MonoBehaviour
{
    public EnemyCheck_m enemy; //スクリプト1を格納(インスペクターからスクリプト①を選択)//
    public float EnemyJumpPower; //踏まれたときにオブジェクト①に加える力//

    private bool underPlayer = false; //踏まれているかのbool値を格納する変数//
    private GameObject gon = null; //オブジェクト①のデータを格納する変数//

    void Update()
    {
        if (sr.isVisible) //カメラ内にいるとき//
        {
            underPlayer = enemy.UnderPlayer();  //踏まれているか//
            gon = enemy.GameObjectName(); //オブジェクト①のデータを格納//

            if (underPlayer) //踏まれてるなら//
            {
                gon.GetComponent<Rigidbody2D>().velocity += new Vector2(0, 0);  //物理挙動にばらつきが出にくいように速度を一旦リセット//
                gon.GetComponent<Rigidbody2D>().AddForce(Vector2.up * EnemyJumpPower); //上方向に力を加える//
                Invoke("EnemyJump", EnemyDeadLong); //少し経ってからEnemyJumpメソッドを呼び出す//
            }
        }
        else //カメラ外にいる場合//
        {
            rb.Sleep(); //スリープさせる//
        }
    }

    void EnemyJump()
    {
        gameObject.SetActive(false); //オブジェクトを消す//
    }
}

よろしくお願いします。

初心者 (160 ポイント) | 68 閲覧

ログインまたはユーザー登録してから回答してください。

回答 1

+1 支持

まず、敵オブジェクトA(1)の子のコライダー(③)にアタッチしたPlayerCheckと、敵オブジェクトA(2)の子のコライダー(⑤)にアタッチしたPlayerCheckの、underPlayerフラグなどの状態が、それぞれ異なる値に更新されるのは、正常な動作です。

なぜそうなっているかという点については、Unityの仕組みというより、Unityのスクリプトに使うプログラミング言語であるC#に理由があります。

別のクラスとして扱われているということでしょうか

③と⑤が持っているPlayerCheckは、同じクラスから作られた別のインスタンスなので、フラグなどの状態はインスタンス毎に持っているからというのが、答えになるかと思います。

public class PlayerCheck : MonoBehaviour の様にMonoBehaviourを継承したクラス(Unityでいうコンポーネント)を書いているとあまりインスタンスを作るコードを書かないかもしれませんが、コンポーネントとしてgame objectにアタッチすると、Unityが内部的にそのクラスからインスタンスを作っています。

[第12回] クラスの基本的な使い方を学ぶ|Unityで学ぶC#入門 – XR-Hub
https://xr-hub.com/archives/9738

クラスとインスタンスについては、C#の基本的な機能なので解説するwebサイトが沢山あります。
例えばこのXR-HUBの記事なんかは、分かりやすいんじゃないかと思います。

【連載】Unityで学ぶC#入門 – XR-Hub
https://xr-hub.com/archives/15201

Unityを始めた事でC#も始める事になった人にちょうど良さそうな連載で15記事あるので、もしかしたら他の記事も読むと役に立つかもしれません。

https://wandbox.org/permlink/wctTLo70wKwoKSUL

あと、C#で書いた、1つのクラスから2つのインスタンスを作り、それぞれが異なる値を持っていて、片方だけ更新される例です。

見習い回答者 (820 ポイント)
0
インスタンス化ついて理解できていませんでした…。ありがとうございます!

関連する質問

0 支持
1 回答
0 支持
1 回答
物理屋さん 初心者 (400 ポイント) 1/21 質問 | 60 閲覧
0 支持
1 回答
勉強中 初心者 (210 ポイント) 2020 11/8 質問 | 116 閲覧
0 支持
1 回答
neoaco 初心者 (280 ポイント) 2020 8/17 質問 | 138 閲覧
2021-02-08 質問・回答をMarkdownで入力できるようにしました。
2020-09-03 新たなスパム対策を導入しました。

123 質問

127 回答

137 コメント

153 ユーザー