###追記【2019/11/15】
@albireo 様にアドバイスしていただいたSortedList
の方が簡易的かつ無駄なく処理できたので
記事の末尾に追加しておきました。
#この記事の狙い
自分の経験を書き記すとともに、有識者の方々からアドバイスや説明をもらえたらいいなぁ。
という期待。
##あらすじ
Unityで画面内に映っているTargetを取得&自キャラとTargetの距離を取得できるようになったので、
これを「距離が近い順」で並べ替えたい!と思い、色々調べながら試してみることに。
#本題
まず「画面内に映っているTarget」と「Targetまでの距離」、この二つの情報を紐付けるには
どうすればいいのかを調べるところから始めた。
これは調べると直ぐに出てきた、最初はList<>か配列[ ]でなんとかするしかないのかな?とか考えていたが、
調べてみるとDictionary
という超便利なクラスがあるではないか。
早速、意気揚々と使ってみる。
Dictionary<GameObject,float> ProvisionalValue = new Dictionary<GameObject,float>();
ProvisionalValue.Add(hit,target_distance);
よし、これで情報の紐付けはできたな...!
後はこれを「距離が近い順」で並べ替えるだけだ...!
なんだ楽勝じゃん。勝ったな、風呂入ってくる。
#ここからが本当の地獄だ...!
さて、ちゃちゃっとSortして終わらせるか~
ProvisionalValue.Sort();
...あれ、できない。なになに?DictionaryにはSortの定義が含まれていない?
あら、そうなのか...。じゃあどうやって並び替えするんだろう、調べてみるか...。
ははーん、Linqを使えば出来るのね。試したことが無いけど、やってみるか...。
ここで訳の分からないことをし始める(多分色々調べているうちにいろんな記事の情報が入り混じった)
えーっと、まずはソートする基準がいるから(?)floatだけをList<>で取得してからこれをOrderByで
並べ替えて...、あれ?Valueが定義が含まれていない...?(Listだから)
これは何かがおかしい...!という感じで混迷を極めた結果、こうなった。
private static Dictionary<GameObject,float> hitsOB = new Dictionary<GameObject,float>();
private static Dictionary<GameObject,float> ProvisionalValue = new Dictionary<GameObject,float>();
{
ProvisionalValue.Add(hit,target_distance);
Sort(ProvisionalValue);
}
public static void Sort(Dictionary<GameObject,float> itemTable) //取得したオブジェクトと距離のデータを距離が近い順でソートするメソッド
{
IOrderedEnumerable<KeyValuePair<GameObject,float>> _table_1 =
itemTable.OrderBy(selector => selector.Value);
foreach(KeyValuePair<GameObject,float> pair in _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...順で並び替える為、
ソートの基準は距離で並び替えたかったので、順番を入れ替える必要がありました。
ということを踏まえた上で変更したものが以下の流れです。(距離の所得等は省いています)
private SortedList<float,GameObject> ProvisionalValue;
void Start()
{
ProvisionalValue = new SortedList<float,GameObject>();
}
public void Sort()
{
ProvisionalValue.Add(target_distance,hit);
foreach(var item in ProvisionalValue)
{
Debug.Log("Distance : " + item.Key + " / Object : " + item.Value);
}
}
これでコンソールに距離順で距離とオブジェクト名が表示されます。