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

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

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

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

Unity

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

Q&A

解決済

3回答

5775閲覧

Listの内容が共有されてしまう

Ans

総合スコア75

C#

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

Unity

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

2グッド

1クリップ

投稿2016/05/09 15:11

編集2016/05/10 05:10

アクションRPGを作っています
敵味方の状態異常を実装しようと思い
とりあえず状態異常の管理にListを使いました
(5回毒を与えたら5個の毒がバラバラにダメージを与えそれぞれの効果時間で各自消滅する
各々が完全に独立しているタイプです)

しかし複数同じ敵(=同じプレハブ=同じスクリプト)がいる場合
Listを共有してしまうためうまくいきません

状態異常のcrassの中身は今の所
効果回数と 効果間隔と 効果数値と 効果種類です。
5回まで 1秒ごとに 10ダメージの 毒 といった感じです

質問です

Listのstatic属性は外せますか?

全く別のスマートな実装方法はありますか?

今考えている代替案は
Listを使わず状態異常のコンポーネントを作っておき
状態異常を与えるたびにaddcomponentするというものですが
これはスマートですか?

回答お待ちしています
よろしくお願いします

act823, Chironian👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんにちは。

HiroshiWatanabeさんの回答へのコメントの使い方でしたら、staticにはなっていません。
もし、List<A>にAdd()したAのインスタンスが共有されているように見えるとしたら、同じインスタンスをAdd()している可能性があります。

例えば、敵の種類毎に毒(クラスA)のインスタンスを作っておいて、そのインスタンスをList<A>へAdd()していた場合、同じ種類の敵の毒について1つしかインスタンスが作られていないので、全て共有されてしまいます。
もし、そのような使い方をされているなら、AにClone()メソッドを実装し、Clone()したインスタンスをAdd()すればうまくいくはずです。

上記問題が原因でしたら、これはプロでもハマり一度ハマったら簡単には抜け出せない問題です。(解っていてもたいへんですが、知らなければ地獄を見ると思います。)
C#はポインタを使っていないように見えて、実は参照や参照型で使っています。値渡しと参照渡し値型と参照型について、良く理解しておくことをお勧めします。

投稿2016/05/10 03:06

Chironian

総合スコア23272

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

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

Ans

2016/05/10 05:22 編集

回答ありがとうございます なるほどズバリその通りでした(多分) はじめに void Aget(A a){ As.add (a);} のようにしていて壁にぶち当たりました 現在は void Aget(A doku){ As.add (new A (doku.tuyosa,doku.count,doku.interval ));} のようにしています(しかしこれがなぜなのかわからず。 理屈はわからんがこれなら通ることを知っているという感じでした) Chironianさんの回答を受けた 今の自分の理解は 3体の敵にA毒を1個ずつ送るには 3体の敵にそれぞれA毒Clone1 A毒Clone2 A毒Clone3を送る必要がある Cloneを作るメソッドの中身は上記で言う As.add (new A (doku.tuyosa,doku.count,doku.interval ) に相当する。(それをAというクラス内に作っとけとおっしゃっている?) 自分が勘違いしていたのは [1つのリストを共有(static)してしまう]ではなく [3つのリストで1つの毒を共有してしまう]ということ 以上理解はあっているでしょうか間違っていたらご指摘ください 確かに3体に毒を付与すると3倍速で毒が治り想定の3分の1しかダメージがでませんでした。(1つの毒を3体で消費し 3体で1つの毒のダメージを受けていた) またアイテムにランダムステータスを付与すると アイテムデータベースの値も変わってしまうなどなど同じような問題に度々悩まされていました Cはポインタが大変 C♯もポインタは実は出てくる 知っていましたし 午前中も「ほへーポインタ大変そうやね そのうち自分もぶつかるかね ゲームセーブデータ改変みたいなもんかね」 とか思ってました。まさにぶつかってたんですね 値渡しと参照渡しもなんやそれでしたが一気にいけそうです 勉強します 最近のもやもやがまとめて吹き飛んだ気がします(理解があってればですが) 自分の理解があっているかだけあと一度よろしくお願いします!
Chironian

2016/05/10 04:37

kzy419さん。 > 以上理解はあっているでしょうか間違っていたらご指摘ください それであってますよ。 C#の参照型はなかなか歯ごたえがありますが、そこまで分かっていれば、後は熟練です。 頑張って下さい。
Ans

2016/05/10 05:01

それはよかったです では解決としたいと思います 皆さんの反応のおかげでたどり着いたので ベストアンサーとか選びにくいのですがつけます Chironian さん HiroshiWatanabe さん tkow さん ありがとうございました 頑張ります。
guest

0

逆になぜstaticをつけているのかがわかりません。
同じprefabだろうが同じscriptだろうがそれぞれの敵毎に(staticをつけずに)Listを持たせればいいだけのように思えますが…?
もしかして単に特定の敵へのアクセス方法がわからずにstaticアクセスにしてしまっている的な事でしょうか?
対象のオブジェクト(GameObject)が特定できているのならそこから欲しいコンポーネント(スクリプト)をGetComponent等でゲットしてやれば後はそれにアクセスするだけですが…
prefabが同じでもそれを元にそれぞれ別のオブジェクトとして配置されているので別物ですしもちろん同じスクリプトでもコンポーネントとしてアタッチしているオブジェクトが別なのでスクリプトとしてもそれぞれ別物として個別に機能していますからそもそも今回のケースでstaticをつける事が誤りな状況のように読めます。

投稿2016/05/10 00:45

HiroshiWatanabe

総合スコア2160

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

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

Ans

2016/05/10 01:33 編集

回答ありがとうございます 敵へのアクセス方法はわかります 後半の部分も理解できますし全くもってその通りだと思います Listの使い方が根本的に間違っているのでしょうか あるいはstaticの理解が間違っているのかも public class enemystates : MonoBehaviour { List<A >As = new List<A>() ; int a ; float b ;//以下いろいろ } void hogehoge(){}//以下スクリプトが続く という指定の仕方なのですが このスクリプトが刺さっているオブジェクトでList Asは共有されてしまいます 自分でstaticをつけたつもりはないのですが 独立させる記述があるのでしょうか
guest

0

実装自体自由度が高いのでListを共有する方法でもできると思いますよ。
勿論クラス内の内部変数として定義すればstaticでリストを定義する必要もありません。
ただ,こういう実装する時って大体エネミークラスみたいな抽象クラスに状態異常typeをenumで持たせてて,このenumの値で,状態異常レベルみたいな変数を持たせてインデクサアクセス出来るようにしてメソッド経由でインクリメントしたりしますね。
それぞれのインスタンスに独立して持たせた方がプロセスを分離しやすいです。同期的に判定を行いたいなどの理由があればこの抽象クラスを継承したサブクラスのインスタンスをポリモーフィズムを利用して同じリストに入れて管理することも出来ます。

投稿2016/05/09 16:08

編集2016/05/09 16:11
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Ans

2016/05/10 01:33

回答ありがとうございます >>リストをstaticでリストを定義する必要もありません。 とのこですが「デフォルトでstaticで定義されてしまうよ〜」というのが自分の現状です 説明不足でした。 enumからインデクサも試してみます 共有する方法で考えた結果 とりあえず状態異常を受けたオブジェクトが リストに状態異常を追加する際そのオブジェクトの名前も記録するようにしました やりたいことはできたのですが Listに関する理解が間違っている?ようなのでもう少しご教授いただきたいです。 ポリモーフィズムはまだ手をつけていないので勉強します。
退会済みユーザー

退会済みユーザー

2016/05/10 04:10

Chironianさんが書かれているようにリストがstaticではなくインスタンスの参照コピーをリストに入れてしまってるんでしょうね。 参照型オブジェクトはコンストラクタ経由で複製しましょう。
Ans

2016/05/10 04:26

new というやつですよね ということはオブジェクトの名前も記録する云々はいらなかったということですね。 (同じ時にnewに置き換えていました) 自分がぶつかっている壁がなんなのかわかっていなかったということでした。 質問してよかったです ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問