追記【2019/11/15】
@albireo様にアドバイスしていただいたSortedList
の方が簡易的かつ無駄なく処理できたので
記事の末尾に追加しておきました。
この記事の狙い
自分の経験を書き記すとともに、有識者の方々からアドバイスや説明をもらえたらいいなぁ。
という期待。
あらすじ
Unityで画面内に映っているTargetを取得&自キャラとTargetの距離を取得できるようになったので、
これを「距離が近い順」で並べ替えたい!と思い、色々調べながら試してみることに。
本題
まず「画面内に映っているTarget」と「Targetまでの距離」、この二つの情報を紐付けるには
どうすればいいのかを調べるところから始めた。
これは調べると直ぐに出てきた、最初はList<>か配列[ ]でなんとかするしかないのかな?とか考えていたが、
調べてみるとDictionary
という超便利なクラスがあるではないか。
早速、意気揚々と使ってみる。
Dictionary<GameObject,float>ProvisionalValue=newDictionary<GameObject,float>();ProvisionalValue.Add(hit,target_distance);
よし、これで情報の紐付けはできたな...!
後はこれを「距離が近い順」で並べ替えるだけだ...!
なんだ楽勝じゃん。勝ったな、風呂入ってくる。
ここからが本当の地獄だ...!
さて、ちゃちゃっとSortして終わらせるか~
ProvisionalValue.Sort();
...あれ、できない。なになに?DictionaryにはSortの定義が含まれていない?
あら、そうなのか...。じゃあどうやって並び替えするんだろう、調べてみるか...。
ははーん、Linqを使えば出来るのね。試したことが無いけど、やってみるか...。
ここで訳の分からないことをし始める(多分色々調べているうちにいろんな記事の情報が入り混じった)
えーっと、まずはソートする基準がいるから(?)floatだけをList<>で取得してからこれをOrderByで
並べ替えて...、あれ?Valueが定義が含まれていない...?(Listだから)
これは何かがおかしい...!という感じで混迷を極めた結果、こうなった。
privatestaticDictionary<GameObject,float>hitsOB=newDictionary<GameObject,float>();privatestaticDictionary<GameObject,float>ProvisionalValue=newDictionary<GameObject,float>();{ProvisionalValue.Add(hit,target_distance);Sort(ProvisionalValue);}publicstaticvoidSort(Dictionary<GameObject,float>itemTable)//取得したオブジェクトと距離のデータを距離が近い順でソートするメソッド{IOrderedEnumerable<KeyValuePair<GameObject,float>>_table_1=itemTable.OrderBy(selector=>selector.Value);foreach(KeyValuePair<GameObject,float>pairin_table_1){hitsOB.Add(pair.Key,pair.Value);}}
改めて見ると何やってるんだか、と思いました。
ProvisionalValueに格納したデータをOrderByで並べ替えて、並べ替えたデータを_table_1に格納して、
foreachでpairに一つずつ格納してhitsOBに順に格納....
いや、これ普通にProvisionalValueをOrderByでソートすればいいじゃん。
はい、というわけでそうした結果がこちら。
ProvisionalValue.Add(hit,target_distance);ProvisionalValue.OrderBy(x=>x.Value);
二行で終了。(なぜ俺はあんなムダな時間を...)
ふりかえり
そもそも混乱した理由は「よく理解していなかったから」につきます。
Dictionaryの値の取得方法すら理解していなかったが為に、KeyとValueがなんなのか分からずに使っていた
結果、今回のような無駄な時間を浪費する羽目になりました...。
まさしく「知識は身を助ける」を身をもって実感しました。
追加記事【SortedList】
先に紹介したDictionaryクラスは値を格納した後にOrderByでソートしていましたが、
SortedListクラスを使用すればわざわざソートする必要がなくなります。
しかし、注意しなければいけない点があります。
それはSortedList <TKey,TValue>
では、キー(TKey)
の値を基準にソートされます。
今回の例で行くと、先の紹介したDictionaryはDictionary<GameObject,float>
としていましたが、
これだとTKeyの値に代入しているGameObjectのソート基準はNameの頭文字をABCD...順で並び替える為、
ソートの基準は距離で並び替えたかったので、順番を入れ替える必要がありました。
ということを踏まえた上で変更したものが以下の流れです。(距離の所得等は省いています)
privateSortedList<float,GameObject>ProvisionalValue;voidStart(){ProvisionalValue=newSortedList<float,GameObject>();}publicvoidSort(){ProvisionalValue.Add(target_distance,hit);foreach(variteminProvisionalValue){Debug.Log("Distance : "+item.Key+" / Object : "+item.Value);}}
これでコンソールに距離順で距離とオブジェクト名が表示されます。