<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>KYUCON*BLOG</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/" />
    <link rel="self" type="application/atom+xml" href="https://www.kyucon.com/blog/atom.xml" />
    <id>tag:www.kyucon.com,2017-12-10:/blog/1</id>
    <updated>2020-06-11T12:44:11Z</updated>
    <subtitle>FlashとUnityの実験や、日常について、メモ代わりに載せていきます｡ </subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 6.3.6</generator>

<entry>
    <title>[Unity] Android App Bundle(AAB)どこで設定するの？</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2020/06/unity-android-app-bundleaab-1.html" />
    <id>tag:www.kyucon.com,2020:/blog//1.466</id>

    <published>2020-06-11T12:34:10Z</published>
    <updated>2020-06-11T12:44:11Z</updated>

    <summary>APKではなくAABにしたいのだけど、Unity 2018.4のBuild Se...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="Android" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>APKではなくAABにしたいのだけど、Unity 2018.4のBuild Settingsを見ても<br />あるはずのBuild App Bundle (Google Play) の項目が見当たらない。<br /><br />検索してもわからず時間を取られてしまったけど結論としては、<br />一つ上の項目であるBuild Systemを「Gradle」にすると出てきた！<br />Internalだと表示されない。<br /><br /></p>]]>
        
    </content>
</entry>

<entry>
    <title>[Unity] Android App Bundle(AAB)どこで設定するの？</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2020/06/unity-android-app-bundleaab.html" />
    <id>tag:www.kyucon.com,2020:/blog//1.465</id>

    <published>2020-06-11T12:34:10Z</published>
    <updated>2020-06-11T12:43:27Z</updated>

    <summary>APKではなくAABにしたいのだけど、Unity 2018.4のBuild Se...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>APKではなくAABにしたいのだけど、Unity 2018.4のBuild Settingsを見ても<br />あるはずのBuild App Bundle (Google Play) の項目が見当たらない。<br /><br />検索してもわからず時間を取られてしまったけど結論としては、<br />一つ上の項目であるBuild Systemを「Gradle」にすると出てきた！<br />Internalだと表示されない。<br /><br /></p>]]>
        
    </content>
</entry>

<entry>
    <title>Visual Effect Graphのカスタムアトリビュート</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2019/08/visual-effect-graph.html" />
    <id>tag:www.kyucon.com,2019:/blog//1.464</id>

    <published>2019-08-12T07:26:03Z</published>
    <updated>2019-08-12T08:02:06Z</updated>

    <summary>Unity VFX Graphのサンプルを見ていると検索しても出てこないアトリビ...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>Unity VFX Graphのサンプルを見ていると<br />検索しても出てこないアトリビュートブロック（"Base Position"とか"Offset 1" とか）を使っている事があり<br />いったいどうやって使うのか調べた結果、<br />下記のチェックボックスをONにすると使えるようになるという事だった。<br />Preferences -&gt; Visual Effects &gt; Experimental Operators/Blocks<br /><br />ONにすると Set Custom AttributeブロックとGet Custom Attributeノードを作成できるようになる。<br />作成するとデフォルトはfloatだが、ブロックを選択してInspectorから型を変えたり、ランダムにしたり、Attribute名を変えたりできる。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Unity、iOSでアプリアップデート時にdeviceUniqueIdentifierが変わってしまう</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2019/05/unityiosdeviceuniqueidentifier.html" />
    <id>tag:www.kyucon.com,2019:/blog//1.463</id>

    <published>2019-05-04T06:11:43Z</published>
    <updated>2019-05-25T01:12:31Z</updated>

    <summary>PlayFabのログインユーザーの識別IDとして、SystemInfo.devi...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="PlayFab" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="iOS" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p><span face="Menlo" style="font-family: Menlo;">PlayFabのログインユーザーの<span>識別</span>IDとして、SystemInfo.deviceUniqueIdentifierを使用している状況で。<br />アプリのアンインストールなどせずに、ただAppStoreでアップデートしただけなのにIDが変化して新規ユーザー扱いになってしまう事象が２件発生した。<br />ユーザー端末は、いずれもiPhone8で iOS 11.3 と iOS 12.2 だった。<br />iOSのバグなのか不明だが非常に困る。<br /><br /><del datetime="2019-05-25T09:57:41+09:00">ひとまず対策として</del><br /><del datetime="2019-05-25T09:57:41+09:00">初回のみ<span face="Menlo" style="font-family: Menlo;"> SystemInfo.deviceUniqueIdentifierを取得してPlayerPrefsに保存し、<br />２回目以降はPlayerPrefsに保存しておいた値を使うことにした。<br />アンインストールしない限りPlayerPrefsは残っているはずなのでたぶん大丈夫だと思う。<br /></span></del><span face="Menlo" style="font-family: Menlo;"><br /></span><span face="Menlo" style="font-family: Menlo;">対策としてKeychainにIDを保存することにした。<br />Keychainに保存したデータは、たとえアンインストールしても残るのでPlayerPrefsより安心。<br />有償アセット<a href="https://assetstore.unity.com/packages/3d/characters/ios-keychain-plugin-43083">iOS Keychain Plugin</a>を使ったが、ネイティブ部分は<a href="https://github.com/phamtanlong/unity-ios-keychain-plugin">unity-ios-keychain-plugin</a>と同じだったので買わなくても良かったかも。<br />有償の方は、iOS以外の場合に<span face="Menlo" style="font-family: Menlo;"><span>persistentDataPathに暗号化したファイルとして保存するようになっていた。</span></span></span></span></p>]]>
        
    </content>
</entry>

<entry>
    <title>PlayFabのローカライズ</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2019/03/playfab-4.html" />
    <id>tag:www.kyucon.com,2019:/blog//1.462</id>

    <published>2019-03-23T07:45:05Z</published>
    <updated>2019-03-23T08:23:10Z</updated>

    <summary>言語ごとに表示内容を変える方法について。ニュース、メール、プッシュ通知については...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>言語ごとに表示内容を変える方法について。<br />ニュース、メール、プッシュ通知については管理画面で各言語ごとに文章を登録できるようになっている。<br />これらはプレイヤーの<span>Language設定に従って自動で表示文章が選ばれる。<br /><span>プレイヤーのLanguageが未設定だったり、一致する言語がない場合はデフォルト言語で表示される。<br />デフォルト言語は管理画面のSettings＞Default languageで設定する。<br /><br /></span>クライアントからプレイヤーの言語を登録する方法は下記のような感じで、Profile.VersionNumberが必要になるので先に取得してから、SetProfileLanguage APIを呼ぶ。<br /></span></p>
<pre><code>
//言語を登録する
    public static void SetLanguage(string language)
    {
        //先にプロフィールのバージョン番号を取得する
        GetProfile((version) =&gt; {
            //取得したバージョン番号を用いて言語登録
            SetProfileLanguage(language, version,(success)=&gt; {
                if(success){
                    Debug.Log("登録完了");
                }else{
                    Debug.Log("登録失敗");
                }
            });
        });
    }
//プロフィールのバージョン番号を取得する
    private static void GetProfile(System.Action callback) {
        PlayFabProfilesAPI.GetProfile(new GetEntityProfileRequest{}, result =&gt; {
            callback.Invoke(result.Profile.VersionNumber);
        },error =&gt; {});
    }
//言語登録APIを実行する
    private static void SetProfileLanguage(string language,int profileVersion, System.Action callback)
    {
        var request = new SetProfileLanguageRequest
        {
            Language = language,
            ExpectedVersion = profileVersion
        };
        PlayFabProfilesAPI.SetProfileLanguage(request, res =&gt;
        {
            callback.Invoke(true);
        }, error=&gt; {
            callback.Invoke(false);
        });
    }
</code></pre>
<p>Unityで取得できるOSの言語（Application.systemLanguage）をPlayFabの言語コードに変換するには下記のようになると思う。 （PlayFabのドキュメントに言語コード一覧が見当たらなかったので、管理画面のプルダウンで使用されている言語コードを使用）<br />※Application.systemLanguageで取得できる言語数より、PlayFabで設定できる言語数のほうが多いが割愛<br />※ノルウェー語やセルビアクロアチア語は、PlayFabでは2種類に分かれるが独断で選んだ。</p>
<pre><code>
    public static string GetLanguageCode()
    {
        switch (Application.systemLanguage)
        {
            case SystemLanguage.Afrikaans: return "af";//アフリカ語
            case SystemLanguage.Arabic: return "ar";//アラビア語
            case SystemLanguage.Basque: return "eu";//バスク語
            case SystemLanguage.Belarusian: return "be";//ベラルーシ語
            case SystemLanguage.Bulgarian: return "bg";//ブルガリア語
            case SystemLanguage.Catalan: return "ca";//カタロニア語
            case SystemLanguage.Chinese: return "zh-Hans";//中国語
            case SystemLanguage.ChineseSimplified: return "zh-Hans";//中国語簡体字(simplified)
            case SystemLanguage.ChineseTraditional: return "zh-Hant";//中国語繁体字(traditional)
            case SystemLanguage.Czech: return "cs";//チェコ語
            case SystemLanguage.Danish: return "da";//デンマーク語
            case SystemLanguage.Dutch: return "nl";//オランダ語
            case SystemLanguage.English: return "en";//英語
            case SystemLanguage.Estonian: return "et";//エストニア語
            case SystemLanguage.Faroese: return "fo";//フェロー語
            case SystemLanguage.Finnish: return "fi";//フィンランド語
            case SystemLanguage.French: return "fr";//フランス語
            case SystemLanguage.German: return "de";//ドイツ語
            case SystemLanguage.Greek: return "el";//ギリシャ語
            case SystemLanguage.Hebrew: return "he";//ヘブライ語
            case SystemLanguage.Hungarian: return "hu";//ハンガリー語
            case SystemLanguage.Icelandic: return "is";//アイスランド語
            case SystemLanguage.Indonesian: return "id";//インドネシア語
            case SystemLanguage.Italian: return "it";//イタリア語
            case SystemLanguage.Japanese: return "ja";//日本語
            case SystemLanguage.Korean: return "ko";//韓国語
            case SystemLanguage.Latvian: return "lv";//ラトビア語
            case SystemLanguage.Lithuanian: return "lt";//リトアニア語
            case SystemLanguage.Norwegian: return "nb";//ノルウェー語(ブークモール)
            case SystemLanguage.Polish: return "pl";//ポーランド語
            case SystemLanguage.Portuguese: return "pt";//ポルトガル語
            case SystemLanguage.Romanian: return "ro";//ルーマニア語
            case SystemLanguage.Russian: return "ru";//ロシア語
            case SystemLanguage.SerboCroatian: return "sr-Latn";//セルビアクロアチア語 (Serbian (Latin))
            case SystemLanguage.Slovak: return "sk";//スロバキア語
            case SystemLanguage.Slovenian: return "sl";//スロベニア語
            case SystemLanguage.Spanish: return "es";//スペイン語
            case SystemLanguage.Swedish: return "sv";//スウェーデン語
            case SystemLanguage.Thai: return "th";//タイ語
            case SystemLanguage.Turkish: return "tr";//トルコ語
            case SystemLanguage.Ukrainian: return "uk";//ウクライナ語
            case SystemLanguage.Vietnamese: return "vi";//ベトナム語
            default: return "en";
        }
    }
</code></pre>
<p>インベントリアイテム名などはローカライズシステムが整っていないので、CustomDataにjson形式で文言を入れておいて自前で選ぶ。</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Unity ] 透過動画(WebM VP8)を作ったときのメモ</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2019/03/unity-webm-vp8.html" />
    <id>tag:www.kyucon.com,2019:/blog//1.461</id>

    <published>2019-03-21T14:09:59Z</published>
    <updated>2020-02-22T02:16:09Z</updated>

    <summary>Unityでサポートしているアルファチャンネル付き動画の形式はWebM（動画コー...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>Unityでサポートしているアルファチャンネル付き動画の形式はWebM（動画コーデックはVP8、音声コーデックはVorbis）。<br /><br />FFmpegを使って、PNG連番画像をWebMにするなら下記で良い。</p>
<pre><code>ffmpeg -r 30 -i frames\%04d.png -auto-alt-ref 0 -c:v libvpx -b:v 5M output.webm</code></pre>
<p>今回、音声コーデックがOpus形式のWebMファイルがあり、そのままではUnityで読み込めないためVorbis形式に変換する必要があった。<br />一発でいけるかもしれないけど、うまくできなかったので下記のような手順を踏んだ。<br />１）サウンドだけ抜き出す</p>
<pre><code>ffmpeg -i original.webm -acodec libmp3lame -aq 4 sound.mp3</code></pre>
<p>２）映像をいったん連番PNGに書き出す</p>
<pre><code>ffmpeg -vcodec libvpx -i original.webm frames\%04d.png</code></pre>
<p>３）連番PNGをWebMファイルに変換（その際フレームレートを60から30に変換、解像度を640x360に変更、ビットレートは20000kb/s）</p>
<pre><code>ffmpeg -framerate 60 -i frames3\%04d.png -vf fps=30 -s 640x360 -auto-alt-ref 0 -c:v libvpx -pix_fmt yuva420p -metadata:s:v:0 alpha_mode="1" -b:v 20000k -r 30 noSound.webm</code></pre>
<p>４）無音のWebMにサウンド(Vorbisコーデック)をつける</p>
<pre><code>ffmpeg -i noSound.webm -i sound.mp3 -c:v copy -c:a libvorbis -map 0:v:0 -map 1:a:0 final.webm</code></pre>
<p><br />なお、Androidで再生する場合は<br />Unityの映像ファイルのImport SettingsでTranscodeをオンにしてCodecをVP8にする必要がある。<br /><br />映像をPlaneとかに貼り付けて透過表示するにはマテリアルのシェーダーをUnlit/Transparentにすれば良い。</p>]]>
        
    </content>
</entry>

<entry>
    <title>PlayFabの不具合とか</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2019/03/playfab-3.html" />
    <id>tag:www.kyucon.com,2019:/blog//1.460</id>

    <published>2019-03-16T10:14:20Z</published>
    <updated>2019-03-23T07:42:18Z</updated>

    <summary>ゲームのバックエンドプラットフォーム「PlayFab」について。一通り機能が揃っ...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="PlayFab" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>ゲームのバックエンドプラットフォーム「PlayFab」について。<br />一通り機能が揃っていて自前で用意する手間が省けるし、<br />インディープランもあるのでみんな使えばいいと思う一方でたまに変な不具合が起きて心配になる。<br />基本的にサービスは安定していると思うけど、これまでに主に管理画面側で遭遇した不具合を記しておく。<br /><br />・Title News APIで、ある日を境にエラーが起きるようになった。<br />→Newsのローカライズ機能が告知なく実装され、既存のニュース記事があるとデータ取得できない状態に。機能リリース前にテストしてないのかな。<br /><br />・他人のタイトルのニュースが混入して消せない現象。<br />→サポートチケット書いたら、インディープランは個別サポートしないのでフォーラムに投稿せよとのこと。1，2週間で直った。<br /><br />・管理画面のメニューが押せない現象。<br />→日本語でのみ発生、1日くらいで直った。<br /><br />・特定のLeaderboadのみ「<span>StatisticAlreadyHasPrizeTable</span>」エラーが出てPrize Tablesを作成できない。<br />→フォーラムに報告したらすぐに対応してもらえた。<br /><br />ついでに欲しい機能：<br />・間違って作ったLeaderboardを消したいな。<br />・ユーザー毎のデータは充実してるけど、タイトル全体の統計情報（総プレイ回数とか流通コイン総額とか）を保存するデータベースがあればなぁ。<br />・有償コインと無償コインをまとめて扱う機能。現状はCloudScriptで実装。</p>]]>
        
    </content>
</entry>

<entry>
    <title>アドフリくん Unity動画広告SDKのパーミッション</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2019/03/-unitysdk.html" />
    <id>tag:www.kyucon.com,2019:/blog//1.459</id>

    <published>2019-03-05T05:54:48Z</published>
    <updated>2019-03-05T06:00:41Z</updated>

    <summary>アドフリくんのUnity動画広告SDK Ver.2.20.1から下記のAndro...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p><span>アドフリくんのUnity動画広告SDK Ver.2.20.</span><wbr /><span>1から<br />下記のAndroidパーミッション要求が自動で追加されるようになった。</span></p>
<p>・SDカードのコンテンツの読み取り（<span>SmaAdで使用</span>）<br />・SDカードのコンテンツを修正/削除する（SmaAdで使用）<br />・Wi-Fiからの接続と切断（Tapjoyで使用）</p>
<p>これらのパーミッションを取り除くためには、<br />/Assets/Plugins/Android/AndroidManifest.xmlに下記を追記する必要があるとの事。<br /><br />・SDカードのコンテンツの読み取り<br />　&lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove"/&gt;<br />・SDカードのコンテンツを修正/削除する<br />　&lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove"/&gt;<br />・Wi-Fiからの接続と切断<br />　&lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE" tools:node="remove"/&gt;<br />　&lt;uses-permission android:name="android.permission.CHANGE_WIFI_STATE" tools:node="remove"/&gt;</p>
<p><span> </span></p>]]>
        
    </content>
</entry>

<entry>
    <title>PlayFabのセッション切れ</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/12/playfab-2.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.458</id>

    <published>2018-12-23T08:34:56Z</published>
    <updated>2018-12-23T08:41:18Z</updated>

    <summary>PlayFab APIはログインから24時間経つとセッションが切れて、下記のエラ...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="PlayFab" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>PlayFab APIはログインから24時間経つとセッションが切れて、下記のエラーが起きる。</p>
<pre><code>{
"code": 401,
"status": "Unauthorized",
"error": "NotAuthenticated",
"errorCode": 1074,
"errorMessage": "X-Authentication HTTP header contains invalid ticket"
}
</code></pre>
<p>ゲームを中断して、次の日に続きを遊ぶ場合などに起こり得るので、エラーチェックと再ログインを実装しておかないといけない。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Unity + PlayFabで課金処理</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/12/unity-playfab.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.457</id>

    <published>2018-12-15T14:51:11Z</published>
    <updated>2018-12-15T15:58:41Z</updated>

    <summary>App Store,Google Play Storeの課金処理はUnity I...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="PlayFab" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>App Store,Google Play Storeの課金処理はUnity IAPで行って、レシートチェックとアイテム付与をPlayFabAPIで行う。<br />以下、要所だけ載せます。</p>
<p></p>
<pre><code class="csharp">
//////////////////////////
// Unityの課金システム構築
StandardPurchasingModule module = StandardPurchasingModule.Instance();
ConfigurationBuilder builder = ConfigurationBuilder.Instance(module);
//商品ID登録（ストアに登録したIDとPlayFabのカタログアイテムIDを統一しておくと面倒がない）
builder.AddProduct("MyItemID", ProductType.Consumable);
// 非同期の初期化を開始
UnityPurchasing.Initialize(this, builder);


//////////////////////////
//Unity IAP 初期化完了時
//////////////////////////
void OnInitialized(IStoreController controller, IExtensionProvider extensions){
	//ストアの表示価格は下記のようにして取得
	Product p=controller.products.WithID("MyItemID");
	Debug.Log(p.metadata.localizedPriceString);
}


//////////////////////////
//購入ボタン押した時
//////////////////////////
controller.InitiatePurchase("MyItemID");


//////////////////////////
//購入完了時の呼ばれる関数
//////////////////////////
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e){
	//プロダクト不明のため無視
	if (e.purchasedProduct == null){
		return PurchaseProcessingResult.Complete;
	}
	//レシートがないので無視
	if (string.IsNullOrEmpty(e.purchasedProduct.receipt)){
		return PurchaseProcessingResult.Complete;
	}
	//レシート検証＆アイテム付与。iOSとAndroidで分岐
	if (Application.platform == RuntimePlatform.Android){
		ValidateAndroidPurchase(e.purchasedProduct);
	} else {
		ValidateIosPurchase(e.purchasedProduct);
	}
	//PlayFabでレシート検証完了するまでペンディングにする
	return PurchaseProcessingResult.Pending;
}

//////////////////////////
//Androidのレシート検証＆アイテム付与
//////////////////////////
private void ValidateAndroidPurchase(Product purchasedProduct) {
	var googleReceipt = GooglePurchase.FromJson(purchasedProduct.receipt);
	PlayFabClientAPI.ValidateGooglePlayPurchase(new ValidateGooglePlayPurchaseRequest()
	{
		CurrencyCode = purchasedProduct.metadata.isoCurrencyCode,
		PurchasePrice = (uint)(purchasedProduct.metadata.localizedPrice * 100),
		ReceiptJson = googleReceipt.PayloadData.json,
		Signature = googleReceipt.PayloadData.signature
	}, result =>
	{
		//購入処理が完了したものとする
		controller.ConfirmPendingPurchase(purchasedProduct);
		//TODO:インベントリ更新するなど
	},
	error =>
	{
		//使用済みレシートが残っていた場合は完了扱いにする
		if (error.ErrorMessage == "Receipt already used"){
			controller.ConfirmPendingPurchase(purchasedProduct);
		}
	}
	);
}

//////////////////////////
//iOSのレシート検証＆アイテム付与
private void ValidateIosPurchase(Product purchasedProduct){
	Dictionary<string, string> receipt=PlayFabSimpleJson.DeserializeObject<Dictionary<string, string>>(purchasedProduct.receipt);
	var request = new ValidateIOSReceiptRequest
	{
		CurrencyCode = purchasedProduct.metadata.isoCurrencyCode,
		PurchasePrice = (int)(purchasedProduct.metadata.localizedPrice * 100),
		ReceiptData = (string)(receipt["Payload"])
	};
	PlayFabClientAPI.ValidateIOSReceipt(request, result =>
	{
		//購入処理が完了したものとする
		controller.ConfirmPendingPurchase(purchasedProduct);
		//TODO:インベントリ更新するなど
	},
	error =>
	{
		//使用済みレシートが残っていた場合は完了扱いにする
		if (error.ErrorMessage == "Receipt already used"){
			controller.ConfirmPendingPurchase(purchasedProduct);
		}
	}
	);
}
</code></pre>]]>
        
    </content>
</entry>

<entry>
    <title>iOS IAP Sandboxアカウントの切り替え</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/12/ios-iap-sandbox.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.456</id>

    <published>2018-12-13T17:46:07Z</published>
    <updated>2018-12-13T17:52:10Z</updated>

    <summary>「設定＞ iTunesとApp Store」でログアウトしてるのにSandbox...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="iOS" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>「設定＞ iTunesとApp Store」でログアウトしてるのにSandbox用のアカウントを選べない状況。<br />購入ボタンを押すと"Confirm Your In-App Purchase"ダイアログが表示されるが アカウント入力欄が無く、パスワードしか尋ねられない。<br />どうやるのか探し回った結果、<br />「iTunesとApp Store」を<strong>スクロールした下の方にSANDBOXアカウントの項目があった</strong>！ <br />昔からありました？</p>]]>
        
    </content>
</entry>

<entry>
    <title>PlayFabの使い方　ログを採る</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/12/playfab-1.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.455</id>

    <published>2018-12-08T17:50:35Z</published>
    <updated>2018-12-15T16:07:55Z</updated>

    <summary>ユーザーの操作ログやエラーログをサーバーに送るには下記のような感じで実行するとP...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="PlayFab" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>ユーザーの操作ログやエラーログをサーバーに送るには下記のような感じで実行するとPlayStreamに記録される。<br /><pre><code class="csharp">
PlayFabClientAPI.WritePlayerEvent(new WriteClientPlayerEventRequest()
	{
		Body = new Dictionary<string, object>() {{ "foo", "bar"}},
		EventName = "my_custom_event"
	},
	result => Debug.Log("Logged"),
	error => Debug.LogError(error.GenerateErrorReport())
);
</code></pre><br /><br />ログイン完了していないとAPI実行できないのでログインエラーのタイミングでは送れない。</p>]]>
        
    </content>
</entry>

<entry>
    <title>PlayFabの使い方　ユーザーデータ周り</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/12/playfab.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.454</id>

    <published>2018-12-08T16:13:59Z</published>
    <updated>2018-12-15T16:10:51Z</updated>

    <summary>ゲームアプリのバックエンドとしてPlayFabを触り始めました。一通り機能が揃っ...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="PlayFab" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>ゲームアプリのバックエンドとしてPlayFabを触り始めました。一通り機能が揃っていてすごく便利な感じです。<br />英語ドキュメントやフォーラムを検索すれば大抵の事は解決しますが、日本語情報が少ないのでここにメモしておきます。<br /><br />まずユーザーに紐づく情報をどう取得または保存するかについて、下記のように使い分けるのが良さそうです。<br /><br /><strong>・プレイヤー表示名</strong>...<br />　　<a href="https://api.playfab.com/playstream/profile/PlayerProfile" target="_blank">PlayerProfile</a>のDisplayNameで取得。<a href="https://api.playfab.com/documentation/client/method/UpdateUserTitleDisplayName" target="_blank">UpdateUserTitleDisplayName</a>で更新。<br /><br /><strong>・プレイヤーの経験値やハイスコアなどの数値</strong>...<br />　　<a href="https://api.playfab.com/documentation/client/method/GetPlayerStatistics" target="_blank">Statistics</a>データとしてサーバー側のCloudScriptを呼び出して保存する。<br />　　不正対策としてクライアントからは直接書き込めないようにデフォルト設定されている。<br />　　Statisticsとして保存しているデータは<a href="https://api.playfab.com/documentation/client/method/GetLeaderboard" target="_blank">Leaderboard</a>(ランキング機能)として扱える。<br /><br /><strong>・ゲーム内通貨の所持数</strong>...<br />　　<a href="https://api.playfab.com/documentation/client/method/GetPlayerCombinedInfo" target="_blank">GetPlayerCombinedInfo</a>のUserVirtualCurrencyで取得。<br />　　不正対策としてクライアントからは通貨の加算減算ができないようにデフォルト設定されている。<br /><br /><strong>・武器やアイテムやスキルの所持フラグ.</strong>..<br />　　マスター情報は<a href="https://api.playfab.com/documentation/client/method/GetCatalogItems" target="_blank">Catalog</a>で管理し、ユーザーの所持データは<a href="https://api.playfab.com/documentation/client/method/GetUserInventory" target="_blank">GetUserInventory</a>で取得。<br />　　販売アイテムじゃない物はprice 0でカタログ登録しておき、サーバー側の<a href="https://api.playfab.com/documentation/server/method/GrantItemsToUser" target="_blank">GrantItemsToUser</a>で付与するか、クライアント側の<a href="https://api.playfab.com/documentation/client/method/PurchaseItem" target="_blank">PurchaseItem</a>で所持する。<br /><br /><strong>・フレンド情報</strong>...<br />　　<a href="https://api.playfab.com/documentation/client/method/GetFriendsList" target="_blank">GetFriendsList</a>や<a href="https://api.playfab.com/documentation/client/method/AddFriend" target="_blank">AddFriend</a>を使う。<br />　　フレンドというより一方的なフォロー登録なので、相互フォローしたいなら自前で処理を書く。<br /><br /><strong>・そのほか諸々のユーザ情報.</strong>..<br />　　<a href="https://api.playfab.com/documentation/client/method/GetUserData" target="_blank">UserData</a>として取得や保存する。<br />　　クライアントから書き換えられたくないデータは、サーバー側で<a href="https://api.playfab.com/documentation/server/method/UpdateUserReadOnlyData" target="_blank">UpdateUserReadOnlyData</a>を使う。<br /><br /><br />ログイン時にまとめてデータを取得するには、下記のようにGetPlayerCombinedInfoRequestParamsを指定する。</p>
<pre><code class="csharp">
GetPlayerCombinedInfoRequestParams InfoRequestParams = new GetPlayerCombinedInfoRequestParams()
{
	GetPlayerProfile = true,
	ProfileConstraints = new PlayerProfileViewConstraints()
	{
		ShowDisplayName = true
	},
	GetPlayerStatistics =true,
	GetUserInventory = true,
	GetUserData = true,
	GetUserReadOnlyData = true,
	GetUserVirtualCurrency = true
};

PlayFabClientAPI.LoginWithCustomID(
	new LoginWithCustomIDRequest()
	{
		TitleId = PlayFabSettings.TitleId,
		CustomId = SystemInfo.deviceUniqueIdentifier,
		CreateAccount = true,
		InfoRequestParameters = InfoRequestParams
	}, 
	(result) => {}, 
	(error) => {}
);
</code></pre>]]>
        
    </content>
</entry>

<entry>
    <title>Photon Unity NetworkingのPhotonTransformViewで微妙にずれる</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/09/photon-unity-networkingphotontransformview.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.452</id>

    <published>2018-09-15T17:38:44Z</published>
    <updated>2018-09-16T09:03:11Z</updated>

    <summary>位置同期をPhotonTransformViewで行う際、補間処理（Interp...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>位置同期をPhotonTransformViewで行う際、<br />補間処理（Interpolate Option）は「Estimated Speed」を使うのが良さそうなのだが<br />移動停止した時の座標が完全に同期せずわずかにずれたままになる現象がある。<br /><br />これを解消するには、PhotonTransformViewPositionControl.csの91〜94行目あたりを下記のようすると良さそう。</p>
<blockquote>float estimatedSpeed = (Vector3.Distance(m_NetworkPosition, GetOldestStoredNetworkPosition()) / m_OldNetworkPositions.Count) * PhotonNetwork.sendRateOnSerialize;<br /> if (estimatedSpeed &lt; 1f)<br /> {<br /> currentPosition = targetPosition;<br /> }<br /> else<br /> {<br /> // move towards the targetPosition (including estimates, if that's active) with the speed calculated from the last updates.<br /> currentPosition = Vector3.MoveTowards(currentPosition, targetPosition, Time.deltaTime * estimatedSpeed);<br /> }</blockquote>
<p>要は、推定速度がほぼ0になってしまうと最後まで移動してくれないので<br />速度 1f未満なら強制的に目標値ぴったりに移動させている。<br /><br />Photonを使い始めるにあたっては下記の記事がすごく丁寧で分かりやすい。<br /><a href="https://www.urablog.xyz/archive/category/Unity-%E6%8A%80%E8%A1%93%E3%83%A1%E3%83%A2-PUN" target="_blank">【Unity】僕もPhotonを使いたい #01〜#14</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>[Unity] AndroidのWebViewでHTML5 videoを表示</title>
    <link rel="alternate" type="text/html" href="https://www.kyucon.com/blog/2018/09/unity-androidwebviewhtml5-video.html" />
    <id>tag:www.kyucon.com,2018:/blog//1.451</id>

    <published>2018-09-01T11:33:20Z</published>
    <updated>2018-09-01T12:09:41Z</updated>

    <summary>AndroidのWebViewでYoutubeなどvideoタグを使った映像再生...</summary>
    <author>
        <name>okuyama</name>
        
    </author>
    
        <category term="unity" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.kyucon.com/blog/">
        <![CDATA[<p>AndroidのWebViewでYoutubeなどvideoタグを使った映像再生をしようとしてはまった点をメモ。<br />WebViewプラグインは<a href="https://github.com/gree/unity-webview" target="_blank">gree/unity-webview</a>を使用。<br /><br />１）まず、映像が表示されない現象。（音だけ流れて、画面表示は黒か白のまま）<br />AndroidManifestの<span>android:hardwareAccelerated="true"は正しく記述されているのに発生した。</span><br />これについてはUnityのバージョンを上げたら解消。<br />2017.4.10→NG<br />2018.1.1 →OK<br /><br />２）映像再生前にとてもダサい再生ボタンが表示される問題。<br /><img src="https://i.stack.imgur.com/TjWmi.png" width="100" height="100" /><br />これはvideoタグのposter属性がない場合にデフォルトで差し込まれるらしい。<br />Chromeブラウザでは表示されないのにWebViewで見ると表示される。<br />消すにはWebViewPlugin.javaを書き換えて.jarをビルドしなおす必要がある。<br /><br />plugins/Android/src/net/gree/unitywebview/CWebViewPlugin.javaを開き、117行目あたりを下記のように変更。</p>
<blockquote>
<p>webView.setWebChromeClient(new WebChromeClient() {<br />　View videoView;<br />　//透明の画像を返す処理を追記<br />　@Override<br />　public Bitmap getDefaultVideoPoster() {<br />　　return Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);<br />　}</p>
</blockquote>
<p>あとはビルドして出来上がったplugins/Android/bin/WebViewPlugin.jarをUnityのAssets/Pluginsに持っていくだけ。<br />ビルド手順は<a href="https://github.com/gree/unity-webview" target="_blank">gree/unity-webview</a>に書かれているが、JDK10だと下記のエラーが出てビルドが通らない。<br />Could not determine java version from '10.0.1'<br />Gradleのバージョンの問題らしいが、Gradleのバージョンを変えてうまくビルドできなかったので、<br />JDK8をインストールすることで回避。</p>]]>
        
    </content>
</entry>

</feed>
