APKã§ã¯ãªãAABã«ã—ãŸã„ã®ã ã‘ã©ã€Unity 2018.4ã®Build Settingsを見ã¦ã‚‚
ã‚ã‚‹ã¯ãšã®Build App Bundle (Google Play) ã®é …ç›®ãŒè¦‹å½“ãŸã‚‰ãªã„。
検索ã—ã¦ã‚‚ã‚ã‹ã‚‰ãšæ™‚é–“ã‚’å–られã¦ã—ã¾ã£ãŸã‘ã©çµè«–ã¨ã—ã¦ã¯ã€
一ã¤ä¸Šã®é …ç›®ã§ã‚ã‚‹Build Systemを「Gradleã€ã«ã™ã‚‹ã¨å‡ºã¦ããŸï¼
Internalã ã¨è¡¨ç¤ºã•ã‚Œãªã„。
APKã§ã¯ãªãAABã«ã—ãŸã„ã®ã ã‘ã©ã€Unity 2018.4ã®Build Settingsを見ã¦ã‚‚
ã‚ã‚‹ã¯ãšã®Build App Bundle (Google Play) ã®é …ç›®ãŒè¦‹å½“ãŸã‚‰ãªã„。
検索ã—ã¦ã‚‚ã‚ã‹ã‚‰ãšæ™‚é–“ã‚’å–られã¦ã—ã¾ã£ãŸã‘ã©çµè«–ã¨ã—ã¦ã¯ã€
一ã¤ä¸Šã®é …ç›®ã§ã‚ã‚‹Build Systemを「Gradleã€ã«ã™ã‚‹ã¨å‡ºã¦ããŸï¼
Internalã ã¨è¡¨ç¤ºã•ã‚Œãªã„。
Unity VFX Graphã®ã‚µãƒ³ãƒ—ルを見ã¦ã„ã‚‹ã¨
検索ã—ã¦ã‚‚出ã¦ã“ãªã„アトリビュートブãƒãƒƒã‚¯ï¼ˆ"Base Position"ã¨ã‹"Offset 1" ã¨ã‹ï¼‰ã‚’使ã£ã¦ã„る事ãŒã‚ã‚Š
ã„ã£ãŸã„ã©ã†ã‚„ã£ã¦ä½¿ã†ã®ã‹èª¿ã¹ãŸçµæžœã€
下記ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’ONã«ã™ã‚‹ã¨ä½¿ãˆã‚‹ã‚ˆã†ã«ãªã‚‹ã¨ã„ã†äº‹ã ã£ãŸã€‚
Preferences -> Visual Effects > Experimental Operators/Blocks
ONã«ã™ã‚‹ã¨ Set Custom Attributeブãƒãƒƒã‚¯ã¨Get Custom Attributeノードを作æˆã§ãるよã†ã«ãªã‚‹ã€‚
作æˆã™ã‚‹ã¨ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã¯floatã ãŒã€ãƒ–ãƒãƒƒã‚¯ã‚’é¸æŠžã—ã¦Inspectorã‹ã‚‰åž‹ã‚’変ãˆãŸã‚Šã€ãƒ©ãƒ³ãƒ€ãƒ ã«ã—ãŸã‚Šã€Attributeåを変ãˆãŸã‚Šã§ãる。
PlayFabã®ãƒã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®è˜åˆ¥IDã¨ã—ã¦ã€SystemInfo.deviceUniqueIdentifierを使用ã—ã¦ã„る状æ³ã§ã€‚
アプリã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãªã©ã›ãšã«ã€ãŸã AppStoreã§ã‚¢ãƒƒãƒ—デートã—ãŸã ã‘ãªã®ã«IDãŒå¤‰åŒ–ã—ã¦æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼æ‰±ã„ã«ãªã£ã¦ã—ã¾ã†äº‹è±¡ãŒï¼’件発生ã—ãŸã€‚
ユーザー端末ã¯ã€ã„ãšã‚Œã‚‚iPhone8㧠iOS 11.3 㨠iOS 12.2 ã ã£ãŸã€‚
iOSã®ãƒã‚°ãªã®ã‹ä¸æ˜Žã ãŒéžå¸¸ã«å›°ã‚‹ã€‚ã²ã¨ã¾ãšå¯¾ç–ã¨ã—ã¦åˆå›žã®ã¿ SystemInfo.deviceUniqueIdentifierã‚’å–å¾—ã—ã¦PlayerPrefsã«ä¿å˜ã—ã€
2回目以é™ã¯PlayerPrefsã«ä¿å˜ã—ã¦ãŠã„ãŸå€¤ã‚’使ã†ã“ã¨ã«ã—ãŸã€‚
アンインストールã—ãªã„é™ã‚ŠPlayerPrefsã¯æ®‹ã£ã¦ã„ã‚‹ã¯ãšãªã®ã§ãŸã¶ã‚“大丈夫ã ã¨æ€ã†ã€‚
対ç–ã¨ã—ã¦Keychainã«IDã‚’ä¿å˜ã™ã‚‹ã“ã¨ã«ã—ãŸã€‚
Keychainã«ä¿å˜ã—ãŸãƒ‡ãƒ¼ã‚¿ã¯ã€ãŸã¨ãˆã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ã‚‚残るã®ã§PlayerPrefsより安心。
有償アセットiOS Keychain Pluginを使ã£ãŸãŒã€ãƒã‚¤ãƒ†ã‚£ãƒ–部分ã¯unity-ios-keychain-pluginã¨åŒã˜ã ã£ãŸã®ã§è²·ã‚ãªãã¦ã‚‚良ã‹ã£ãŸã‹ã‚‚。
有償ã®æ–¹ã¯ã€iOS以外ã®å ´åˆã«persistentDataPathã«æš—å·åŒ–ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å˜ã™ã‚‹ã‚ˆã†ã«ãªã£ã¦ã„ãŸã€‚
言語ã”ã¨ã«è¡¨ç¤ºå†…容を変ãˆã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã€‚
ニュースã€ãƒ¡ãƒ¼ãƒ«ã€ãƒ—ッシュ通知ã«ã¤ã„ã¦ã¯ç®¡ç†ç”»é¢ã§å„言語ã”ã¨ã«æ–‡ç« を登録ã§ãるよã†ã«ãªã£ã¦ã„る。
ã“れらã¯ãƒ—レイヤーã®Languageè¨å®šã«å¾“ã£ã¦è‡ªå‹•ã§è¡¨ç¤ºæ–‡ç« ãŒé¸ã°ã‚Œã‚‹ã€‚
プレイヤーã®LanguageãŒæœªè¨å®šã ã£ãŸã‚Šã€ä¸€è‡´ã™ã‚‹è¨€èªžãŒãªã„å ´åˆã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆè¨€èªžã§è¡¨ç¤ºã•ã‚Œã‚‹ã€‚
デフォルト言語ã¯ç®¡ç†ç”»é¢ã®Settings>Default languageã§è¨å®šã™ã‚‹ã€‚
クライアントã‹ã‚‰ãƒ—レイヤーã®è¨€èªžã‚’登録ã™ã‚‹æ–¹æ³•ã¯ä¸‹è¨˜ã®ã‚ˆã†ãªæ„Ÿã˜ã§ã€Profile.VersionNumberãŒå¿…è¦ã«ãªã‚‹ã®ã§å…ˆã«å–å¾—ã—ã¦ã‹ã‚‰ã€SetProfileLanguage APIを呼ã¶ã€‚
//言語を登録ã™ã‚‹
public static void SetLanguage(string language)
{
//å…ˆã«ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’å–å¾—ã™ã‚‹
GetProfile((version) => {
//å–å¾—ã—ãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’用ã„ã¦è¨€èªžç™»éŒ²
SetProfileLanguage(language, version,(success)=> {
if(success){
Debug.Log("登録完了");
}else{
Debug.Log("登録失敗");
}
});
});
}
//プãƒãƒ•ã‚£ãƒ¼ãƒ«ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’å–å¾—ã™ã‚‹
private static void GetProfile(System.Action callback) {
PlayFabProfilesAPI.GetProfile(new GetEntityProfileRequest{}, result => {
callback.Invoke(result.Profile.VersionNumber);
},error => {});
}
//言語登録APIを実行ã™ã‚‹
private static void SetProfileLanguage(string language,int profileVersion, System.Action callback)
{
var request = new SetProfileLanguageRequest
{
Language = language,
ExpectedVersion = profileVersion
};
PlayFabProfilesAPI.SetProfileLanguage(request, res =>
{
callback.Invoke(true);
}, error=> {
callback.Invoke(false);
});
}
Unityã§å–å¾—ã§ãã‚‹OSã®è¨€èªžï¼ˆApplication.systemLanguage)をPlayFabã®è¨€èªžã‚³ãƒ¼ãƒ‰ã«å¤‰æ›ã™ã‚‹ã«ã¯ä¸‹è¨˜ã®ã‚ˆã†ã«ãªã‚‹ã¨æ€ã†ã€‚ (PlayFabã®ãƒ‰ã‚ュメントã«è¨€èªžã‚³ãƒ¼ãƒ‰ä¸€è¦§ãŒè¦‹å½“ãŸã‚‰ãªã‹ã£ãŸã®ã§ã€ç®¡ç†ç”»é¢ã®ãƒ—ルダウンã§ä½¿ç”¨ã•ã‚Œã¦ã„る言語コードを使用)
※Application.systemLanguageã§å–å¾—ã§ãる言語数よりã€PlayFabã§è¨å®šã§ãる言語数ã®ã»ã†ãŒå¤šã„ãŒå‰²æ„›
※ノルウェー語やセルビアクãƒã‚¢ãƒã‚¢èªžã¯ã€PlayFabã§ã¯2種類ã«åˆ†ã‹ã‚Œã‚‹ãŒç‹¬æ–ã§é¸ã‚“ã 。
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";
}
}
インベントリアイテムåãªã©ã¯ãƒãƒ¼ã‚«ãƒ©ã‚¤ã‚ºã‚·ã‚¹ãƒ†ãƒ ãŒæ•´ã£ã¦ã„ãªã„ã®ã§ã€CustomDataã«jsonå½¢å¼ã§æ–‡è¨€ã‚’入れã¦ãŠã„ã¦è‡ªå‰ã§é¸ã¶ã€‚
Unityã§ã‚µãƒãƒ¼ãƒˆã—ã¦ã„るアルファãƒãƒ£ãƒ³ãƒãƒ«ä»˜ãå‹•ç”»ã®å½¢å¼ã¯WebM(動画コーデックã¯VP8ã€éŸ³å£°ã‚³ãƒ¼ãƒ‡ãƒƒã‚¯ã¯Vorbis)。
FFmpegを使ã£ã¦ã€PNG連番画åƒã‚’WebMã«ã™ã‚‹ãªã‚‰ä¸‹è¨˜ã§è‰¯ã„。
ffmpeg -r 30 -i frames\%04d.png -auto-alt-ref 0 -c:v libvpx -b:v 5M output.webm
今回ã€éŸ³å£°ã‚³ãƒ¼ãƒ‡ãƒƒã‚¯ãŒOpuså½¢å¼ã®WebMファイルãŒã‚ã‚Šã€ãã®ã¾ã¾ã§ã¯Unityã§èªã¿è¾¼ã‚ãªã„ãŸã‚Vorbiså½¢å¼ã«å¤‰æ›ã™ã‚‹å¿…è¦ãŒã‚ã£ãŸã€‚
一発ã§ã„ã‘ã‚‹ã‹ã‚‚ã—ã‚Œãªã„ã‘ã©ã€ã†ã¾ãã§ããªã‹ã£ãŸã®ã§ä¸‹è¨˜ã®ã‚ˆã†ãªæ‰‹é †ã‚’è¸ã‚“ã 。
1)サウンドã ã‘抜ã出ã™
ffmpeg -i original.webm -acodec libmp3lame -aq 4 sound.mp3
ï¼’ï¼‰æ˜ åƒã‚’ã„ã£ãŸã‚“連番PNGã«æ›¸ã出ã™
ffmpeg -vcodec libvpx -i original.webm frames\%04d.png
3)連番PNGã‚’WebMファイルã«å¤‰æ›ï¼ˆãã®éš›ãƒ•ãƒ¬ãƒ¼ãƒ レートを60ã‹ã‚‰30ã«å¤‰æ›ã€è§£åƒåº¦ã‚’640x360ã«å¤‰æ›´ã€ãƒ“ットレートã¯20000kb/s)
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
4)無音ã®WebMã«ã‚µã‚¦ãƒ³ãƒ‰(Vorbisコーデック)ã‚’ã¤ã‘ã‚‹
ffmpeg -i noSound.webm -i sound.mp3 -c:v copy -c:a libvorbis -map 0:v:0 -map 1:a:0 final.webm
ãªãŠã€Androidã§å†ç”Ÿã™ã‚‹å ´åˆã¯
Unityã®æ˜ åƒãƒ•ã‚¡ã‚¤ãƒ«ã®Import Settingsã§Transcodeをオンã«ã—ã¦Codecã‚’VP8ã«ã™ã‚‹å¿…è¦ãŒã‚る。
æ˜ åƒã‚’Planeã¨ã‹ã«è²¼ã‚Šä»˜ã‘ã¦é€éŽè¡¨ç¤ºã™ã‚‹ã«ã¯ãƒžãƒ†ãƒªã‚¢ãƒ«ã®ã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’Unlit/Transparentã«ã™ã‚Œã°è‰¯ã„。
ゲームã®ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ãƒ—ラットフォーム「PlayFabã€ã«ã¤ã„ã¦ã€‚
一通り機能ãŒæƒã£ã¦ã„ã¦è‡ªå‰ã§ç”¨æ„ã™ã‚‹æ‰‹é–“ãŒçœã‘ã‚‹ã—ã€
インディープランもã‚ã‚‹ã®ã§ã¿ã‚“ãªä½¿ãˆã°ã„ã„ã¨æ€ã†ä¸€æ–¹ã§ãŸã¾ã«å¤‰ãªä¸å…·åˆãŒèµ·ãã¦å¿ƒé…ã«ãªã‚‹ã€‚
基本的ã«ã‚µãƒ¼ãƒ“スã¯å®‰å®šã—ã¦ã„ã‚‹ã¨æ€ã†ã‘ã©ã€ã“ã‚Œã¾ã§ã«ä¸»ã«ç®¡ç†ç”»é¢å´ã§éé‡ã—ãŸä¸å…·åˆã‚’記ã—ã¦ãŠã。
・Title News APIã§ã€ã‚る日を境ã«ã‚¨ãƒ©ãƒ¼ãŒèµ·ãるよã†ã«ãªã£ãŸã€‚
→Newsã®ãƒãƒ¼ã‚«ãƒ©ã‚¤ã‚ºæ©Ÿèƒ½ãŒå‘ŠçŸ¥ãªã実装ã•ã‚Œã€æ—¢å˜ã®ãƒ‹ãƒ¥ãƒ¼ã‚¹è¨˜äº‹ãŒã‚ã‚‹ã¨ãƒ‡ãƒ¼ã‚¿å–å¾—ã§ããªã„状態ã«ã€‚機能リリースå‰ã«ãƒ†ã‚¹ãƒˆã—ã¦ãªã„ã®ã‹ãªã€‚
・他人ã®ã‚¿ã‚¤ãƒˆãƒ«ã®ãƒ‹ãƒ¥ãƒ¼ã‚¹ãŒæ··å…¥ã—ã¦æ¶ˆã›ãªã„ç¾è±¡ã€‚
→サãƒãƒ¼ãƒˆãƒã‚±ãƒƒãƒˆæ›¸ã„ãŸã‚‰ã€ã‚¤ãƒ³ãƒ‡ã‚£ãƒ¼ãƒ—ランã¯å€‹åˆ¥ã‚µãƒãƒ¼ãƒˆã—ãªã„ã®ã§ãƒ•ã‚©ãƒ¼ãƒ©ãƒ ã«æŠ•ç¨¿ã›ã‚ˆã¨ã®ã“ã¨ã€‚1,2週間ã§ç›´ã£ãŸã€‚
・管ç†ç”»é¢ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãŒæŠ¼ã›ãªã„ç¾è±¡ã€‚
→日本語ã§ã®ã¿ç™ºç”Ÿã€1æ—¥ãらã„ã§ç›´ã£ãŸã€‚
・特定ã®Leaderboadã®ã¿ã€ŒStatisticAlreadyHasPrizeTableã€ã‚¨ãƒ©ãƒ¼ãŒå‡ºã¦Prize Tablesを作æˆã§ããªã„。
→フォーラムã«å ±å‘Šã—ãŸã‚‰ã™ãã«å¯¾å¿œã—ã¦ã‚‚らãˆãŸã€‚
ã¤ã„ã§ã«æ¬²ã—ã„機能:
・間é•ã£ã¦ä½œã£ãŸLeaderboardを消ã—ãŸã„ãªã€‚
・ユーザー毎ã®ãƒ‡ãƒ¼ã‚¿ã¯å……実ã—ã¦ã‚‹ã‘ã©ã€ã‚¿ã‚¤ãƒˆãƒ«å…¨ä½“ã®çµ±è¨ˆæƒ…å ±ï¼ˆç·ãƒ—レイ回数ã¨ã‹æµé€šã‚³ã‚¤ãƒ³ç·é¡ã¨ã‹ï¼‰ã‚’ä¿å˜ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒã‚ã‚Œã°ãªã。
・有償コインã¨ç„¡å„Ÿã‚³ã‚¤ãƒ³ã‚’ã¾ã¨ã‚ã¦æ‰±ã†æ©Ÿèƒ½ã€‚ç¾çŠ¶ã¯CloudScriptã§å®Ÿè£…。
アドフリãã‚“ã®Unity動画広告SDK Ver.2.20.
下記ã®Androidパーミッションè¦æ±‚ãŒè‡ªå‹•ã§è¿½åŠ ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã£ãŸã€‚
・SDカードã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®èªã¿å–り(SmaAdã§ä½¿ç”¨ï¼‰
・SDカードã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ä¿®æ£/削除ã™ã‚‹ï¼ˆSmaAdã§ä½¿ç”¨ï¼‰
・Wi-Fiã‹ã‚‰ã®æŽ¥ç¶šã¨åˆ‡æ–(Tapjoyã§ä½¿ç”¨ï¼‰
ã“れらã®ãƒ‘ーミッションをå–り除ããŸã‚ã«ã¯ã€
/Assets/Plugins/Android/AndroidManifest.xmlã«ä¸‹è¨˜ã‚’追記ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã¨ã®äº‹ã€‚
・SDカードã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®èªã¿å–ã‚Š
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove"/>
・SDカードã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ä¿®æ£/削除ã™ã‚‹
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove"/>
・Wi-Fiã‹ã‚‰ã®æŽ¥ç¶šã¨åˆ‡æ–
 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" tools:node="remove"/>
 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" tools:node="remove"/>
PlayFab APIã¯ãƒã‚°ã‚¤ãƒ³ã‹ã‚‰24時間経ã¤ã¨ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒåˆ‡ã‚Œã¦ã€ä¸‹è¨˜ã®ã‚¨ãƒ©ãƒ¼ãŒèµ·ãる。
{
"code": 401,
"status": "Unauthorized",
"error": "NotAuthenticated",
"errorCode": 1074,
"errorMessage": "X-Authentication HTTP header contains invalid ticket"
}
ゲームをä¸æ–ã—ã¦ã€æ¬¡ã®æ—¥ã«ç¶šãã‚’éŠã¶å ´åˆãªã©ã«èµ·ã“ã‚Šå¾—ã‚‹ã®ã§ã€ã‚¨ãƒ©ãƒ¼ãƒã‚§ãƒƒã‚¯ã¨å†ãƒã‚°ã‚¤ãƒ³ã‚’実装ã—ã¦ãŠã‹ãªã„ã¨ã„ã‘ãªã„。
App Store,Google Play Storeã®èª²é‡‘処ç†ã¯Unity IAPã§è¡Œã£ã¦ã€ãƒ¬ã‚·ãƒ¼ãƒˆãƒã‚§ãƒƒã‚¯ã¨ã‚¢ã‚¤ãƒ†ãƒ 付与をPlayFabAPIã§è¡Œã†ã€‚
以下ã€è¦æ‰€ã ã‘載ã›ã¾ã™ã€‚
//////////////////////////
// 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 receipt=PlayFabSimpleJson.DeserializeObject>(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);
}
}
);
}