【Unity】リストを扱うときはforeachよりもLINQ使った方がシンプル。.Select(hoge=>fuga)みたいなやつ。【LINQ】

Unityで複数のゲームオブジェクトを配列で取得するときがあります。
例えば[GameObject.FindGameObjectsWithTag](https://docs.unity3d.com/ja/current/ScriptReference/GameObject.FindGameObjectsWithTag.html)を使ってGameObject型の配列で取ってきたり、[Physics.RaycastAll](https://docs.unity3d.com/ja/current/ScriptReference/Physics.RaycastAll.html)でRaycastHit型の配列で取ってきたり。
配列に何かしらの処理をする時は、forループやforeachループよりも一旦リストに変換してからLINQライブラリを使うと記述がシンプルになります。

#【環境】
・MacOS Catalina 10.15.7
・Unity versiton:2019.4.14f1

##各要素に戻り値のない処理をしたい→ForEach
例えばFindGameObjectsWithTagで取得したゲームオブジェクトたちの名前をコンソールに書き出したい時。

※Selectとの使い分けはこちらの記事を参考にさせていただきました。
　[LINQのそのForEach、実はSelectで書き換えられるかも](https://qiita.com/t_takahari/items/6dc72f48b1ebdfed93b7)

```c#:LinqTest.cs
using System.Collections.Generic;
using UnityEngine;

public class LinqTest : MonoBehaviour
{
    void Start()
    {
        //PlayerタグをつけたGameObjectを配列で取得しリストへ変換
        List<GameObject> gameObjects = GameObject.FindGameObjectsWithTag("Player").ToList();
        //取得したGameObjectの名前をコンソールに出力
        gameObjects.ForEach(gameObj => print(gameObj.transform.name));
    }
}
```

##各要素に戻り値のある処理をしたい→Select
例えばRaycastHit型で取得したゲームオブジェクトたちをGameObject型のリストに変更したい時。
Case2のまとめて記述する場合は、こちらの記事を参考にさせていただきました。
[【Unity】自キャラに一番近いオブジェクトを対象とするロックオン方式の実装](https://gomafrontier.com/unity/1810)

```c#:LinqTest.cs
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class LinqTest : MonoBehaviour
{
    void Start()
    {
        //Case1：段階に分けて記述する場合
        List<RaycastHit> hits1 = Physics.SphereCastAll(transform.position,10.0f,transform.forward,0.01f).;
        List<RaycastHit> hits1_RH_list = new List<RaycastHit>(hits1);
        List<GameObject> hits1_GO_list = hits1_RH_list.Select(h => h.transform.gameObject).ToList();

        //Case2：まとめて記述する場合
        var hits2 = Physics.SphereCastAll(transform.position,10.0f,transform.forward,0.01f)
        .Select(h => h.transform.gameObject).ToList();
    }
}
```


##各要素を条件に応じて絞り込みたい→Where
例えばSphereCastAllで取得したゲームオブジェクトの中で、特定の名前（"Player1"）のオブジェクトだけに絞りたい時。

```c#:LinqTest.cs
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class LinqTest : MonoBehaviour
{
    void Start()
    {
        var hits3 = Physics.SphereCastAll(transform.position, 10.0f, transform.forward, 0.01f)
       .Where(h => h.transform.gameObject.name == "Player1").ToList();
    }
}
```

##各要素を条件付きで絞り込んだ後に処理したい→WhereとSelectの組み合わせ
例えばSphereCastAllで取得したゲームオブジェクトの中で、特定の名前（"Player1"）のオブジェクトだけに絞り、その座標をリストで取得したい時。

```c#:LinqTest.cs
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class LinqTest : MonoBehaviour
{
    void Start()
    {
        var hits4 = Physics.SphereCastAll(transform.position, 10.0f, transform.forward, 0.01f)
        .Where(h => h.transform.gameObject.name == "Player1")
            .Select(h => h.transform.position).ToList();
    }
}
```

こちらの記事も参考にさせていただきました。
[【LINQのメソッド紹介その1】foreachメソッドの概要とコード例](https://www.fenet.jp/dotnet/column/language/1452/)
[【LINQのメソッド紹介その2】Selectの概要とコードの例](https://www.fenet.jp/dotnet/column/language/1454/)
[【LINQのメソッド紹介その3】Whereで条件に合うデータを取得する](https://www.fenet.jp/dotnet/column/language/1458/)