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

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

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

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

3回答

5753閲覧

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

terrat

総合スコア14

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

0クリップ

投稿2019/06/15 12:24

編集2019/06/15 13:58

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

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class ScriptableCharaController : MonoBehaviour { 6 7 public EnemyData enemyData; 8 9 void Start(){ 10 ShowScriptableObjectData(); 11 } 12 13 void Update(){ 14 15 } 16 17 void ShowScriptableObjectData(){ 18 // 参照しているEnemyDataの中身をコンソールに表示する 19 Debug.Log("私の名前は" + enemyData.enemyName + 20 ", 最大HPは" + enemyData.maxHp + 21 ", 攻撃力は" + enemyData.atk + 22 ", 防御力は" + enemyData.def + 23 ", 経験値は" + enemyData.exp + 24 ", ゴールドは" + enemyData.gold + "です。"); 25 }

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

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5[CreateAssetMenu(menuName = "MyScriptable/Create EnemyData")] 6public class EnemyData : ScriptableObject { 7 public string enemyName; 8 public int maxHp; 9 public int atk; 10 public int def; 11 public int exp; 12 public int gold; 13}

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

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

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

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

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

guest

回答3

0

ベストアンサー

混乱を招くのは「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/16 06:08

編集2019/06/16 06:22
sakura_hana

総合スコア11427

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

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

terrat

2019/06/19 12:44

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

0

2つ考えられます。

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

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

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

投稿2019/06/15 13:06

編集2019/06/15 14:32
gentaro

総合スコア8949

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

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

terrat

2019/06/15 14:37

public class EnemyData : ScriptableObject { とあるのでクラスではないかと思います(上の本文で追記しました)。 であればおっしゃる2択の1つ目ということになるでしょうか? ですが内容が理解できません(すみません・・・)。「インスタンス変数のenemyDataがpublicなので、ShowScriptableObjectData()を呼ぶ側のスクリプト内でnewする前提で定義だけに留めている」という理解でいいでしょうか? それだとするとStart()でShowScriptableObjectData()が呼ばれていて、newしないままログ出力までできているのがもう何がなんだか(泣)
gentaro

2019/06/15 14:46 編集

ものすごく乱暴な言い方をすれば「どっかで誰かが魔法を使ってnewしてくれる」という事です。 ちょっとググってみましたが、どうやらアセットファイルとして保存してある内容をデシリアライズしてくれるみたいですね。 そのための呪文が [CreateAssetMenu(menuName = "MyScriptable/Create EnemyData")] で、この属性がついていると、Unityのフレームワーク側がファイルの中身を読んでオブジェクトをnewして突っ込んでくれる、ぐらいの理解で良いんじゃないでしょうか。
len_souko

2019/06/15 14:49

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

2019/06/15 15:01

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

2019/06/15 15:06 編集

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

0

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

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

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

投稿2019/06/15 14:51

Zuishin

総合スコア28660

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問