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

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

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

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

Unity

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

Q&A

解決済

3回答

851閲覧

Unity C# Listの使い方

gozi200

総合スコア6

C#

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

Unity

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

0グッド

1クリップ

投稿2017/12/26 03:41

###前提・実現したいこと
Listを使ってゲームで使用する、ステータスを持ったプレイヤーを作成したいです

###発生している問題・エラーメッセージ
PlayerクラスでListを作り、他のクラスでListにAddしています。
そうするとPlayerクラスの方でAddしたものが反映されず困っています。
csvで行っているのですが、値を入れるところは問題なくできているので、コードを省略します。
Addしているところにブレークポイントを立てて確認したところ、そこではきちんと値が入っていました。

###該当のソースコード

C#

1public class Player : MonoBehaviour { 2 private Player_Data player_data; 3 private Player_Status player_status; 4 5 public List<Player_Status> players = new List<Player_Status>(); 6 7 void Start() { 8 player_data = GetComponent<Player_Data>(); 9 player_data.Set_Parameter(); 10 }  11} 12 13public struct Player_Status { 14 public int ID; // 番号 15 public string name; // 名前 16} 17 18public class Player_Data : MonoBehaviour { 19 Player player = new Player(); 20 21 public void Set_Parameter() { 22 Player_Status player_status; 23 for(int i = 0; i < 2; ++i) { // TODO: マジックナンバー 24 player_status.ID = int.Parse(player_data[i][0]); // 番号 25 player_status.name = player_data[i][1]; // 名前 26 27    player.players.Add(player_status); // ここでプレイヤーの持っているListに格納 28    }

###試したこと
newのタイミングを変えてみたがダメだった。調べてもクラスを分けて行っているところが見つからない。

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

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

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

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

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

guest

回答3

0

自己解決

Player_Dataのnew Player();がいらなかった

GameObjectがいるという前提を抜かして言いました。
どこの情報が大切なのかが分かっていなかったためのミスでした。

参考にさせていただく部分が多くあったので学ばせていただきます。

ありがとうございました。

投稿2017/12/26 08:12

gozi200

総合スコア6

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

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

0

PlayerのHPを変動させたいときに

あなたが書いたPlayerは型です。例えばintstring,int[]なども型です。
型に対してその型のデータ(実体、インスタンス)は複数存在できます。
複数存在できるということは、データを操作するときは、当然どのデータに対して操作するかを書く必要があります。
ですので、

class Battleでplayer.HPの値の計算は、Battle用に作られたPlayer playerのHPを計算するのであって、PlayerクラスのHPの値を変えているわけではないという事ですか?

その通りです。そもそも、あなたが考えているであろう「PlayerクラスのHP」というものはありません。

投稿2017/12/26 05:42

ozwk

総合スコア13512

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

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

gozi200

2017/12/26 06:22

ごめんなさい、HPは例で挙げさせていただきました。説明不足でした。 ですが、BeatStar様の返事に書いたコードではクラスの関数を呼び出してみると、Playerで呼んだ値しか変えてないのにクラスの値まで変わっています。 #include<iostream> class Player { public: int HP = 10; // Playerクラス内ではノータッチ void HP_Check() { std::cout << HP << std::endl; } }; void main() { Player player; player.HP = 20; // mainの持っているPlayer playerであってPlayerのHPではない? std::cout << player.HP << std::endl; player.HP_Check(); // mainのPlayer playerにしか値を入れていないのに、PlayerクラスのHPの値が変わっている system("pause"); }
ozwk

2017/12/26 07:38 編集

言い方が悪かったようですが、例だとかそういうの関係なく あなたの言う「クラスの値」(クラスが持っている値)というのは存在しません。 初心者によくある勘違いです。 class Player{...}であなたが書いているのは 「こういう内容のデータの実態があります。」ではなく 「こういう性質をもつデータの種類(型)があります。」です。 Player p1; Player p2; とかけばp1,p2がそれぞれ個別にHPを持っていますが、 Playerは、「この型のデータが作られたら、そいつはHPという名前のint型のデータを内包していて、初期値は10である」と定義しているだけです。
gozi200

2017/12/26 07:45

なるほど。 プレイヤーにステータスだけを設定してあるものを委譲させて、それをプレイヤーのステータスとして扱おうと思っています。 なのでプレイヤー自体は持っていなくても問題ないのかと思っていますがどうなのでしょう? 全部手探りなので書き方がおかしいのかもしれませんが、そうしているつもりです。 質問にも不慣れなもので必要な情報が少なく申し訳ございません。
ozwk

2017/12/26 08:00

> プレイヤーにステータスだけを設定してあるものを委譲させて、それをプレイヤーのステータスとして扱おうと思っています。 どういう意味ですか? > プレイヤー自体は持っていなくても * (何かが)プレイヤー自体は持っていなくても * プレイヤー自体は(ステータスを)持っていなくても どっちですか?
gozi200

2017/12/26 08:08

後者です
ozwk

2017/12/26 08:10

なぜプレイヤーとプレイヤーのステータスを分けたいんですか?
gozi200

2017/12/26 08:13

私の参考にしている本での書き方がそうであったため、そうするものだと思っています。
guest

0

C言語でいう構造体とかJavaとかでいうクラスのオブジェクトって、

基本的には staticじゃないから、同じクラスから生成していても、

Java

1 2public class Test{ 3 public method1(){ Test2 t = new Test2(); } 4 public method2(){ Test2 t = new Test2(); } 5} 6 7public Test2{ 8 ... 何らかのメンバ ( メソッドやフィールド ) 9} 10

だと method1と method2 にあるt は別物です。

int型のローカル変数と同じです。

これのクラスレベルじゃないかなと。

Player_Dataクラスを見ると Playerクラスをコンポジションしているけど、

これだと、例えば yusha( 勇者 ), wizard ( 魔法使い )... とあったとき、

yushaは yusha用の Player playerにアクセスします。

よって、全体のやつには反映されない。

クラスって"ある意味" 変数と一緒。

単なる型。

だから複数個作れますよね。

同じクラスから作れば(持っているデータも)共通しているなら、意味がない。

逆にめんどくさくなるし。

勇者用にYushaクラス, Wizardクラス...って少しでも違えばクラスを生成しないといけなくなる。


[返信1]

変数で考えてみてください。

Java

1int method1(){ 2 int a; 3  a = 100; 4} 5 6int method2(){ 7 int a; 8 a = 32; 9} 10

さて、上記の場合、int a はそれぞれ同じものでしょうか?

実際には method1はmethod1内にあるint aを, method2は method2内にある int aを参照します。

よって、別物になります。

これのオブジェクト版。

なので、例えばmainメソッド内で、

Java

1Player player1 = new Player( "player1" ); 2Player enemy1 = new Player( "ememy1" ); 3CharaManager manager = new CharaManager(); 4 5manager.add( palyer1 ); 6manager.add( enemy1 ); 7

みたいになると思う。

この一つのmanagerがListを持っていて、管理する...みたいな。

あと、基本的にオブジェクト指向の言語はフィールドはprivateです。

そうじゃないとC言語でいうグローバル変数と同じになってしまいますから。

で、そのアクセスはアクセサと呼ばれるget/setで。

C# なら プロパティって呼ばれるもの。

Listを持つのは一つに限定したほうがいいはず。

( 複数個あってもいいが、完全に独立しているから今回は不向き。 )


[ 返信2 ]

えーと、返信1 で挙がっているmanager をC++で書くと

C++

1class PlayerManager{ 2 public: 3 void add( Player *player ){ players.push_back( player ); } 4 ... // その他メンバ 5 private: 6 List<Player> players; 7};

みたいに持っていて、管理者として存在します。

別にこれはなくてもいいですが、あくまで考え方。

返信にある ( 20になった... ) のコードでは

main関数で player が生成されていますね。

このplayerオブジェクトが持つので player::x には 20が入っている。

が、これを別のクラスや関数でさらに生成して使用しても player自体がまったく違う物質になっていますから、もっているデータも違ってくる。

同じ"太郎"でも山田太郎と東京太郎では違いますよね。

それと同じです。

最初の質問では、流れを考えるといいと思います。

まず、

Playerのほうで生成するとしても、player_dataを生成 -> player_data::Set_Parameterで設定 -> ( Set_Parameterの呼び出し ) -> Player playerが生成される -> Set_Parameterが動く ...

という感じで考えると、( Player_Data の方の ) Player player とかがわかりにくくなる。

というか、なぜこういう風に複雑にしたのかが疑問。

( 私が馬鹿なだけかもしれないが。 )


[ 返信3 ]

例えば、上記のPlayerManager クラスがあるとして、

C++

1void func( PlayerManager *manager ){ 2 Player player; // プレイヤーを生成 ( 本来は引数が必要だと思うが、例なので省略 ) 3 manger->add( player ); 4} 5

みたいにしておけば、

C++

1// main関数内 2PlayerManager manager; // これも本当は引数が必要だろうけど、例なので省略。 3func( &manager );

みたいに管理者を渡せばOkだと思う。

オブジェクト指向だからって、複雑に捉えすぎると意味がわからなくなり、余計アレになる。

関係性をUMLとかで洗い出して考えてみては?

投稿2017/12/26 04:06

編集2017/12/28 02:21
BeatStar

総合スコア4958

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

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

gozi200

2017/12/26 05:16

値を触るところでListを作らなくてはいけないという事ですか? 根本から勘違いしているかもしれません。(私が) 例えばPlayerのHPを変動させたいときに例: class Battleでplayer.HPの値の計算は、Battle用に作られたPlayer playerのHPを計算するのであって、PlayerクラスのHPの値を変えているわけではないという事ですか? これが分かれば理解がしやすくなるのかなと感じます。
BeatStar

2017/12/26 05:25

ちょっと、本編? の方で追加しますね。
gozi200

2017/12/26 05:54

class Hoge { public: int x = 10; void hoge() { std::cout << x << std::endl; } }; void main() { Hoge hoge; hoge.x = 20; std::cout << hoge.x << std::endl; hoge.hoge(); system("pause"); } 実行結果はとに20でした。 mainで作成したmain用のhoge.xとHogeの持っているxは連動しているのですか? なのにListの内容が別物になってしまう違いがよくわからないです>< 書いてくださったmanagerはListですか? そうでないならAddできないですし、そうなのでしたら最初に私が試していたPlayerに入れるのとどう違うのでしょう? 記入漏れがありました。C++でしたらまだC#よりは分かるので良い例があるのでしたらC++で挙げていただけたら理解は早まるかもしれません
gozi200

2017/12/26 06:47

なるほど、クラス別で呼ぶとわかりやすかったのですね。 やはり複雑ですよねorz 一つのクラスで処理をまとめるのは設計上よくないと技術が足りていないのにも関わらず変に分けようとしているからですね… ManagerのListに格納したとしても、他所で使おうとするとまた値が違うのでつかえなくないですか? Managerで値をいじることが前提なのでしょうか
BeatStar

2017/12/28 02:15

そうですね。Managerで値をいじることが前提です。 が、main関数 ( Javaだとmainメソッドですが。 ) みたいに必ず呼ばれるものならいいですが、 普通の関数やメソッド等は呼び出さないと動きません。 よって、呼び出す必要がありますが、例えばmain関数内でmanagerを生成して、 managerに命令する関数やメソッド等 ( main関数以外 ) も生成すると別のものになるので 引数で渡します。 例は本体に記述しますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問