SOOMLA@Unityによるストアの情報取得(値段とか)

課金を行う際に、値段やタイトルなどアプリに組み込むとタイトルの変更や為替の変動による価格の変更に対応するためアプリの再申請が必要になってしまう。
そもそも世界で売る場合は使用しているマーケットの国がわからないので金額が分かりませんね。
なのでマーケット(iTunes Store/Google Play)から直接取得した方がイイ。

SOOMLAだとまずはイベントのリスニング

StoreEvents.OnSoomlaStoreInitialized += this.OnSoomlaStoreInitialized;
StoreEvents.OnMarketItemsRefreshFinished += this.OnMarketItemsRefreshFinished;
StoreEvents.OnMarketItemsRefreshFailed += this.OnMarketItemsRefreshFailed;

this.storeAssets = new StoreAssets();
SoomlaStore.Initialize(this.storeAssets);

そして、初期化完了後にマーケットの情報を取得しに行く。

void OnSoomlaStoreInitialized() {
	#if UNITY_EDITOR
	this.OnMarketItemsRefreshFinished(new List<MarketItem>());
	#else
	SoomlaStore.RefreshMarketItemsDetails();
	#endif
}

取得ができたら自分のストアの設定の情報を取得したMarketItemで上書き。

void OnMarketItemsRefreshFinished(List<MarketItem> marketItems) {
	// ストアの情報を取得したMarketItemで上書きさせていく
	foreach (MarketItem item in marketItems) {
		foreach (VirtualGood good in this.storeAssets.GetGoods()) {
			PurchaseWithMarket purchaseType = good.PurchaseType as PurchaseWithMarket;

			if (purchaseType.MarketItem.ProductId == item.ProductId) {
				purchaseType.MarketItem = item;
			}
	}

	StoreEvents.OnSoomlaStoreInitialized -= this.OnSoomlaStoreInitialized;
	StoreEvents.OnMarketItemsRefreshFinished -= this.OnMarketItemsRefreshFinished;
	StoreEvents.OnMarketItemsRefreshFailed -= this.OnMarketItemsRefreshFailed;
}

ここは…こんな感じでいいのかしら…?
手動でやるのかな?
ストアの情報の取得は稀に失敗することもあるので、何度かリトライさせる必要もありそうです。

Animator.SetFloat()でアニメーションのループが止まる

Animator.SetFloat()にてdampTime, deltaTimeを使用するとアニメーションが止まるケースがある。アニメーションを頻繁に切り替えたり、Unityがポーズされたとき(他のアプリにフォーカスを移したとき)なんかによく起こる気がする。
アニメーションが短いときや、dampTimeが短いときに起こりやすい気もします…
いくつかの条件が重なって起こるんでしょうか…それともまったく別の原因なのか…(謎)

SOOMLA@Unityによる、iOS, Androidでの課金方法

UnityでIAP(アプリ内課金)をやってみたのでメモ。(Store Version 1.8.2)
まず、どんなライブラリがあるのかはこちらが参考になります。
基本的にSOOMLAは課金周りの処理だけではなくて、ユーザーのアイテム管理、ショップ管理までサポートするフレームワークでそこに課金機能もサポートされているという感じ。ユーザーの持ち物をすべてOS側のデータ領域に保存してくれる。
アプリ内でショップ、持ち物の管理ができるので便利だけど、サーバー側でも同じような管理をする場合にはその辺の機能は使わず購入処理だけうまく使う感じになりますが、その場合はprime31なんかを使った方がシンプルかもしれません。(有料 iOS/Androidそれぞれ$70くらい)
今回はサーバーでアイテムを管理するものの、SOOMLAのソースコードやコメントがキレイだったり、アップデートが頻繁だったりSOOMLA側のスタッフやユーザーのコミュニティが活発だったのでSOOMLAを選んでみた。

SOOMLAで(消耗型)課金コンテンツの実装でのメモ。
そもそもアプリ内課金自体が初めてなので、各プラットフォームの下準備。
まずはiOS側の下準備。

Continue…

Lightmap使用時に暗くなる問題

Lightmapを使ってGlobal Illuminationを焼き込んだ際に、staticなオブジェクトが暗くなってしまうケースがあったので調べてみた。
iOS8や最新のAndroidでは大丈夫だけど、iOS7やAndroidの古い機種で暗くなってしまった。
どうやらLightingの設定の、General GI => Directional ModeをDirectionalにするとOpenGL ES 3.0以上のデバイスでしか動かず、Non Directionalにする必要があるようです。
lighting_directinal_mode

違いは、

Non-directional(負荷低)ライトマップのデータを一つだけ持つ、一番に負荷が低いモードです。
Directional(負荷中)ライトマップのデータを複数持ち、よりリアルな影を表現できます。

こちらのイメージを見るとわかりやすいかも。
lighting_directional_image

でも、調べると僕のiOS7@iPhone5sもOpenGL ES 3.0対応となっているんですが暗くなります。。。

参考)
vDogのUnityプログラミング | Unity5のLightmapでマップの影を作成
いんでぃーづ | Unity5の Lighting ウインドウの見かた ~基本編~

影が切れる

UnityEditor上では問題ないけどモバイルに転送すると、カメラが動くときに影が切れてしまう現象があったので調べてみた。
はじめはレンダリングのカリングかLightのBias/Normal Biasあたりかと思ったら、影を描画する距離の設定でした。

Edit > Project Settings > Quality
こちらで、モバイルのクオリティの
Shadows > Shadow Distance
こちらの数値が

カメラから影が見える距離範囲。この距離を越えて投影される影はレンダリングされません。

ということらしい。
この数値を調整すればOK。
ただし、計算する影の量が増えるので負荷が高くなります。
スクリプトからは

QualitySettings.shadowDistance

こちらに設定でOK。

UniRx

最近になって、Reactive Extensions通称Rxというのが気になってたのですがUnityにもUniRxというのがあるので試してみた。
C#で実装されている機構なんだけどこの機能はLINQとの関連が深いのでまずはLINQをある程度理解していないといけない。
そもそもC#でデータの問い合わせをするにはLINQ以前は

IEnumerable<Character> q =
	from c in Characters
	where c.hp >= 100
	select c;

こんな感じでプログラムとは分離されたSQL的な書き方をしていたらしい。
それがLINQを使うと

IEnumerable<Character> q = this.Customers
				.Where(c => c.City == "London")
				.Select(c => c);

こんな感じで、見やすいメソッドになる。
データベースに限らずデータの集合(XMLやJSON)なども同じ機構で扱えるようにしたのがLINQ to XMLやらLINQ to JSONというものらしい。
C#のIEnumerable<T>の型に対してLINQが適応できて、例えばListのようなデータに対して偶数(Where)のものを3つ(Take)取得するとすると。

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
IEnumerable<int> numsEnumerable = list.Where(_ => _ % 2 == 0).Take(3);
foreach (int num in numsEnumerable) {
	Debug.Log(num); // 2, 4, 6
}

こんな感じになる。
データの最大値を取得したり、平均を算出したりなどデータ群に対して抽出や操作ができる。
参考)
地平線に行く | LINQの拡張メソッド一覧と、ほぼ全部のサンプルを作ってみました。

C#の強みはLINQと言われているくらいなんだけど、どうもUnityではiOSに書き出した際に落ちることがあるらしい。詳細はこちら
Qiita | やっぱりUnityでもC#なんだからLINQが使いたい!

LINQはデータ群を扱う為のものですが、「イベントもタイムライン上で順番に並べるとそれも一つの配列と見なせ、LINQのような機構をつかってイベントをフィルタリングやデータを操作できますよね。」っていう変態的な考えを誰かが考えた!それがReactive Extensions。
JavaScriptですがこちらの記事がわかりやすい。
LIG Inc | 「RxJS」初心者入門 – JavaScriptの非同期処理の常識を変えるライブラリ

最初にMicrosoft DevLabsに2009年に登場したようでまだ新しい技術ですね。これがだんだんとjsやphpなどでも広がっていき言語を超えた機構として広まっているみたいです。

LINQもまったく使ったことがなかったので、LINQも含め幾つかのサンプルを作ってUniRxを試してみた。
(1つ落ちるサンプルがあるけど、なにか間違っているのかな…?)
あとは開発者さんのところで開催された勉強会の資料なんかも読むと良さそうです。

第一回UniRx勉強会を開催しました+スライドまとめ

LINQのSelectManyは理解に時間がかかったけど、こちらを参考に勉強した。
[C#・LINQ]九九だけじゃない!アプリ開発にもゲーム開発にも使える、SelectMany!
Rxの場合はSelectManyはストリームの流れを変えるようなときに使われるって感じでしょうか。

Continue…

Androidに書き出したアプリのログを確認する方法

android_device_monitor

Unityで書き出したものをAndroid端末で見る際にログが見たいなと思い調べてみました。
Android端末にかき出すためにAndroidのSDKを入れたと思うんですがそのSDKのtoolsの中にmonitorというアプリがあるのでこちらを立ち上げればAndroidのすべてのログが確認できます。

参考)

アニメーションのマスク

layer_mask

アニメーションで歩いているキャラに手を上げさせたい場合、別途手を上げて歩いているアニメーションを作るといろいろと大変になってくるのでマスクするにはどうしたらいいのかなと思ったらMecanimにLayerという概念があった。
ちょっとテキトーなキャラを作って動かしてみたところできた。

Animator上でLayerを追加するとLayerの設定に、weightというのがあってこいつが他のレイヤーとの動きの重みとなっている。Maskというのは3Dオブジェクトのどの部分を指すかというオブジェクトでAssetsにCreate => Avatar Maskで作成できる。Humanoidの場合はパーツを選べばいいし、独自の3Dパーツであれば指定したAvatarからボーンの構造を選んで指定できる。Layerの設定に今回であれば右腕だけをマスクしたAvatar Maskを設定してweightを変えれば歩きながら右腕をあげる動きの完成。Blendingはマスクしたパーツの動きを上書きするかどうか(Override)、もしくは重ねるか(Additive)が選べる。Syncを選択すると選択したレイヤーと同じステートマシーンの構造が作られるので手をあげるでも、歩いている時走っているときなどで変えたい時にいいのかな。

参考)Unity | アニメーションレイヤー

Unityのサンプルプロジェクト

Unityをインストールするときにサンプルプロジェクトを入れるかどうか聞かれるので、インストールしてみたけどどこにあるのか分からなかった。
そしたらここにあった。(Mac)

/ユーザー/共有/Unity/Standard Assets Example Project