kazumalab tech log

流行りとリラックマと嵐が大好きです。技術的ログ。

アセットストアをまとめたサイトを更新しました。

かずまです。

けものフレンズというアニメが流行ってますね。

わーすごーい!アセットを紹介できるフレンズなんだねーということで(笑)、
Unityのアセットを探して使い方やどういったものか〜みたいなのが書かれたサイトを同時に見つけられる
Assetストアまとめサイトを前回紹介しました。

あの段階ではほんと作りたて、という感じでしたが、今回のアップデートでかなり改善しました。
少しは使いやすくなっていると思われます。

...検索を充実させたい...けど。

アセットを探すなら UA

デザインの変更

前回のデザインも好きだったのですが、並びがどうもうまく収まらなくて止む終えなく変更しました。
今回のはOculusのサイトのような....感じのテンプレートを使用したのでかなり落ち着いています。

フレームワークなどは今まで同様Railsをつかってます。

並びや検索などもわかりやすくなっていると思います。

機能の追加

お気に入り機能

今回は右のメニューバーが追加されています。
これはサインアップ・ログインした場合に有効になります。

いつでも簡単にアクセスできるようになりました。
合計金額も書かれています。
(削除ボタンはまだ未実装なので有効ではありません。)

Twitterアカウント設立!(2/14)

twitter.com

Twitterでは特にゲームがアップされたり、ブログが投稿された場合にのみ更新されます!
ブログを書いたら紐付けてOK!

コンテンツ量

前回よりは20個ぐらいアップしましたが少ないです。
しかし!現在データをかき集めている最中です。
手作業きつい!!

追記

2/12 10:30

コンテンツを頑張って200ほど増やしました!

課題

ドメイン

まだHerokuのドメインを使ってますのでそのうち変更したい。

ドメインを変更しました!
www.asset.techmatome.com

サイト

ぜひ使ってみてください。

www.asset.techmatome.com

メッセージを以前頂いた方へ

前回Slaaskでメッセージを頂いたかたがいらっしゃったのですが、
Slaaskでは長期の会話はダメそうなのでもしこのメッセージをみられましたら
TwitterのDMまたは、FacebookのMessengerでご連絡いただけると幸いです。

Unity C#でHaskellのmapっぽいものを実装したお話

かずまです。

最近、すごいHaskell楽しく学ぼう! を読み始めました。

おもしろおかしく書かれているところもあるので読み行ってしまいます。
なので、寝る前に少し読む、みたいなスタイルで。

Haskellの高層関数

Haskellには高層関数と呼ばれるものがあり、マッピング(map)や畳込みなどが例に挙げれらます。
その中でも今回はmapを実装してみたいと思います。

mapとは?

map関数はリストを返す関数で、引数にfの関数を取り、引数2つめのリストの中身にその関数を適用してくれるという優れもの。
例は以下のように書きます。

map (2 *) [1, 2, 3, 4, 5]
-- [2, 4, 6, 8, 10]

Haskellを僕も今回初めて読み書きしましたがこのように書くようです。
(2 *)は関数で引数としてintを一つ受取り2倍するというもの。

初見では何してるの!?これって感じでした。笑
今回はmapという関数を作って、関数とリストを投げて、マッピングして適用させます。

C#でのFunctional的に書く方法

  • Lambda式を使う

C#でもLambda式が使えるのでそれを利用します。
無名関数とも言いますね!

公式ドキュメントはこちら。
Lambda Expressions (C# Programming Guide)

  • 引数でデリゲートを使う

Lambda式を受けるデリゲートは

Func(T, TResult) Delegate (System)

ココらへんを使えば良さそうです。

** Func

これは一つ目のTは引数の型、TResultは返り値の型をGenericで指定するようです。

なんと、この2つを使えばできるはずですね!!

クラスとメソッドの作成

とりあえず、Funcというクラスを作って、staticでListを返すメソッドを用意してみます。

このような感じで書いてみました。
メソッドをGenericにするのはうーん、どうなのかな。
ClassをGenericにするのもいい気がするけど今はこっちでかきました。

使い方

先程のクラスとは別にFunctorTestクラスを用意します。
以下のように記述してみました。

public class FunctorTest : MonoBehaviour {

	private List<int> list = new List<int>(){ 1, 2, 3, 4, 5 };

	private void Start () {
		System.Func<int, int> f =  (int arg) => {
			return arg * 2;
		};

		list = Functor.map (f, list);

		print (list);
	}
}

追記 2/7

Lambda式をまとめるのもありです。

public class FunctorTest : MonoBehaviour {

	private List<int> list = new List<int>(){ 1, 2, 3, 4, 5 };

	private void Start () {

		list = Functor.map ((int arg) => {return arg * 2;}, list);
		print (list);
	}
}

このコードではHaskellと同じように2倍するLambda式を書いて、それをmapの第一引数として渡すだけ!
簡単ですね!ただHaskellと違ってタイプする数は多いのでスマートじゃない...

これぐらいなら許容範囲!


mapはGenericだけど型を指定しなくても良さそう

mapはGenericな型を要求するので実際は

list = Functor.map<int> (f, list);

と指定するのがいいのか、と想定していました。
ところがTestクラスを書いた時にmapの後ろに型の指定を忘れていたのです。

でもコンパイルエラーも出なく、きちんと出力されていたので
自動的に型を認識するのかと感動してしまいました。

f:id:kazumalab:20170130235140p:plain

きちんとint型だと認識していますね。
公式のドキュメントにもきちんとかいてありました。
Generic Methods (C# Programming Guide)

便利だしHaskellに一歩近づいた?笑

出力結果

f:id:kazumalab:20170130235534p:plain

素晴らしい、ちゃんと出てますね!

Stringでも試してみよう!

Listのintが出来たのでstringでも同様に使えるはずです。

	private List<string> slist = new List<string>() { "Hello", "World" };

	private void Start () {

		System.Func<string, string> fs =  (string arg) => {
			return arg + "(ΦωΦ)";
		};

		slist = Functor.map (fs, slist);

		print (slist);
	}

この様にHelloとWorldの後ろに(ΦωΦ)を付け足すスクリプトです。

結果

f:id:kazumalab:20170131003311p:plain

にゃーと猫がでてきましたね。

まとめ

Haskellはまだまだ初心者ですので間違ってる解説などありましたらご指摘ください。
あとこう書いたほうがいいよ〜みたいなのもぜひ!

今回はHaskellっぽくC#で書いてみよう!みたいな感じでしたが、
おもったより便利だと思います。

追記

C# やるなら LINQ を使おう | プログラマーズ雑記帳

LINQを使えば畳み込みも写像も出来るみたい。
次にそのことを書きたいではある。

Global Game Jam 2017に参加しました。

かずまです。

21 ~ 22日で行われた(他の会場では20日もあった)Global Game Jamに参加してきました。
参加だけでなく僕達IGDA琉球大学、琉ゲ部では沖縄会場の運営も行っておりました。

Global Game Jam(GGJ)とは

Game Jamは、ゲーム開発を行うハッカソンです。
その中でも、Global Game Jam (以下、GGJ) は、ギネス記録を持つ世界最大のGame Jamです。

全世界にハッカソン会場が設けられており、全世界で同じ日に同じテーマでゲームを開発します。GGJは、2009年の初開催以降年々規模を大きくしており、2016年1月のGGJでは、世界93の国と地域で、36,000人以上が参加し、約6,800の作品が制作されました(世界の会場一覧はここから見られます)。

引用URL

Global Game Jam JAPAN | Innovation, Collaboration, Experimentation! Jan. 20~22, 2017

沖縄会場の参加者

毎回少ない沖縄会場ですが、23名の参加がありました。
ほぼ学生ですが、企業の方も数名きていただきました。

最近は

琉球大学
KBC(専門学校)
ITカレッジ

の3校からの参加が多いです。

制作物

今回運営チームとして

evilonedeath.blog.fc2.com

彼と2人で作成しました。

もちろんゲームエンジンはUnityです。
担当はHookを飛ばす、引き寄せる部分を彼に担当してもらい、その他(剣のモデルを含める)は僕が担当しました。

タイトル

「Hook VR」

コンセプト

VRで試したことない体験したい、ということで敵にHookを引っ掛けて、近くに引き寄せて剣で切る、というもの。

プレイ動画


データ配布

HookVR.exe - Google ドライブ

上記URLからダウンロードしてください。
GPU GTX 970以降搭載のPC、HTC Viveが必要になります。

Asset

使ったアセットは

assetstore.herokuapp.com

こちらになります。
やっぱり$10は安い。

第2回 技術的ログ Twitterから

前回の記事はこちら。
blog.kazumalab.com

Twitterでの技術エントリー(?)をまとめただけになります。

技術本の大賞

学生が作ったUE4の作品

めっちゃレベル高い。
ゲームの気持ちいい部分を抜き出しててすごくやりたい。

ねこが可愛い...

たまには癒やしも必要ですよん。

RapidAPIを使えばすべて同一のコーディングで利用できるらしい。

Oculus TouchでもSteamVR Pluginが使えるらしい @Unity

The Labのやつができるみたい。
Steam強い。

写真から木を作成SpeedTree

UE4でも動くのすごくいい。

コードの書く際に見直すべきサイト

Gitからコーディングスタイル、ガイドラインまで、幅広い。

UnityのResourcesからLoadする際のキャストの件

かずまです。

UnityでResourcesからLoadするときになにもキャストしない場合Object型で返ってきます。
ただそれではGameObjectとして使えないのでキャストする必要があります。
今回はas演算子もキャストとして扱っています。
どの方法が一番はやく処理ができるのか、気になったので今回はそれを計測してメモしておきたいと思います。

キャスト方法

現在僕が知っている限りResourcesからのGameObjectへの型の変換方法は3つです。

asを使う

GameObject obj = Resources.Load ("Prefabs/Box/Wood") as GameObject;

予想ではasは早いと聞いたのでこれが早いかと!

(GameObject) 対象物

GameObject obj = (GameObject) Resources.Load ("Prefabs/Box/Wood");

これだとInvalidCastExceptionが投げられる場合があるので2つめの引数として型を指定します。

(GameObject)対象物 + typeof(GameObject)

GameObject obj = (GameObject) Resources.Load ("Prefabs/Box/Wood", typeof(GameObject));

二段階で念入りではありますが、これ実は2回も型変換しているので遅いのでは?と思っています。

Genericで指定

GameObject obj = Resources.Load<GameObject> ("Prefabs/Box/Wood");

Genericはコードを書く文にはキャストし忘れ、ということは減るはずなのでいいのですが、はたしてas演算子とどう変わるかといったところですね。

速度計測方法

今回は上記コードを1万回Loadし、そのたびに速度(時間)を計測します。
それを100回試行し、平均を取ります。

計測に使うのは
C#のStopwatchです。
Stopwatch クラス (System.Diagnostics)

プログラムのサンプルはこちら。

// asでの型変換の計測
for(int count = 0; count < times; count++) {
			Stopwatch st = new Stopwatch ();
			st.Start ();
			for (int i = 0; i < 10000; i++) {
				GameObject obj = Resources.Load ("Prefabs/Box/Wood") as GameObject;
			}
			st.Stop ();
			total_as += st.Elapsed.TotalMilliseconds;
}

PCの性能

OS : macOS Sierra 10.12.2
CPU : 2.9 GHz Intel Core i5
メモリ : 8 GB 2133 MHz

Unityと.Net Framework

Unity 5.5.0f3 Personal (64bit)
.NET Framework 4.5

こんな感じです。

計測結果

以下の結果になりました。
f:id:kazumalab:20170115015326p:plain

表に早い順番に並べるとこのような感じ。

方法 実行時間(100回平均)
as演算子 9.47781ms
(GameObject)対象物 + typeof 9.74216ms
(GameObject)対象物 9.99564ms
Generic 10.02538ms

予想ではas演算子が早いということでしたが、ほんとに早かったです。
as演算子を使う場合は少し制約があるのでそこも考えないと行けないです。

nullが返ってくる

キャストが出来なかった場合、InvalidCastExceptionをthrowされますが、
as演算子ではnullが返ってきます。

ufcpp.net

予想より早い(GameObject)対象物 + typeof(GameObject)

今回は早い結果となりましたが、何回か再生をポチポチした時にtypeofがない方が早いという結果になることも。
一概には早かったとはいえないけど、そこまで遅くないので使うのは良さそうですね。

Genericでは他に比べると遅いのかな、という印象でした。
高速に使うならas演算子、確実にキャストするなら(GameObject)対象物 + typeof(GameObject)を使うのが良さそうですね。

もし、もっとこうしたほうが良い、ホントはこうだと思うことがあればどんどんコメントでください。
絶賛C#マスター中ですのでご指摘、議論は嬉しいです。

よろしくお願いします。