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

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

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

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

Unity

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

Q&A

解決済

2回答

1151閲覧

C# Unity 敵の撃破リストの検索が上手くいくようにしたい

Koma2000

総合スコア3

C#

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

Unity

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

0グッド

0クリップ

投稿2021/04/23 01:08

C# 複合型のリストを検索したい
・Unity にてゲームで使う敵の撃破リストを
・リストの中身「 Int・String・Int 」で構成
・リストは外部から読み取り可能・関数を使う場合のみ色々とリストの変更が可能
→ 他の質問の方から流用・アレンジさせてもらってます

C#

1 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6// リスト管理 クラス 7public class EnemyKillList : MonoBehaviour 8{ 9 // 外部から読み取り専用のリスト 10 // リスト内データの「更新・追加・削除」は専用の関数でなければアクセス出来ない 11 [SerializeField] 12 public static IReadOnlyList<IReadOnlyRecordData> Readlist => Recodlist; 13 14 // privateリスト <static>が付いているのは上の読み取り専用を<static>にする為 15 [SerializeField] 16 private static List<RecordData> Recodlist = new List<RecordData>(); 17 18 // リストデータ追加 関数 19 // 引数からリスト型 変換 20 // その後リスト 追加 21 public static void AddData(int OrderNumber, string EnemyName, int KillCount) 22 { 23 var rd = new RecordData(); 24 rd.OrderNumber = OrderNumber; 25 rd.EnemyName = EnemyName; 26 rd.KillCount = KillCount; 27 Recodlist.Add(rd); 28 } 29 30  /// 問題箇所A /// 31 // リスト内データ<撃破数>更新 関数 32 public static void UpdateData(int Number, string Name, int Count) 33 { 34 var Findlist = new RecordData { OrderNumber = Number, EnemyName = Name }; 35 var Updatelist = new RecordData { OrderNumber = Number, EnemyName = Name, KillCount = Count }; 36 37 // リスト内のデータ 検索 38 if (Recodlist.Contains(Findlist)) // ← ここのリスト内の検索方法が上手くいきません 39 { 40 // データがリストの何番目かを検索 変数に代入 41 int IndexNum = Recodlist.IndexOf(Findlist); 42 43 // データの撃破数を置き換える 44 Recodlist[IndexNum].KillCount = Updatelist.KillCount; 45 } 46 } 47 48  /// 問題箇所B /// 49 // リスト内データ削除 関数 50 public static void RemoveData(int Number, string Name, int Count) 51 { 52 var Removelist = new RecordData { OrderNumber = Number, EnemyName = Name, KillCount = Count }; 53 54 // リスト内に引数と同じデータがあれば削除 55 if (Recodlist.Contains()) 56 { 57 Recodlist.Remove(Removelist); 58 } 59 60 // 無い場合は処理終了 61 else 62 { 63 return; 64 } 65 } 66} 67 68// 読み取り専用インターフェイス クラス 69public interface IReadOnlyRecordData 70{ 71 int OrderNumber { get; } 72 string EnemyName { get; } 73 int KillCount { get; } 74} 75 76// リスト内部・読み取り専用 クラス 77public class RecordData : IReadOnlyRecordData 78{ 79 public int OrderNumber { get; set; } 80 public string EnemyName { get; set; } 81 public int KillCount { get; set; } 82} 83

問題点
・問題箇所のリスト内検索が上手くいかない
・問題箇所Aの部分では「OrderNumber・EnemyName」で検索をかけ該当するものがある際には「KillCount(撃破数)」を加算・上書きする
・問題箇所Bの部分では「OrderNumber・EnemyName・KillCount」で検索をかけ該当するものがある際にそのリストを削除する
・検索する型が間違っていると考えていますが未だ解決に至っていません

未だ未熟なのでコードに不備などあるかもしれませんかその際は適宜指摘してもらえるとありがたいです

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

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

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

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

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

ayousanz

2021/04/23 02:48

ちょっと記憶が確かではないのですが,classの入ったListを検索するときはいい感じにしないと一致系のメゾットがうまく動作しない気がします.一度for文で回してOrderNumberとEnemyNameがどちらとも一致している場合という風に書き換えて試してもらってもいいでしょうか? 仮にfor文ですべてif判定を行ってできるのであれば,classのFindあたりを修正したらAはうまくいくと思います.(Bも同様)
YAmaGNZ

2021/04/27 00:24

1570pさんの回答に対して「参考にしながら実装できました。ありがとうございます!」と返しておきながら「まだ回答を求めています」というのはどういうことなのでしょうか?
Koma2000

2021/04/27 03:52

すみません朝寝ぼけていたみたいです 押した記憶はなかったのですが... ご指摘ありがとうございます。
YAmaGNZ

2021/04/27 04:02

解決されたのであれば、ベストアンサーを決めてあげてはどうでしょうか。
guest

回答2

0

クラスインスタンス同士の等値比較は暗黙的に RefarenceEqual(参照に対する比較)として扱われるため、質問のRecodlist.Contains(Findlist) は常にfalseを返します。

等値比較をクラス内変数の等値性によるものにしたい場合は、RecordDataにIEquatable<T>を実装します。詳しくは以下のリンクをご参照ください。

IEquatableを完全に理解する
https://qiita.com/cactuaroid/items/f277a097ecf51eb247c0


追記 (2021/04/27)

参考コード書きました。リンク先のページ上部にあるRunを押すと実際に試せます。
https://dotnetfiddle.net/g0rAUT

投稿2021/04/23 08:46

編集2021/04/27 00:53
tor4kichi

総合スコア763

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

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

Koma2000

2021/04/23 22:21

ご回答ありがとうございます 回答頂いたものを実践したいと思います
Koma2000

2021/04/27 00:03

せっかく回答を頂いておいて申し訳ないですが リンク先の記事や自分でも調べてみても実装が出来ませんでした すみません
guest

0

ベストアンサー

検索がうまくいかないというFindListの部分はnewされて新しく作られたRecoadDataのインスタンスですので、当然RecodList内に存在しません。全く同じ値を持っているRecoadDataだとしてもそれは異なる存在です。

List内からNumberとNameが同じものを探したいというのなら、
手っ取り早くLinqを使用(using System.Linq;を追加)、

// RecodListの中からNumberとNameが同じ値のRecoadDataの最初に見つけた参照を得る、見つけられなければnull、同一の値があるようなListの場合、最初に見つけた物となるためこれもバグとなりえる
var data = RecodList.FirstOrDefault(_ => _.OrderNumber == Number && _.EnemyName == Name);

if (data != null) data.killCount = Count;
else // リスト内に存在しなかった場合の処理

みたいな感じか?

RecodList.Contains(~
として使いたい場合、
public static void UpdateData(RecoadData data)
として、RecoadDataそのものを引数とする?
RecodList.Contains(data)

他、Bの問題個所も上記と同じ理由でnewで生成したものと比較してもList内には存在しないため、常にfalseが返ってくる。

投稿2021/04/23 06:53

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Koma2000

2021/04/23 23:30

明確な問題点の解説ありがとうございます勉強になりました コメントを参考に試してみます
Koma2000

2021/04/27 00:00

参考にしながら実装できました ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問