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

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

ただいまの
回答率

90.03%

newしなくてもいいんでしょうか?

解決済

回答 3

投稿 編集

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

terrat

score 12

下のソースコードはScriptableObjectを継承したクラスEnemyDataにあるフィールドの値をコンソールに表示しているそうです。
「クラスの中身を利用したければnewでインスタンスを生成しなければならない」と思っているのですが、下のソースコードではnewせずEnemyDataの中身を利用しているようです。
public EnemyData enemyData;と定義したらenemyData = new EnemyData();とインスタンス化しなければデータを扱えないと考えてしまうのですが・・・どういうことなんでしょうか?

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

public class ScriptableCharaController : MonoBehaviour {

    public EnemyData enemyData;

    void Start(){
        ShowScriptableObjectData();
    }

    void Update(){

    }

    void ShowScriptableObjectData(){
        // 参照しているEnemyDataの中身をコンソールに表示する
        Debug.Log("私の名前は" + enemyData.enemyName + 
                    ", 最大HPは" + enemyData.maxHp + 
                    ", 攻撃力は" + enemyData.atk +
                    ", 防御力は" + enemyData.def +
                    ", 経験値は" + enemyData.exp +
                    ", ゴールドは" + enemyData.gold + "です。");
    }


下は参照先のEnemyDataクラスです。

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

[CreateAssetMenu(menuName = "MyScriptable/Create EnemyData")]
public class EnemyData : ScriptableObject {
    public string enemyName;
    public int maxHp;
    public int atk;
    public int def;
    public int exp;
    public int gold;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+3

混乱を招くのは「EnemyDataがインスタンス化されるのはいつか」と「enemyData変数にオブジェクトが入るのはいつか」が別であるからだと思います。

EnemyDataがインスタンス化されるのはいつか

自分でまとめようかと思ってたら既に情報がありました。
【Unity】ScriptableObjectを使用した、コンポーネント・シーン間でのデータ共有について - テラシュールブログ

ScriptableObjectはアセットでありインスタンスである

というわけで、インスタンス化されるのは「ScriptableObjectアセットを作った瞬間」です。
(これはScriptableObjectを継承したクラスの特性です)

[CreateAssetMenu(menuName = "MyScriptable/Create EnemyData")]
は「こういう名前のメニューを用意しますよ、それが選択されたらこのスクリプトを実行しますよ(その結果EnemyDataというScriptableObjectが生成されますよ)」という意味のコードです。

つまりnew EnemyData()に匹敵するのは、このメニューを実行した瞬間(=プロジェクトフォルダ内にEnemyDataアセットが出来た瞬間)ということになります。

enemyData変数にオブジェクトが入るのはいつか

「ScriptableCharaControllerコンポーネントのインスペクター上で、enemyData変数にEnemyDataアセットをドラッグ&ドロップした時」
または「別のスクリプトから何らかの方法で設定した時」です。

これは通常の参照型の変数と何ら変わりません。
public GameObject enemyObj;と同じようなものである、ということ)

なのでインスペクター上で設定せず、他スクリプトからの設定も無ければ、enemyDataはnullのままであり、ShowScriptableObjectDataメソッド内のDebug.Logはエラーになります。


とても余談ですが、MonoBehaviourを継承したクラスもnew出来ません。
「そのクラスが付与されているGameObjectが生成された瞬間」or「AddComponentメソッドによりGameObjectに付与された瞬間」にインスタンス化される為です。(内部的にはnewされていることに違いはありませんが、自分でnewしようとすると警告を出してくると思います)
Unity(のMonoBehaviour)はそういうもの、という認識でいいと思います。

これらの継承が無いクラスのインスタンスを作りたければnewする必要があります。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/19 21:44

    非常にわかりやすかったです!
    理解できました。ありがとうございました。
    ご回答くださった皆さんもありがとうございました。

    キャンセル

+3

2つ考えられます。

  1. publicフィールドなのでそのクラスの利用者側がnewしてセットする前提で作られている(よろしくないですが)
  2. EnemyDataがクラスではなく構造体(struct)

たぶん後者じゃないかと。

なんか質問が編集されてたので2じゃないっぽいですね。
Unity自体はよく知らないんですが、1です。
属性が付いてるので、DIっぽい感じで開発環境やフレームワークと連携してインスタンスがセットされる仕組みになってるのかと。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/15 23:49

    Unityは門外漢だけど
    >[CreateAssetMenu(menuName = "MyScriptable/Create EnemyData")]
    この属性の部分があるから、そのアセットやらの設定メニューか何かに表示されるんじゃないかな?
    で、その設定メニューか何かに表示するって属性があるので設定メニューに表示するために裏でこっそりとnewされてるって推測かと思われる

    キャンセル

  • 2019/06/16 00:01

    属性がnewしてくれてるというのは頭にありませんでした・・・。
    >この属性がついていると、Unityのフレームワーク側がファイルの中身を読んでオブジェクトをnewして突っ込んでくれる
    とりあえずこの考え方で納得できました。属性についてはまだ未学習だったので調べてみようと思います。
    newしてないじゃないか!って思うことが度々あって調べてもわからなくて騙し騙し学習してたので回答してもらえて本当に良かったです。
    ありがとうございました。

    キャンセル

  • 2019/06/16 00:06 編集

    もう少し正確に言えば、属性は目印みたいなもんで、Unityフレームワークがこの目印がついていればファイルの中身を読んでオブジェクトを作ってセットしてくれる、ということです。
    menuName = "MyScriptable/Create EnemyData"
    あたりで何のデータをどこにセットするのか指定するっぽいですね。(この場合はEnemyDataになってる)
    そのあたりの指定の詳しいやり方は調べてみて下さい。

    キャンセル

+2

この辺読んでみてください。

【Unity】ScriptableObjectってなんなん? って時に読む記事【解説】

ScriptableObject であり、CreateAssetMenu 属性がついていることで、メニューからあらかじめ作成されています。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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