前提・実現したいこと
投稿記事:【C#,Unity】Dictionary<GameObject,float>をfloat基準で昇順にSortしようとしたら謎処理を挟んでいた話
もともとQiitaの方でDictionaryを使ってSortをする際に苦戦したという話を投稿した際に、
コメントで読み取りの頻度が高いのであればSortedListの方が向いていますよ。というアドバイスをいただき、
変更したのですが、後日、SortedListは同じKeyの値が登録された場合、追加ではなく上書きされるので防止したほうがいいですよ、
(Unityで試しに同じ値を追加しようとしたらArgumentエラーが発生しました)
とアドバイスと頂き、コードを提示までした頂いたのですが、まるで理解が及ばず困惑しています。
実際に現在使用しているスクリプトが以下のスクリプトになります。
cs
1using System.Collections.Generic; 2using UnityEngine; 3using System.Linq; 4 5public class LockOnTargetDetector : MonoBehaviour 6{ 7 public GameObject player; 8 public List<GameObject> hitsOb {get; set;} 9 private SortedList<float,GameObject> SortList; 10 11 void Start() 12 { 13 if(player == null) 14 { 15 player = GameObject.FindGameObjectWithTag("Player"); 16 } 17 SortList = new SortedList<float,GameObject>(); 18 hitsOb = new List<GameObject>(); 19 } 20 21 public void GetTargetClosestScreenCenter() 22 { 23 float search_radius = 10f; 24 25 var hits = Physics.SphereCastAll( //playerを中心に半径10fの半球内にあるTargetを取得 26 player.transform.position, 27 search_radius, 28 player.transform.forward, 29 0.01f, 30 LayerMask.GetMask("Target") 31 ).Select(h => h.transform.gameObject).ToList(); 32 33 hits = FilterTargetObject(hits); 34 35 if (0 < hits.Count()) { 36 37 foreach (var hit in hits) { 38 39 Vector3 targetScreenPoint = hit.transform.position; //各Targetの位置を取得 40 float target_distance = Vector2.Distance( //playerの位置から各Targetまでの距離を取得 41 player.transform.position, targetScreenPoint ); 42 43 SortList.Add(target_distance,hit); //各Targetと距離を格納 44 } 45 46 foreach(var item in SortList) //Sortしなくとも自動で昇順に並び替えて出力してくれる 47 { 48 hitsOb.Add(item.Value); 49 } 50 SortList = new SortedList<float,GameObject>(); 51 52 } else { 53 SortList = new SortedList<float,GameObject>(); //何もなかった場合リストを初期化 54 hitsOb = null; //何もなかったらNullを返す 55 } 56 } 57 protected List<GameObject> FilterTargetObject(List<GameObject> hits) //Physics.SphereCastAllでゲットしたTargetが画面内に入っているか判定 58 { 59 return hits 60 .Where(h => { 61 Vector3 screenPoint = Camera.main.WorldToViewportPoint(h.transform.position); 62 return screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1; 63 }) 64 .ToList(); 65 } 66}
処理内容的には、画面内のTargetオブジェクトをプレイヤーに近い順に取得する。となっています。
ここに提示していただいたコードを追加しようとしたのですが、記事の方にも書いてあるように
各値に何を渡してあげればいいのか、どこに記述して処理を実行すればいいのか、まるでわかりません。
そこで教えていただきたいのは、提示していただいたコードの各値に上記のスクリプトのどの値を渡せばいいのか、
提示していただいたコード1と2の関係性はどうなっているのか?
そもそもこの中に組み込むことが出来ないのか?等の知識を教えてください。
理解が及ばないため、どうか皆様のお力をお借りできれば幸いです。
提示していただいたコード
1
1.cs
1class MultiSortedList : SortedList<float, List<GameObject>> 2{ 3 //Addメソッドのオーバーロード 4 public void Add(GameObject obj) { 5 float distance = obj.距離計算メソッド(); 6 if (this.TryGetValue(distance, out insertTarget)) { 7 //すでに同じ距離の登録済みオブジェクトあり 8 insertTarget.Add(obj); 9 } else { 10 //同じ距離のオブジェクトなし 11 this.Add(distance, new List<GameObject> { obj }; 12 } 13 } 14 15 //ソート済みリストを一次元リストに展開して取り出す 16 IEnumerable<GameObject> GetSotedObjects() { 17 return this.Values.SelectMany(elems => elems); 18 } 19}
2
cs
1//本当は「距離でソートしたリストを作成」と「リスト順に処理を実行」は別メソッドに分けた方がいいと思う 2public void Sort() { 3 var list = new MultiSortedList(); 4 //ソートしたいオブジェクトを全部登録 5 foreach(var obj in itemTable.Where(ここにフィルタ条件を記述)) { 6 float distance = objから距離を算出; 7 list.Add(dicstance, obj);//距離もパラメータとして渡すことにします。メソッドの実装はわざわざコードを書かなくてもわかるんじゃないかと思います。 8 } 9 10 //距離順に個別処理を実行 11 foreach(var obj in list.Values) {//個別処理には距離情報が不要な場合 12 //個別処理 13 } 14}
試したこと
分からないなりに無理やり突っ込んでみましたが、結局どの値をどこに渡せばいいかわからず実装できませんでした。
回答2件
あなたの回答
tips
プレビュー