unityでのlinq活用例

148
UnityでのLINQ活用例 室星亮太 2015/02/20()

Upload: ryota-murohoshi

Post on 22-Jul-2015

2.753 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: UnityでのLINQ活用例

UnityでのLINQ活用例室星亮太

2015/02/20(金)

Page 2: UnityでのLINQ活用例

質問です

Page 3: UnityでのLINQ活用例

Unityでゲームを作成している方?

Page 4: UnityでのLINQ活用例

LINQ知っている方?

Page 5: UnityでのLINQ活用例

LINQ使っている方?

Page 6: UnityでのLINQ活用例

LINQがっつり使っている方?

Page 7: UnityでのLINQ活用例

ありがとうございました

Page 8: UnityでのLINQ活用例

UnityでのLINQの活用事例を通し、LINQの良さや利用方法を紹介します。

Page 9: UnityでのLINQ活用例

今日の目標みなさんに• LINQを使うとコードが読みやすくなることを知ってもらう

• LINQを活用できるシーンが多いことを知ってもらう

• LINQを使ってみよう・勉強してみようと思ってもらう

• LINQにこんな便利なメソッドあったんだと知ってもらう

Page 10: UnityでのLINQ活用例

Unityでの例を通して!

Page 11: UnityでのLINQ活用例

ところで

Page 12: UnityでのLINQ活用例

ゲーム開発で大切なものたくさんありますよね

Page 13: UnityでのLINQ活用例

その中のひとつ

Page 14: UnityでのLINQ活用例

簡潔で読みやすいコード

Page 15: UnityでのLINQ活用例

なぜかって?動けば同じじゃないかって?

Page 16: UnityでのLINQ活用例

仕様、変わりますよね?リリース後もアプデしますよね?

Page 17: UnityでのLINQ活用例

「汚いコードでとりあえず動く物」短期的には早いかもしれない

×"短期的な開発速度◯!中・長期的な開発速度

Page 18: UnityでのLINQ活用例

仕様は開発途中で変わりますよね?簡潔で読みやすく奇麗なコードこれに比べて汚く長いコードの仕様変更はとても大変!

Page 19: UnityでのLINQ活用例

遊びながら試行錯誤し面白い物を作るそれには簡潔で読み安いコードが必要!あと汚く長いコード、まじアプデしんどい!

Page 20: UnityでのLINQ活用例

読みやすいコードは大切賛成していただけますか?

Page 21: UnityでのLINQ活用例

ところで今日のテーマはLINQです

Page 22: UnityでのLINQ活用例

LINQを使うと、リストなどのコレクションを扱うコードが、

簡潔に読みやすくなりますよ!

Page 23: UnityでのLINQ活用例

さて、LINQとは

Page 24: UnityでのLINQ活用例

LINQとは統合言語クエリ!(LINQ)!は、強力なクエリ機能を!C#!言語および!Visual!Basic!言語の構文へと拡張する、Visual!Studio!2008!で導入

された機能のセットです。!

MSDN%LINQよりh*ps://msdn.microso7.com/ja:jp/library/bb397926.aspx

Page 25: UnityでのLINQ活用例

イメージわきます?

Page 26: UnityでのLINQ活用例

配列とかリストとかディクショナリとか

シーケンス(↑のようなオブジェの集まり)を

を扱うコードがLINQを使うと綺麗に書ける

ってことだけとりあえず今はイメージしてください(適当ですいません)

今日お話しするのは、LINQ%to%Objectsです

今日の話で「LINQが使えるようになる」とはなりません。みなさんに便利さを紹介しようと思います。

Page 27: UnityでのLINQ活用例

自己紹介• 名前:室星亮太

• 所属:Fuller,)Inc.

• 仕事:Unityを用いたゲーム開発

• 投稿先:h3p://qiita.com/RyotaMurohoshi

• Twi3er:@RyotaMurohoshi

• コミュニティ:Androidの会Unity部

Page 28: UnityでのLINQ活用例

ライブラリUniLinq作ったりUniBookでLINQについて書いたり

Page 29: UnityでのLINQ活用例

LINQ大好きです!「LINQのないC#なんてC#じゃない」

って言う方もいますが、私もそう思います!

Page 30: UnityでのLINQ活用例

そんな私がこういう風に使える、こんな状況で使えるという例をガンガン紹介していきます

Page 31: UnityでのLINQ活用例

第一部

今すぐに使って欲しいメソッド3選

Count・All・Any

Page 32: UnityでのLINQ活用例

こんなクラスがあってpublic class Monster{ public int Id { get; set; } public string Name { get; set; } public int Hp { get; set; } /* 中略 */}

Page 33: UnityでのLINQ活用例

List<Monster>の中でHpが0以下の要素を数える

のようなリスト内の指定の条件を満たした要素を数える

ってことやりません?

Page 34: UnityでのLINQ活用例

Count特定の条件を満たした要素を数える

Page 35: UnityでのLINQ活用例

Hpが0以下の要素、つまり死んでいるモンスター(Monster)の数を数えたい

Page 36: UnityでのLINQ活用例

よくあるforeach、ifのコードList<Monster> monsterList = LoadMonsterList ();

// LINQを使わないとint deadMonsterCount = 0;foreach (Monster monster in monsterList) { if(monster.Hp <= 0) { deadMonsterCount++; }}

Page 37: UnityでのLINQ活用例

Count指定の条件を満たした要素を数える

List<Monster> monsterList = LoadMonsterList ();

// Hpが0以下の要素の数にint deadMonsterCount = monsterList.Count ((Monster monster) => monster.Hp <= 0);

Page 38: UnityでのLINQ活用例

さっきの2つのコードどう読めます?

Page 39: UnityでのLINQ活用例

このコード、どう読みます?List<Monster> monsterList = LoadMonsterList ();

// LINQを使わないとint deadMonsterCount = 0;foreach (Monster monster in monsterList) { if(monster.Hp <= 0) { deadMonsterCount++; }}

Page 40: UnityでのLINQ活用例

int型のdeadMonsterCountを0で初期化

foreach文でmonsterListをまわす

もし要素のmonsterのHpが0以下ならば

deadMonsterCountをインクリメント

Page 41: UnityでのLINQ活用例

あ、つまり!

HPが0以下のモンスターを数えるのか!

という1回頭の中での変換が必要

Page 42: UnityでのLINQ活用例

一方LINQは?どう読みます?// LINQを使うとList<Monster> monsterList = LoadMonsterList ();

// Hpが0以下の要素の数にint deadMonsterCount = monsterList.Count ((Monster monster) => monster.Hp <= 0);

Page 43: UnityでのLINQ活用例

int型のdeadMonsterCountを次の値で初期化

monsterList内の次の条件を満たす要素数だ!

条件は要素のHPが0以下だ!

Page 44: UnityでのLINQ活用例

ほぼ意味的に、「Hpが0以下のモンスターを数えろ!」

左から右に素直に読める!

Page 45: UnityでのLINQ活用例

foreach文、if文のは「どう処理しているか」が書かれている

LINQでは「何がしたいか」が書かれている

Page 46: UnityでのLINQ活用例

だからLINQのコードは読みやすいしかも簡潔

Page 47: UnityでのLINQ活用例

ここからは基本、LINQ版のみでさくさく行きます

Page 48: UnityでのLINQ活用例

Any特定の条件を満たす要素が存在するか調べる

Page 49: UnityでのLINQ活用例

Any特定の条件を満たす要素が存在するか調べる

List<Monster> monsterList = LoadMonsterList ();

// Hpが0以下のモンスターが存在すればtruebool isExistDeadMonster = monsterList.Any((Monster monster) => monster.Hp <= 0);

Page 50: UnityでのLINQ活用例

All全ての要素が指定の条件を

満たすか調べる

Page 51: UnityでのLINQ活用例

All全ての要素が指定の条件を満たすか調べる

List<Monster> monsterList = LoadMonsterList ();

// 全てのモンスターのHpが0以下ならばtruebool isAllMonsterDead = monsterList.All((Monster monster) => monster.Hp <= 0);

Page 52: UnityでのLINQ活用例

次はUnityっぽいのでかつ

割とマイナーなやつを

Page 53: UnityでのLINQ活用例

第二部

Editor拡張でも活躍

OfType

Page 54: UnityでのLINQ活用例

OfType指定の型の要素のみにフィルタリングし、

指定の型のシーケンスに変換

Page 55: UnityでのLINQ活用例

Projectウィンドウ中で選択中の物の中で、テクスチャ(Textureクラス)のみを処理する

(UnityEditor拡張)

Page 56: UnityでのLINQ活用例

• UnityEditor.Selec0onクラスのobjectsプロパティを利用

• Selec0on.objectsは現在選択しているものを取得

• 型はUnityEngine.Object[]で取得

• これには当然テクスチャ(Textureクラス)以外のものも含まれる

• けどTextureのみを対象にしたい

Page 57: UnityでのLINQ活用例

フィルタリングといえばWhereこれをis演算子とあわせて

foreach (UnityEngine.Object target in Selection.objects.Where (o => o is Texture)){

// キャストする or as演算子利用がめんどい Texture texture = target as Texture;

// ここでTextureに何かしらの処理}

Page 58: UnityでのLINQ活用例

Castメソッドでキャストもできますがforeach (Texture texture in Selection.objects .Where (o => o is Texture) .Cast<Texture>()){ // ここでTextureに何かしらの処理}

Page 59: UnityでのLINQ活用例

そこでOfTypeですよ!

Page 60: UnityでのLINQ活用例

OfType指定の型の要素のみにフィルタリングし、指定の型のシーケンスに変換

// Selection.objectsの中の要素をTexture型のみにフィルタリングし、// IEnumerable<Texture>に変換foreach (Texture texture in Selection.objects.OfType<Texture> ()){ // ここでTextureに何かしらの処理}

Page 61: UnityでのLINQ活用例

UnityのEditor拡張で、Selec.onは利用シーンが多い!

(MenuItemと合わせて導入が楽!)

「Selec%on.objects.OfType<Texture>7()」、ぜひ!

実際に使った例がこちら!!h#p://qiita.com/RyotaMurohoshi/items/b01e3cdb91fea96f4574

Page 62: UnityでのLINQ活用例

OfTypeメソッド

他ではNUnitLiteというライブラリを使った際

System.Objectから特定の型への変換でも使いました

Page 63: UnityでのLINQ活用例

Editor拡張でのLINQ活用LINQ、実はiOSで問題があります

けれどUnityEditor内であれば大丈夫!

Editor拡張から利用し始めるのはオススメ!

Page 64: UnityでのLINQ活用例

第三部

指定の条件を満たす先頭の要素を取得する

First、FirstOrDefault

Page 65: UnityでのLINQ活用例

List<Monster>の中でHpが0以下の要素が一つ欲しい

のようなリスト内の指定の条件を満たす要素を一つ取得する

ってことやりません?

Page 66: UnityでのLINQ活用例

First指定の条件を満たす先頭の要素を取得する条件を満たした要素がない場合は例外発生

Page 67: UnityでのLINQ活用例

First指定の条件を満たす先頭の要素を取得する。条件を満たした要素がない場合は例外発生

List<Monster> monsterList = LoadMonsterList ();

// ひとつもHpが0以下の要素が存在しないなら例外発生Monster deadMonster = monsterList .First ((Monster monster) => monster.Hp <= 0);

Page 68: UnityでのLINQ活用例

Firstメソッドは

条件を満たす要素がない場合例外が発生!

じゃあ例外を発生たくない場合?

Anyで存在チェックしてあった場合のみ、もしくは...

Page 69: UnityでのLINQ活用例

FirstOrDefault指定の条件を満たす先頭の要素を取得する条件を満たした要素がない場合は

その型の規定値を返す

Page 70: UnityでのLINQ活用例

条件を満たした要素がない場合、

「規定値を返す=nullを返す」じゃない!

ここ要注意!値型の規定値はnullじゃない!

Page 71: UnityでのLINQ活用例

規定値• クラス型の場合、null

• intの場合、0

• floatの場合、0.0F

• boolの場合、false

• Vector3の場合、x、y、zが全て0.0F

Page 72: UnityでのLINQ活用例

FirstOrDefault指定の条件を満たす先頭の要素を取得する。条件を満たした要素がない場合はその型の規定値を返す

List<Monster> monsterList = LoadMonsterList ();

// ひとつもHpが0以下の要素が存在しないならMonsterクラスの規定値nullにMonster deadMonster = monsterList .FirstOrDefault ((Monster monster) => monster.Hp <= 0);

Page 73: UnityでのLINQ活用例

ここでさらにもう一つ!

Page 74: UnityでのLINQ活用例

DefaultIfEmptyシーケンスが空ならば引数で渡したものを唯一の要素とするシーケンスに変換

Page 75: UnityでのLINQ活用例

Firstと組み合わせてこんなことができる

Page 76: UnityでのLINQ活用例

DefaultIfEmptyシーケンスが空ならば引数で渡したものを唯一の要素とするシーケンスに変換

List<Monster> monsterList = LoadMonsterList ();Monster defaultMonster = GetDefaultMonster ();int targetId = GetTargetId ();

// 指定IDのモンスターを探す。なかったらdefaultMonsterに。Monster targetMonster = monsterList .Where ((Monster monster) => monster.Id == targetId) .DefaultIfEmpty (defaultMonster) .First (); // このオーバーロードは単純に先頭要素取得

Page 77: UnityでのLINQ活用例

ところで

Page 78: UnityでのLINQ活用例

デリゲートとラムダ式• 「(Monster*monster)*=>*monster.Hp*<=*0」はラムダ式

• 「ラムダ式」ではなく「デリゲート」を引数にとる

• LINQの多くのメソッドがFunc<T,*TResult>を取る

• ラムダ式の用途の一つはデリゲートの生成

詳しくは! h"p://qiita.com/RyotaMurohoshi/items/740151bd772889cf07de にまとめました

Page 79: UnityでのLINQ活用例

第四部

算術計算系

Max、Min、Sum、Average

Page 80: UnityでのLINQ活用例

こんなクラスを使いますpublic class PlayLog{ public int StageId { get; set; } public int Score { get; set; } public DateTime PlayedAt { get; set; } public TimeSpan PlayTime { get; set; }}

Page 81: UnityでのLINQ活用例

List<PlayLog>の要素の中で一番大きいScoreを求める

のようなリスト内要素を変換して、その一番大きい値を求める

ってことやりません?

Page 82: UnityでのLINQ活用例

Max各要素に変換を施しその最大値を計算する

Page 83: UnityでのLINQ活用例

Max各要素に変換を施しその最大値を計算する

List<PlayLog> playLogList = LoadPlayLogList ();

// PlayLogListのScoreの最大値int maxScore = playLogList.Max ((PlayLog playLog) => playLog.Score);

Page 84: UnityでのLINQ活用例

Min各要素に変換を施しその最小値を計算する

Page 85: UnityでのLINQ活用例

Min各要素に変換を施しその最小値を計算する

List<PlayLog> playLogList = LoadPlayLogList ();

// PlayLogListのScoreの最小値int minScore = playLogList.Min ((PlayLog playLog) => playLog.Score);

Page 86: UnityでのLINQ活用例

Sum各要素に変換を施しその合計値を計算する

Page 87: UnityでのLINQ活用例

Sum各要素に変換を施しその合計値を計算する

List<PlayLog> playLogList = LoadPlayLogList ();

// PlayLogListのScoreの合計値int sumOfScore = playLogList.Sum ((PlayLog playLog) => playLog.Score);

Page 88: UnityでのLINQ活用例

Average各要素に変換を施しその平均値を計算する

Page 89: UnityでのLINQ活用例

Average各要素に変換を施しその平均値を計算する

List<PlayLog> playLogList = LoadPlayLogList ();

// PlayLogListのScoreの平均値double averageOfScore = playLogList.Average ((PlayLog playLog) => playLog.Score);

Page 90: UnityでのLINQ活用例

ところで

Page 91: UnityでのLINQ活用例

LINQとiOS(1)• Unity+iOSだと実機実行時エラーになることがある

• 理由はAOTコンパイルがうまくいっていないみたい

• それを解決するためにUniLinqっていうやつを作った

Page 92: UnityでのLINQ活用例

LINQとiOS(2)• IL2CPP登場

• IL2CPPで大丈夫か試したら、テストするやつが実機でエラーに

• AssemblyクラスのCodePathプロパティがnullなのが原因

• 今後も正しく動くかどうかなど、継続して調べていきます!

Page 93: UnityでのLINQ活用例

第五部

並び替え

OrderBy、OrderByDescending

ThenBy、ThenByDescending

Page 94: UnityでのLINQ活用例

List<PlayLog>をScroreの降順で並び変える

のような整列操作

ってやりません?

Page 95: UnityでのLINQ活用例

OrderBy各要素に変換を施しその結果で並び替え

Page 96: UnityでのLINQ活用例

OrderBy各要素に変換を施しその結果で並び替え

List<PlayLog> playLogList = LoadPlayLogList ();

// スコアの降順で並び替えIEnumerable<PlayLog> orderedPlayLog = playLogList .OrderByDescending ((PlayLog playLog) => playLog.Score);

OrderByは昇順で並び替え、OrderByDescendingは降順で並び替え

元のデータを並び変えるのでなく、新たに並び替えたシーケンスをつくる

Page 97: UnityでのLINQ活用例

もし同じScoreならどうしよう?

同ScoreならばPlayTimeが短い順にしたい場合は?

Page 98: UnityでのLINQ活用例

もう一度OrderByを呼ぶのは間違い!

Page 99: UnityでのLINQ活用例

ThenByOrderByで並び替えたもので、同評価だったものを並び替え

Page 100: UnityでのLINQ活用例

ThenByOrderByで並び替えたもので、同評価だったものを並び替え

List<PlayLog> playLogList = LoadPlayLogList ();

// スコアの降順で並び替えて、同点なら時間が短い方を先にIEnumerable<PlayLog> orderedPlayLog = playLogList .OrderByDescending ((PlayLog playLog) => playLog.Score) .ThenBy ((PlayLog playLog) => playLog.PlayTime);

Page 101: UnityでのLINQ活用例

第六部

スキップと取得

Skip、Take、SkipWhile、TakeWhile

Page 102: UnityでのLINQ活用例

データを画面に10個ずつ表示

インデックス0の1ページ目、0番目から9番目

インデックス1の2ページ目、10番目から19番目

インデックス2の3ページ目、20番目から29番目

ってことやりません

Page 103: UnityでのLINQ活用例

Skip%+%Take

Page 104: UnityでのLINQ活用例

Skip先頭から引数で渡した個数だけ

要素を飛ばす

Page 105: UnityでのLINQ活用例

Take先頭から引数で渡した個数だけ

要素を返す

Page 106: UnityでのLINQ活用例

Skip+Takeデータを画面に10個ずつ表示、今回は3ページ目(インデックスは2)

List<PlayLog> playLogList = LoadPlayLogList ();

int numPerPage = 10;int pageIndex = 2;int skipNum = numPerPage * pageIndex;

// 3ページ目(インデックスは2)、20番から10個の要素を取得IEnumerable<PlayLog> selectedPlayLogs = playLogList .Skip (skipNum) .Take (numPerPage);

Page 107: UnityでのLINQ活用例

今、DateTime型のPlayedAtの昇順でPlayLogが並んでいる

ある時刻から、他のある時刻までのデータを取得したい

Page 108: UnityでのLINQ活用例

SkipWhile)+)TakeWhile

Page 109: UnityでのLINQ活用例

SkipWhile先頭から引数で渡した条件が真の間

要素を飛ばす

Page 110: UnityでのLINQ活用例

TakeWhile先頭から引数で渡した条件が真の間

要素を返す

Page 111: UnityでのLINQ活用例

SkipWhile)+)TakeWhileList<PlayLog> playLogList = LoadPlayLogList ();

DateTime start = GetStartTime ();DateTime end = GetEndTime ();

// PlayedAtがstartより後or同時刻で、endより前な要素を取得IEnumerable<PlayLog> selectedPlayLogs = playLogList

.SkipWhile ((PlayLog playLog) => playLog.PlayedAt < start) .TakeWhile ((PlayLog playLog) => playLog.PlayedAt < end);

Page 112: UnityでのLINQ活用例

第七部

その他オススメ

Page 113: UnityでのLINQ活用例

ElementAtシーケンス中の

指定のインデックスの要素を取得

Page 114: UnityでのLINQ活用例

⚪番インデックスの要素が欲しいこういう時、ありますよね。どうします?

あまり書かないかもしれないけど、リファクタリングの途中で必要なこともある?

Page 115: UnityでのLINQ活用例

多くのLINQメソッドの返値型である、IEnumerable<T>型は

インデクサで要素にアクセスできない!

Page 116: UnityでのLINQ活用例

ToArrayはダメ絶対!// ToArrayで配列にしてからアクセス?// 効率悪い!!!// playLogsはIEnumerable<PlayLog>型PlayLog index5PlayLog = playLogs.ToArray ()[5];

Page 117: UnityでのLINQ活用例

ElementAt

// インデクサはないけれど// ElementAtメソッドでインデックスにアクセスできるPlayLog index5PlayLog = playLogs.ElementAt (5);

Page 118: UnityでのLINQ活用例

ToDic&onaryシーケンスから辞書を作る

キーを指定する。バリューも指定できる。

Page 119: UnityでのLINQ活用例

こんなクラスを使いますpublic class Item{ public int Id { get; set; } public string Name { get; set; } public ItemType ItemType { get; set; }}

public enum ItemType{ Weapon, ConsumptionItem, ValuableItem}

Page 120: UnityでのLINQ活用例

List<Item>*からItemのIdをキーとする

Dic$onary<int,-Item>をつくる

みたいなことしたくありません?

それLINQで一行でかけます!

Page 121: UnityでのLINQ活用例

ToDic&onaryシーケンスから辞書を作る!(その1)

List<Item> itemList = LoadItemList ();

// Idプロパティをキーとするディクショナリの生成// もしキーの重複があったら例外が発生Dictionary<int, Item> itemDict = itemList .ToDictionary((Item item) => item.Id);

Page 122: UnityでのLINQ活用例

ToDic&onaryシーケンスから辞書を作る!(その2)

List<Item> itemList = LoadItemList ();

// Idプロパティをキー、Nameプロパティバリューとする// ディクショナリの生成// もしキーの重複があったら例外が発生Dictionary<int, string> itemDict = itemList.ToDictionary( (Item item) => item.Id, (Item item) => item.Name);

Page 123: UnityでのLINQ活用例

ToLookupシーケンスからILookupを作る

グループ化したコレクションを生成

Page 124: UnityでのLINQ活用例

List<Item>*itemListがあって

Dic$onary<ItemType,2List<Item>>が欲しい

LINQにはDic(onary<ItemType,5List<Item>>に似ている

ILookup<ItemType,.Item>が作れるメソッドがある

Page 125: UnityでのLINQ活用例

ToLookupシーケンスからILookupを作る(グループ化したコレクションを生成)

List<Item> itemList = LoadItemList ();

// ILookup<ItemType, Items>は// Dictionary<ItemType,List<Item>>に似ているILookup<ItemType, Item> itemLookup = itemList. ToLookup((Item item) => item.ItemType);

// ディクショナリのように[]とキーでそのグループにアクセスできるIEnumerable<Item> weapons = itemLookup[ItemType.Weapon];

Page 126: UnityでのLINQ活用例

SelectManyリストのリストの平滑化を行う

Page 127: UnityでのLINQ活用例

SelectManyリストのリストの平滑化を行う(その1)

// モンスターのリストのリストList<List<Monster>> listOfMonsterList = LoadListOfMonsterList ();

// モンスターのシーケンスにIEnumerable<Monster> monsters = listOfMonsterList .SelectMany ((List<Monster> list) => list);

Page 128: UnityでのLINQ活用例

SelectManyはリストのリストだけが対象じゃない

結構使える!

Page 129: UnityでのLINQ活用例

こんなクラスがあってpublic class MonsterParty{ public string Name { get; set; } // Monsterのリスト、このプロパティがミソ public List<Monster> MonsterList { get; set; }}

Page 130: UnityでのLINQ活用例

SelectManyリストのリストの平滑化を行う(その2)

// パーティーのリストList<MonsterParty> monsterPartyList = LoadMonsterPartyList ();

// モンスターのシーケンスにIEnumerable<Monster> monsters = monsterPartyList .SelectMany ((MonsterParty party) => party.MonsterList);

Page 131: UnityでのLINQ活用例

Dis$nct重複を除く

Page 132: UnityでのLINQ活用例

Dis$nct重複を除く

// シンプルな例int[] ids = new int[]{0, 1, 1, 2, 2, 2, 3, 3, 4};

// 重複が除かれているIEnumerable<int> distinctedIds = ids.Distinct ();

Page 133: UnityでのLINQ活用例

Dis$nct重複を除く

// パーティーに同じモンスターはいないが、他のパーティーには同じモンスターがいるList<MonsterParty> monsterPartyList = LoadMonsterPartyList ();

// 重複の無しモンスターのIdのシーケンスを作るIEnumerable<int> monsterIds = monsterPartyList // モンスターのシーケンスにして .SelectMany (party => party.MonsterList) // Idのシーケンスにして .Select (monster => monster.Id) // 重複を排除する .Distinct ();

Page 134: UnityでのLINQ活用例

ちなみにLINQには次のような集合演算を行うものもあります

差集合を求める!Except

和集合を求める!Union

積集合を求める!Intersect

Page 135: UnityでのLINQ活用例

Join二つのシーケンスをキーで突合

Page 136: UnityでのLINQ活用例

PlayLogクラスとStageDataクラスから、PlayDataを作りたい

public class PlayLog { // StageのIdのみでStageの情報はない public int StageId { get; set; } public int Score { get; set; } /* 中略 */

}

public class StageData { public int Id { get; set; } public string Name { get; set; } /* 中略 */

}

Page 137: UnityでのLINQ活用例

PlayLogクラスとStageDataクラスから、PlayDataを作りたい

public class PlayData { // StageDataクラスの名前から public string StageName { get; set; } // PlayLogクラスのScoreから public int Score { get; set; } /* 中略 */}

Page 138: UnityでのLINQ活用例

List<PlayLog>なplayLogListと

List<StageData>なstageDataListから

PlayDataのシーケンスを作りたい

Page 139: UnityでのLINQ活用例

foreachな例// foreachな例、長いList<PlayData> playDataList = new List<PlayData> ();foreach(PlayLog playLog in playLogList) { StageData targetStageData = null; foreach(StageData stageData in stageDataList) { if (playLog.StageId == stageData.Id) { targetStageData = stageData; break; // nullなやつはないよねというコード } } playDataList.Add (new PlayData { StageName = targetStageData.Name, Score = playLog.Score, });}

Page 140: UnityでのLINQ活用例

LINQ利用な例// LINQ利用な例、まだ長いList<PlayData> playDataList = new List<PlayData> ();

foreach(PlayLog playLog in playLogList) { StageData stageData = stageDataList.First (stage => stage.Id == playLog.StageId);

playDataList.Add (new PlayData { StageName = stageData.Name, Score = playLog.Score, });}

Page 141: UnityでのLINQ活用例

Joinの例IEnumerable<PlayData> playDatas = playLogList.Join ( stageDataList, (PlayLog playLog) => playLog.StageId, // PlayLogのキー (StageData stageData) => stageData.Id, // StageDataのキー // 二つのキーが揃ったPlayLogとStageDataが来る (PlayLog playLog, StageData stageData) => new PlayData { StageName = stageData.Name, Score = playLog.Score, });

Page 142: UnityでのLINQ活用例

さて

Page 143: UnityでのLINQ活用例

LINQとのつきあい方• エラーにならないライブラリを作るor使う

• エラーになるメソッドor使い方で使わない

• Editor拡張のみで使う

• エラーになる問題が直るまで待つ

Page 144: UnityでのLINQ活用例

何か質問あります?

Page 145: UnityでのLINQ活用例

さて、今日の目標のおさらいです

Page 146: UnityでのLINQ活用例

今日の目標みなさんに• LINQを使うとコードが綺麗になることを知ってもらう

• LINQを使える活用シーンが多いことを知ってもらう

• LINQを使ってみよう・勉強してみようと思ってもらう

• LINQにこんな便利なメソッドあったんだと知ってもらう

Page 147: UnityでのLINQ活用例

いかがだったでしょうか?LINQ使ってみたくなりましたか?

Page 148: UnityでのLINQ活用例

ありがとうございました!@RyotaMurohoshi