Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Unity5.3をさわってみた

11,817 views

Published on

UnityFukuoka 09 での発表資料。
Unity5.3のマルチシーン編集( Multi-Scene-Editing )とアプリ内課金( Unity IAP )をさわってみた話。

Published in: Engineering
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Unity5.3をさわってみた

  1. 1. Unity5.3をさわってみた (MSE,IAP) 長峰慶三 2015/12/13 @Unity Fukuoka 09
  2. 2. 自己紹介 • 長峰慶三 • 株式会社Jollystics • ソフトウェアエンジニア • Unity / Xamarin • チャージアックス / ブシドー
  3. 3. 内容 • マルチシーン編集
 (Multi Scene Edit, MSE) • アプリ内課金
 (Unity IAP)
  4. 4. はじめに • 出たばかりの機能をさわってみた話です • 自分の認識・印象なので参考程度に • ちがうよ!ってときはご指摘ください
  5. 5. マルチシーン編集 Multi Scene Editing
  6. 6. デモ
  7. 7. 何がいいのか?
  8. 8. こういうとき? • ベースのシーンにサブシーンを乗せるかんじ • 複数のシーンで使いまわしたい • 複数人でシーンを分割して開発したい プレハブでやってたのが シンプルになりそう!
  9. 9. スクリプト
  10. 10. Application.LoadLevel() Application.loadedLevel … 非推奨になりました
  11. 11. SceneManager using UnityEngine;
 using UnityEngine.SceneManagement; // これがいる
 
 public class SceneA : MonoBehaviour 
 {
 public void OnClick()
 {
 // 5.2
 Application.LoadLevel("SceneB");
 
 // 5.3
 SceneManager.LoadScene("SceneB");
 }
 }
  12. 12. ロード // 5.2
 Application.LoadLevel(0);
 Application.LoadLevel("SceneB");
 
 // 5.3
 SceneManager.LoadScene(0);
 SceneManager.LoadScene("SceneB");
 

  13. 13. ロード(非同期) // 5.2
 var operation = Application.LoadLevelAsync(0);
 var operation = Application.LoadLevelAsync("SceneB");
 
 // 5.3
 var operation = SceneManager.LoadSceneAsync(0);
 var operation = SceneManager.LoadSceneAsync("SceneB");
 

  14. 14. 加算ロード // 5.2
 Application.LoadLevelAdditive(0);
 Application.LoadLevelAdditive("SceneB");
 
 // 5.3
 SceneManager.LoadScene(0, LoadSceneMode.Additive);
 SceneManager.LoadScene("SceneB", LoadSceneMode.Additive);
 

  15. 15. 加算ロード(非同期) // 5.2
 var operation = Application.LoadLevelAdditiveAsync(0);
 var operation = Application.LoadLevelAdditiveAsync("SceneB");
 
 // 5.3
 var operation = SceneManager.LoadSceneAsync(0, LoadSceneMode.Additive);
 var operation = SceneManager.LoadSceneAsync("SceneB", LoadSceneMode.Additive);
  16. 16. アンロード // 5.2
 Application.UnloadLevel(0);
 Application.UnloadLevel("SceneB");
 
 // 5.3
 SceneManager.UnloadScene(0);
 SceneManager.UnloadScene("SceneB");
 

  17. 17. シーン数を取得 // 5.2
 Application.levelCount; // BuildSettingに登録されている数
 
 // 5.3
 SceneManager.sceneCount; // 現在ロードされている数
 SceneManager.sceneCountInBuildSettings; // BuildSettingで登録されている数
 

  18. 18. シーン情報を取得 // 5.2
 Application.loadedLevel; // 現在のシーンインデックス
 Application.loadedLevelName; // 現在のシーン名
 
 // 5.3
 Scene active = SceneManager.GetActiveScene();
 
 Scene scene1 = SceneManager.GetSceneAt(0);
 Scene scene2 = SceneManager.GetSceneByName("SceneA");
 Scene scene3 = SceneManager.GetSceneByPath("Assets/SceneA.unity");
 
 Scene[] loadedScenes = SceneManager.GetAllScenes();
 

  19. 19. Scene構造体 int buildIndex;
 
 string name;
 
 string path;
 
 bool isLoaded;
 
 bool isDirty; // シーンが変更されているか
 
 int rootCount; // シーンのルートにあるゲームオブジェクト数
 
 bool IsValid(); // 有効なシーンかどうか
 

  20. 20. その他 // ゲームオブジェクトが属するシーンを取得
 Scene scene = gameObject.scene;
 
 // ゲームオブジェクトを生成するとActiveなシーンに追加される
 GameObject go = new GameObject("New Object");
 
 // ゲームオブジェクトを特定のシーンに移動
 SceneManager.MoveGameObjectToScene(go, scene);
 
 // シーンをマージ
 SceneManager.MergeScenes(src, dst);
 
 // SceneManager.Get***()で取得できるのはロード済みのシーンのみ
 Scene scene = SceneManager.GetSceneByName("NotLoaded");
 bool isValid = scene.IsValid(); // falseが返る
  21. 21. Unity起動するたびに セットアップが必要
  22. 22. エディタスクリプト
  23. 23. EditorSceneManager using UnityEngine;
 using UnityEngine.SceneManagement;
 using UnityEditor.SceneManagement; // これも必要
 
 {
 // 現在のシーン情報を取得
 SceneSetup[] current = EditorSceneManager.GetSceneManagerSetup();
 
 // シーン情報から再構築
 EditorSceneManager.RestoreSceneManagerSetup(current);
 }

  24. 24. SceneSetupを保存・復元
  25. 25. ScriptableObjectとかね!
  26. 26. デモ
  27. 27. 気になること • Managerオブジェクトのために DontDestroyOnLoadするのは避けたほうが良 い。代わりにManagerシーンを作って加算 ロードで管理すべし。
 と、マニュアルのTipsに書いてある。
 が、理由は分からない。
  28. 28. ドキュメント関係 • マニュアル
 http://docs.unity3d.com/Manual/ MultiSceneEditing.html • スクリプトリファレンス
 http://docs.unity3d.com/ScriptReference/ SceneManagement.SceneManager.html
  29. 29. 共有 • シーン状態保存・復元スクリプト
 https://gist.github.com/KzoNag/ f47e8eddec95afd7b3da
  30. 30. アプリ内課金 Unity IAP
  31. 31. そもそもの アプリ内課金の仕組み
  32. 32. アプリケーション(C#) ネイティブとのつなぎ(C#) ネイティブ(Objective-C, Java) ストア(iOS, Android) ネイティブ
 プラグイン 購入リクエスト 成功 or 失敗
  33. 33. 5.2まで
  34. 34. ①自力で実装する C# Obj-C Java iOS Android
  35. 35. ②アセットを利用 $ Version prime31 Soomla
  36. 36. 5.3
  37. 37. ③Unity公式サポート
  38. 38. アプリケーション(C#) ネイティブとのつなぎ(C#) ネイティブ(Objective-C, Java) ストア(iOS, Android) ネイティブ
 プラグイン 購入リクエスト 成功 or 失敗 Unity ここだけ
  39. 39. 手順 1. ストアでの課金アイテム登録 2. IAP有効化・インポート 3. プログラム実装
  40. 40. ストアでの課金アイテム登録 • 詳細は説明しません • iTunesConnect • GooglePlayデベロッパーコンソール • IDは一緒にしておくと楽っぽい(別でもOK)
  41. 41. IAP有効化・インポート • エディタのServiceビューでIAPを有効化 • 続けてプラグインをインポート
  42. 42. ①Serviceビューを開く ②アカウントを選択して ③プロジェクト作成
  43. 43. これを選択
  44. 44. ここを押して
  45. 45. ①対象年齢に応じて選択 ②保存
  46. 46. インポート
  47. 47. 追加される
  48. 48. プログラム実装 • 結果を受け取るコールバック • 初期化リクエスト • 購入リクエスト
  49. 49. 結果を受け取るコールバック • IStoreListenerインターフェイスを実装する • OnInitialized() • OnInitilizeFailed() • ProcessPurchase() • OnPurchaseFailed()
  50. 50. (例)PurchaseManager using UnityEngine;
 using UnityEngine.Purchasing;
 
 public class PurchaseManager : MonoBehaviour, IStoreListener 
 {
 void OnInitialized(IStoreController controller, IExtensionProvider extensions)
 {
 }
 
 void OnInitializeFailed(InitializationFailureReason error)
 {
 }
 
 PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
 {
 }
 
 void OnPurchaseFailed(Product i, PurchaseFailureReason p)
 {
 }
 }
  51. 51. 初期化完了 IStoreController controller;
 IExtensionProvider extensions;
 public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
 {
 this.controller = controller;
 this.extensions = extensions;
 } • controllerにプロダクト情報が入る • controllerは購入時に使うので保持しておく
  52. 52. 初期化失敗 public void OnInitializeFailed(InitializationFailureReason error)
 {
 } • errorに失敗の理由が入る • 端末の購入設定、有効なアイテムがないetc • 通信できない場合は呼ばれない(トライし続ける)
  53. 53. 購入成功 public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
 {
 return PurchaseProcessingResult.Complete;// アプリケーション側の課金処理も完了
 //return PurchaseProcessingResult.Pending; // 未完了としてIAPシステムに通知
 } • Pendingを返すと起動時に再度ProcessPurchaseが呼ばれる • controller. ConfirmPendingPurchase(product)を呼ぶと完了状態に • Pending->サーバー側でアイテム追加->Confirmみたいなかんじか
  54. 54. 購入失敗 public void OnPurchaseFailed(Product i, PurchaseFailureReason p)
 {
 } • errorに失敗の理由が入る
  55. 55. 初期化リクエスト • プロダクト設定を構築 • プロダクト設定とコールバックで初期化
  56. 56. (例)PurchaseManager using UnityEngine;
 using UnityEngine.Purchasing;
 
 public class PurchaseManager : MonoBehaviour, IStoreListener 
 { … void Start()
 {
 // 基本は定型(購入の内部処理をカスタマイズしたりもできるっぽい)
 var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
 
 // プロダクト設定(プロダクトIDとプロダクトの種類を指定)
 builder.AddProduct("ProductID", ProductType.Consumable);
 
 // 初期化リクエスト(ここで指定したインスタンスのコールバックが呼ばれる)
 UnityPurchasing.Initialize(this, builder);
 } …
 }
  57. 57. ストアごとにIDが異なる場合 builder.AddProduct("ProductID",
 ProductType.Consumable,
 new IDs()
 {
 { "iOSProductID", AppleAppStore.Name } ,
 { "AndroidProductID", GooglePlay.Name }
 } ); • ストアごとに異なる場合も対応可能 • 購入するときは”ProductID”で指定する
  58. 58. 購入リクエスト(簡単版) public void Purchase()
 {
 controller.InitiatePurchase("ProductID");
 }
  59. 59. 購入リクエスト(しっかり版) public void Purchase()
 {
 var product = controller.products.WithID("ProductID");
 
 if (product != null && product.availableToPurchase)
 {
 controller.InitiatePurchase(product);
 }
 
 }
  60. 60. リストアについて • Androidは勝手にリストアしてくれる
 (初期化後にProcessPurchase()が呼ばれる) • iOSは明示的にリストアを呼ぶ必要がある
  61. 61. iOSでのリストア public void Restore()
 {
 var apple = extensions.GetExtension<IAppleExtensions>();
 apple.RestoreTransactions((result) => 
 {
 // result: リストアが成功したかどうか
 } );
 } • 成功したらProcessPurchase()が呼ばれる
  62. 62. 対応しているプロダクト • Consumable : 消費型(コインとか) • NonConsumable : 非消費型(ステージ解放とか) • Subscription : 定期購読
  63. 63. 取得できるプロダクト情報 Productのmetadataプロパティから取得できる • isoCurrencyCode • localizedDescription • localizedPrice • localizedPriceString • localizedTitle
  64. 64. エディタ上での挙動 • すぐに成功コールバックが呼ばれる • 初期化時にuseFakeStoreUIModeという設定 をするとダミーのストアUIを出せる var module = StandardPurchasingModule.Instance(); 
 module.useFakeStoreUIMode = FakeStoreUIMode.StandardUser; // これ
 var builder = ConfigurationBuilder.Instance(module);
  65. 65. デモ
  66. 66. その他 • UnityAnalyticsに紐付いてるので購入数などの 情報を見ることができる • プラグイン自体にもサンプルが入っていて参 考になる
  67. 67. ドキュメント関係 • マニュアル
 http://docs.unity3d.com/Manual/UnityIAP.html • スクリプトリファレンス
 http://docs.unity3d.com/ScriptReference/ Purchasing.UnityPurchasing.html • チュートリアル
 http://unity3d.com/learn/tutorials/topics/analytics/ integrating-unity-iap-your-game-beta?playlist=17123

×