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

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

ただいまの
回答率

90.51%

  • Unity

    4024questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

staticだとアクセスエラー。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 155

tkmnusr

score 162

 前提・実現したいこと

同じインスタンスを取得してるはずなのに、
staticメソッドだとエラーになってしまいます。
static内でも「インスタンス.インスタンスメンバ」にアクセスできる方法があれば教えていただけませんか?
また、それが不可な場合は、その理由について教えていただきたいです。
ご教示お願い致します。

 該当のソースコード

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

public class Sample : MonoBehaviour {
    public int i = 20;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sample2 : MonoBehaviour {

    [SerializeField]
    Sample sample;

    void Start () {
        Sample2.MyStatic();
        this.MyStatic2();
    }

    static void MyStatic(){
        Debug.Log(sample.i);  //エラーになる。
    }

    void MyStatic2(){
        Debug.Log(sample.i);  //エラーにならない。
    }
}

 補足情報(FW/ツールのバージョンなど)

Unity

 追記質問。

「staticメソッド内部に記載された変数はstaticとして扱われる」
これをもっと掘り下げると、
「staticメソッド内部に記載されたローカル変数以外の変数やメソッドはstaticとして扱われる。」
で合っていますか?
また、下記コードのコメントも合っていますか?

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

public class Sample3 {
    public int i = 1;
    static int j = 2;

    public static void staticMethod(){
        //Debug.Log(i);   //Sample3クラスのstaticなiを参照しようとして見つからないのでエラー。
        Debug.Log(j);     //出力:2。Sample3クラスのstaticなjを参照する。
        MyMethod();       //出力:MyMethod。Sample3クラスのstaticなMyMethodを呼び出す。
        int k = 3;        //staticメソッド内で宣言した変数はローカル変数なのでstaticとして扱われない。
        Debug.Log(k);     //出力:3。
        Sample3 s = new Sample3();  //staticメソッド内で生成した変数はローカル変数なのでstaticとして扱われない。
        Debug.Log(s.i);   //出力:1。
    }

    public static void MyMethod(){
        Debug.Log("MyMethod");
    }

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

public class GameManager : MonoBehaviour {

    void Start () {
        Sample3.staticMethod();
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

同じインスタンスを取得していません
以下、staticとそうでないクラス/変数/メソッドのイメージです。

staticでないクラス/変数/メソッドは「インスタンス」として存在します。
SampleクラスおよびSample2クラスが付いたオブジェクト「SampleObj」がシーン上に存在していて、Sample2の変数sampleにSampleObjに付いているSampleクラスをセットしていたとすると、
sample.i は SampleObjに付いているSampleのi
sample2.MyStatic2() は SampleObjに付いているSample2のMyStatic2メソッド
となります。

一方、staticなクラス/変数/メソッドはインスタンスとして存在しません。
では何処に存在しているかというと、「static領域」にひとつだけ存在しています。
Sample2.MyStatic() は static領域のSample2のMyStaticメソッドを指していることになります。
(Sample2クラスが付いたオブジェクトが何個存在しようが、static領域のSample2のMyStaticメソッドというただ1つの存在を参照します)

C#のルールとして「staticメソッド内部に記載された変数はstaticとして扱われる」というものがあります。
つまりSample2.MyStatic()の中のsample.i は static領域のSample2の中の変数sampleのiを指しています。
しかしそんな変数は存在していません。
Sample2で定義されているsample変数は何らかのオブジェクトに付いているSampleクラス(=インスタンス)を指している為、static領域で変数sampleは宣言されていない為です。

なのでこの場合の対処方法は、Sample2の中のsample変数もstaticにすること(そしてその変数に適切なSampleクラスを代入しておくこと)です。

public class Sample2 : MonoBehaviour {
    //staticにする
    static Sample sample;

    void Start () {
        //static変数に値を入れる
        sample = GetComponent<Sample>();

        Sample2.MyStatic();
        this.MyStatic2();
    }

    static void MyStatic(){
        Debug.Log(sample.i);  //エラーにならない。
    }

    void MyStatic2(){
        Debug.Log(sample.i);  //エラーにならない。
    }
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/08 20:02

    ご回答ありがとうございます。
    「staticメソッド内部に記載された変数はstaticとして扱われる」ということを知りませんでした。
    こちらに関して、追記質問を追記しましたが、合っていますか?

    キャンセル

  • 2018/07/08 21:40

    多分合っています。

    厳密には、staticなメソッドの中で作ったローカル変数も、存在場所自体はstatic領域だと思います。
    ただメソッドを出た瞬間に消される上に外部からのアクセスも出来ない為、基本的にはローカル変数と同じ挙動をすると思っていいと思います。
    (但し非同期で複数箇所から同時に呼んだらどうなるのかはちょっと分からないです……)

    キャンセル

  • 2018/07/08 22:50

    ご回答ありがとうございます。
    なるほど、static内は全てstatic領域だから厳密にはローカル変数もstaticなのですね。

    今回理解させていただいたことをメモの為、下記にまとめました。
    ローカル変数の言い回しは厳密ではないと思いますが、下記で他に問題点がありましたら、ご指摘いただけたら幸いです。
    「staticメソッド内部に記載されたローカル変数以外の変数やメソッドはstaticとして扱われる。
     これより、staticメソッド内部で、ローカル変数以外でstaticでない変数やメソッドを参照しようとすると、それらの変数やメソッドをstaticなもので探しにいくので、参照エラーを起こす。」

    キャンセル

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

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

関連した質問

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

  • Unity

    4024questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。