FirebaseとAdmobをUnity上に共存させて盛大に詰まった時の対処法

はじめに

標題の通りです。Firebaseでシステムを作ったのは良いけど、AdMobの設定が終わっているUnityのProjectに持っていったら盛大にエラーが出まくって詰みまくった時にどう解決したか、をレポートしていきます。

AdMobについては至る所で説明されているので割愛させていただきます。
Firebaseについては、本ブログで色々と記事を記載していますので、そちらを御覧ください。

www.project-unknown.jp

事象

AdMobとFirebaseをUnity上で同居させると、Editorエラーに始まりスクリプトエラーやらマニュフェストがどうたらとか、、、もちろんゲームを実行させることも出来ません。
(あまりのエラーの多さにキャプチャやらログを控えるのを諦めてしまった(;・∀・)

原因

心をポッキリ折ってくれた詰みポイントを交えて、原因を紹介します。

エラーの内容が多すぎ(詰みポイント1)たのですが、私が解決した際の助けになったエラーログが以下です。

TypeLoadException: Could not load type 'GooglePlayServices.UnityCompat' from assembly 'Firebase.Editor'. 

↓を見る限りだとどうもPlayServicesResolverを常に最新にしないと行けないとなっています。

github.com

PlayServicesResolverはGoogleから提供されるPackageに大体梱包されています。

が、どれが最新かわかりません。(詰みポイント2)

また、PlayServicesResolverはUnityの不具合なのかわかりませんが、Project Viewを綺麗にしようとして、別フォルダ等に移動していたら、同一ファイルと認識しません(詰みポイント3)

と言うか、Firebaseから入ってくるPlayServicesResolverはファイル名にバージョンが示されており、またAdMobから入ってくるPlayServicesResolverはファイル名にバージョンが入って居ないため、やっぱりどれが最新かわかりません(詰みポイント4)

解決策 (2017/9/3時点)

FirebaseとAdMobの共存で不具合が起きた場合は大体がPlayServicesResolverに行き着くと思います。
対応方針は、最新のPlayServicesResolverにすることです。

2017/9/3時点では、Firebaseから導入するPlayServicesResolverの方が最新でしたので、こちらを採用しました。(と言うか2つとも試して、エラーにならない方を採用した)

なので、現状私の構成は以下の通りです

f:id:project-unknown:20170903211533p:plain

参考

blog.naichilab.com

written by ゆう@あんのうん

本当に書いた、怖いソース (swift編) viewDidLoadの肥大化 Initialization Closure

はじめに

どうも、どうまずです。
本当に書いた、汚いソース第2弾です。

今回はどんな怖いソースが出てくるのか・・・・

viewDidLoad

まずはこちらのソースをご覧頂きたい。

override func viewDidLoad() {
    super.viewDidLoad()
    
    mainCollectionView.delegate   = self
    mainCollectionView.dataSource = self

    // xibの読み込み
    self.mainCollectionView.register(UINib(nibName: MainNibName.title.rawValue, ・・・
    //以下略




おわかり頂けただろうか・・・
一見なんの変哲もないviewDidLoadですが、

書きすぎなんです

サンプルなどでも、delegateやdataSourceはviewDidLoadに記載されていることが多いのですが、本格的なアプリ開発になればなるほど、このviewDidLoadが長くなるんです。

そのため、ViewDidLoadに記載しなければならない処理は極力外だし・メソッド化して、読みやすくしとくようにしましょう。

修正後のソースは下記の通りです。

override func viewDidLoad() {
    super.viewDidLoad()
    
    collectionViewInitialize()
    
    // xibの読み込み
    self.mainCollectionView.register(UINib(nibName: MainNibName.title.rawValue, ・・・
    // 中略
}

func collectionViewInitialize() {
            
    mainCollectionView.delegate   = self
    mainCollectionView.dataSource = self

}

今回はちょっと過剰かもしれませんが、 viewDidLoadを簡素化しておくという発想が大切です。

さらに初期化でいろいろ記載することがあるようならば、 「Initialization Closure」という方法もあるようです。

参考サイト

qiita.com

例えば、下記のように単純なラベルを表示するコードがあるとします。

let testLabel = UILabel()
override func viewDidLoad() {
    super.viewDidLoad()
    
    testLabel.text      = "どうまず"
    testLabel.textColor = UIColor.blue
    testLabel.frame     = CGRect(x: 0, y: 0, width: 100, height: 50)
    
    view.addSubview(testLabel)
}

これもviewDidLoadの簡素化の観点からどうにかしたいソースです。
これを下記のように、クロージャで初期化しちゃいます。

let testLabel = {() -> UILabel in
    let label       = UILabel()
    label.text      = "どうまず"
    label.textColor = UIColor.blue
    label.frame     = CGRect(x: 0, y: 0, width: 100, height: 50)
    return label
}

override func viewDidLoad() {
    super.viewDidLoad()
        
    view.addSubview(testLabel())        
}

これでviewDidLoadには必要最低限の記載だけになりましたね。
私はaddSubViewを殆ど使ったことなかったので、こんなやり方もあるんだとちょっと驚きました。
ダイエット方法はいろいろありますね。頑張って痩せなきゃ・・・

注意

レビューアの観点によって、諸説あります。

HomebrewがMacのVerupで動作しなくなった時にやったこと

f:id:project-unknown:20170903131826p:plain

はじめに

MacをEl Capitanにした時も発生したのですが、Sierraでも発生してこれまでとちょっと対策が違ったので記事にします。

PlantUMLをbrewから入れようとしたのですが、以下のエラーが発生しました。

/usr/local/bin/brew: bad interpreter: /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin: no such file or directory

ちなみに当たり前なのですが、以下のコマンドみたいにversionの確認すらできません。

brew --version  

検索してみても、似たような所で上記エラーと一緒にRubyの方でもエラーが発生している記事ばかりで軽く詰み掛けたのですが、色々と試行錯誤してみます。

brewのRubyのPathを変更する

とりあえずエラーに出ているrubyのPathが1.8と明らかに古かったので、そこを直してみます。

$ vim /usr/local/bin/brew

brefore

#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -W0

after

#!/System/Library/Frameworks/Ruby.framework/Versions/current/usr/bin/ruby -W0

結果

以下な感じでエラーが別な所に伝搬しました。

/Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': /usr/local/Library/Homebrew/extend/pathname.rb:185: invalid multibyte escape: /^\037\213/ (SyntaxError)

brewを最新の状態にする

もう

$ brew update

上記すら効かない状態だったので、gitから最新の状態にする (以下、実際はadmin権限でやってます)

$ cd /usr/local/Homebrew
$ git fetch origin

これすらエラーになったらどうしようと不安になったのですが、これは問題なく動作しました。

この状態で再度以下のコマンドを叩きます

$ brew update
Error: /usr/local must be writable!

えー(;・∀・)

ちょっと/usr/local周りの権限を弄るのは怖いですが、どうやらよくあるエラーっぽくて、権限を変更してupdateするのが定石みたいなので、変更して対応します。

$ sudo chown -R $(whoami):admin /usr/local
$ brew update

これでうまく通りました。実行後に、

Homebrew no longer needs to have ownership of /usr/local. If you wish you can
return /usr/local to its default ownership with:
  sudo chown root:wheel /usr/local

こんな配慮されているということは公式的にも問題ない対応みたいですね。

流石に怖いので権限を元に戻しておきます。

$ sudo chown root:wheel /usr/local

最後に冒頭で失敗したversion確認。

$ brew --version  

Homebrew >1.2.0 (no git repository)
Homebrew/homebrew-core (git revision 4572; last commit 2017-09-02)

問題なく通りましたヽ(=´▽`=)ノ

Written by ゆう@あんのうん

UnityでFirebaseのRealtimeDatabaseとデータのやり取りをする - UnityでFirebaseを使ったオンラインランキングシステムを作るvol3

この記事はシリーズ物です。
シリーズの記事は以下を参照ください。
特に本稿は、以下の2つの記事を読み終えている事前提で記載していますのでご注意ください。

www.project-unknown.jp www.project-unknown.jp www.project-unknown.jp

https://assetstore.unityhttps://assetstore.unity.com/packages/3d/environments/fantasy/alchemist-s-house-interior-47318.com/packages/3d/environments/fantasy/alchemist-s-house-interior-47318

はじめに

今回は、FirebaseのRealtimeDatabaseとのデータのやり取りを行います。
これまで、Twitter認証・Firebase認証とやってきて、やっとランキングのデータのやり取りを行います。
試行錯誤した結果を記載していますので、もし手順などの漏れで動かない等御座いましたら、@YuwUnknownまでご連絡ください。

注意

アクセス制限について

今回の記事では、Debug・実装のやりやすさから、FirebaseのRealtimeDatabaseに対しての読み書きの制限を行いません。
実際に運用する際には、セキュリティの観点からも、読み書きの制限を行うことを強くお勧めします
また、読み書きの制限については、次の回で説明する予定です。

データ通信のやり取りについて

今回の記事は、Firebaseの無料の範囲内で記載しています。
無料で出来る範囲は、公式の料金表に詳細が記載されています。

料金表に載っていない突っ込んだ情報は、以下の記事で実際にヒアリングした結果をレポートしていますので、ご確認ください。

www.project-unknown.jp

今回のランキングシステムは、データ量もさほど多くないですし、スコアを見る時だけ接続する等を実施すれば無料の範囲内で十分に使えるはずです。
またFirebaseのRealtimeDatabaseはローカルにキャッシュし、データ更新があれば実際にデータのやり取りを行う優れた機能ですので、そこまで気にする必要は無いかもしれません。

本稿の構成

以下で進めます。

  • FirebaseのRealtimeDatabaseにスタブデータ(自前で用意したデータ)を登録して、Unityから参照できるようにする
  • UnityからRealtimeDatabaseに書き込みをする

では行きます。

FirebaseのRealtimeDatabaseにスタブデータ(自前で用意したデータ)を登録して、Unityから参照できるようにする

Firebaseコンソールにスタブデータを登録し、ルールを編集して簡単にアクセスできるようにする

FirebaseのRealtimeDatabaseを見てみる

まずは、実際にランキングデータを格納することになる、FirebaseのRealtimeDatabaseを見てみます。
Firebase Consoleのプロジェクトに移動して、以下のキャプチャが示す所を見てください。

f:id:project-unknown:20170830222145p:plain

これが実際にデータを格納する所です。最初のデータが無い状態だとrootを指し示すものだけが表示されていると思います。
今開いているのが、データを弄るエディタにもなっているので、実際にデータを手入力で入れてみます。

RealtimeDatabaseにスタブデータを登録する

rootノードをマウスオーバーすると、「+」が出て来るのでクリックします。

f:id:project-unknown:20170831230219p:plain

すると、子要素を入れれるようになるので、ここにデータを追加していきます。

f:id:project-unknown:20170831230304p:plain

ここでは、子要素を更に入れ子にしたいので、「名前」のところだけ入力して、更に「+」ボタンを押します。

f:id:project-unknown:20170831230433p:plain

最終的に、以下のように入力していきます。

f:id:project-unknown:20170831230734p:plain

それぞれの要素の説明は以下です。

  • UnitySample
    • Firebaseでは複数のProjectをぶら下げる事が出来ますし、見て分かるように階層ごとにデータの意味合いをもたらして管理することも出来ます。ここではUnitySampleという名前のProjectという意味での識別子としています
  • Ranking
    • Rankingデータをこの要素の以下にぶら下げるように作っています
  • uid
    • ユーザを一意に特定する為のものです。TwitterのIDでも良いのですが、ここではFirebaseのAuthenticationが発行するuidを入れる用途にしています。
    • 上述の通り、このuidはユーザ毎のrankingデータを格納する為に用意しています
  • name
    • ユーザ名です。Twitterから取得します
  • id
    • ユーザIDです。Twitter IDを入れます
  • score
    • ユーザのScoreです。
  • updatedate
    • データの更新日を入れておきます。

これで、スタブデータを入れることが出来ました。
ここまでデータを入れてきておわかりの通り、FirebaseのRealtimeDatabaseはJSONライクのNoSQLっぽいデータの取扱となります。
SQL周りを知らなくてもなんとかなると言うのが気軽に使えて便利ですね。
ただ、その分DBMSでよく使うリレーションシップ周りのデータ管理をしようと思うと、自力でデータ構造を設計してあーだこーだ考えないといけなくなるので、そこはデメリットになるかも…。

RealtimeDatabaseのルールを編集する。

冒頭で記載しました通り、Firebaseへのアクセスに制限を加えることができます。
デフォルトでは、Authenticationの認証が終わっていないとアクセスする事ができないので、今回の説明を行う上でちょっと不便となるので、アクセス制限を開放します。
ルールについては、次回に詳細を書く予定ですので、本番リリースする際は、確実に適切なルール設定をお願いします
というのと、アクセス制限を開放するのは、テスト時であっても危険ですので、出来ることなら、開発が一段落したらルールを設定して制限するなど自衛を行うように出来ると良いですね。

まず、Database > ルールでルール画面を開きます。

f:id:project-unknown:20170831232437p:plain

恐らくデフォルトでは、以下が設定されていると思います。

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

この状態だと、Firebaseの認証しているユーザのみ読み書きが出来る状態となっています。
これを以下に置き換えてください

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

これで、全てのユーザが読み書き出来るようになります。

UnityからFirebaseのRealtimeDatabaseとデータのやり取りを行う

UnityからFirebaseのRealtimeDatabaseのデータを参照する

前提として、FirebaseSDKがimportされている必要があります。
まだの方はVol2の記事に導入の仕方を載せてますので、importをお願いします。

さぁいよいよRealtimeDatabaseとUnityとを接続させます!

ここでの例は、Firebase Realtime Databaseにあるscoreが一番高いデータを取得する。を目標に実装を行います。

UnityからFirebaseへ接続する設定は、ここまでで全部終わっているので、コードをゴリゴリ書くだけです。

説明は後ほど記載しますので、まずは完成形のコードを記載します。

前回のFirebaseへTwitterアカウントでログインする際のコードを拡張します。

gist.github.com

では、以下に今回追加分になったコードの説明を記載していきます。

コードの詳細

フィールド

フィールドには、以下を追加しています。

// Firebase
private DatabaseReference _FirebaseDB;
private Firebase.Auth.FirebaseUser _FirebaseUser;
  • _FirebaseDB
    • Firebase RealtimeDatabaseへ参照を持ったObjectを保持します。(参照の仕方は後述)
    • 以後は、このObjectに対して読み書きの処理を行えば、適切なタイミングでデータを引っ張り出してくれたり、書き込みの通信を行ってくれるようになります。
  • _FirebaseUser
    • 前回の記事に載せるのを失念していたのですが、Firebaseに接続した際の認証情報を保持し、Firebaseとユーザ認証周りでやり取りする際には、このObjectに保持されている情報を利用します
Startメソッド

Startメソッドには、以下を追加しています。

// Firebase RealtimeDatabase接続初期設定
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("Firebase Realtime Database URL");

Firebaseの接続設定を行います。
中身まで読み取っていないですが、シングルトン設計になっているっぽくて、引数に参照先のURL(Firebase Realtime Database URL)を記載する事で、以後RealtimeDatabaseの参照先はそのURLを見に行くようになります。
URLは、以下のキャプチャの場所を参照して入力してください。

f:id:project-unknown:20170902125359p:plain

// Databaseの参照先設定
_FirebaseDB = FirebaseDatabase.DefaultInstance.GetReference("UnitySample/Ranking");

フィールドにある_FirebaseDBに、どの要素を参照するのかを保持します。
冒頭で作成したスタブデータの、

f:id:project-unknown:20170831230734p:plain

Ranking以下を参照して行きたいので、「UnitySample/Ranking」と記載します。
このように階層は「/」区切りで指定していけば、該当の要素まで一気に絞って参照することができます。

もちろん、「UnitySample/Ranking」ではなく「UnitySample」としても良いのですが、
そうすると、今回必要なのはRanking以下のデータなのに、UnitySampleにぶら下がった全てのデータを取得するようになり、データ通信的に無駄になりますし、後の処理も一々Ranking以下を参照するコードを書かないといけなくなり冗長となってしまいます。
この例の用に、参照する要素が特定出来るのであれば、参照先は一気にその場所まで指定してしまった方が良いです。

FirebaseLoginメソッド

このメソッドは殆ど変更はありません。
認証が完了した後の、以下2行を追加しています。

_FirebaseUser = task.Result;

// 認証完了したらデータを読み込む
this.GetRankingData();

最初の_FirebaseUserに、task.Resultを突っ込んでいるのは、後ほどFirebase認証情報を利用したいので、保持するようにしています。
二つ目の、this.GetRankingData()が、後述するランキングデータを読み込むメソッドを認証が完了した際に実行しようとしています。

GetRankingDataメソッド

今回の肝となる部分です。
ここでは、先程Firebase参照Objectである、_FirebaseDBを用いて実際にデータを取得しています。

_FirebaseDB.OrderByChild("score").LimitToLast(1).GetValueAsync().ContinueWith(task => {
});

ここで、Firebaseからscoreが1番高いユーザのデータを1件だけ取得する。
事を実現しています。

GetValueAsync

GetValueAsyncを使う事で、指定されたPath(UnitySample/Ranking)を1度読み込む事が出来ます。
読み込んだデータはFirebaseでスナップショットと呼ばれます。
なので、データを取得するだけであれば、以下でも十分です。

_FirebaseDB.GetValueAsync().ContinueWith(task => {
});

ただ、これだと「UnitySample/Ranking」パス以下のデータを全て取得してしまうので、不要なデータも受け取ってしまい通信量が増えますし、その後の処理も要るデータ/要らないデータとを分けて処理を行う必要が出てきてしまうため、非常に無駄な事をしてしまいます。
ですので、後述にある通り、ある程度必要なデータを絞って取得するようにします。

今回の例では、1度読み込むだけにしていますが、Realtime Databaseの旨味である、データに変更があったら通信を行うことも出来ます。
これについては別途記事にします。

OrderByChild

SQLを利用した事がある方だとなんとなく意味が理解できそうですが、これで結果を並べ替えることが出来ます。

  • OrderByChildは指定した子キーの値で結果を並べ替える事ができます。
    • また、子キーは指定したPath直下じゃなくても、子の子でも指定できます。
      • 今回の場合は、「UnitySample/Ranking」配下の「uid/score」で並べ替えを行います。
  • OrderByChild("score")とすることで、scoreを昇順に並び替えます。
  • OrderByChildは降順には並び替えることが出来ません。
    ただ、今回はランキングが一番高いユーザ情報を取得したいので、降順なデータが欲しい所。
    そんなときは、以下の、LimitToLastを使って降順なデータ取得を実現します。

データの並び替えには、他にも以下の機能がサポートされています。

  • OrderByKey()
    • 子キーで結果を並べ替える
  • OrderByValue()
    • 子の値で結果を並べ替えます
LimitToLast

これは、OrderByChild等で並び替えられたデータを、末尾から返却する最大数を設定します。
なので、OrderByChildで降順に並び替えを行い、LimitToLastで最後の方のデータを取得する事で降順が実現できます。
以下は具体例です。

// 元のデータの並び
1,3,2,6,5,4,8,7,9

// OrderByChildを掛けた後
1,2,3,4,5,6,7,8,9

// LimitToLast(2)で最後から2番目まで取得
8,9

// これをローカルで大きい順に並び替える
9,8

本当だったら、OrderByChildDeskとかあればいいんですけどね…。
LimitToLastと似た機能として、以下が提供されています。

  • LimitToFirst()
    • LimitToLastの反対で最初の方からデータを取得します
  • StartAt()
    • 指定したキーまたは値以上のデータを取得します
  • EndAt()
    • 指定したキーまたた値以下のデータを取得します
  • EqualTo()
    • 指定してキーまたは値に等しいデータを取得します
まとめると
_FirebaseDB.OrderByChild("score").LimitToLast(1).GetValueAsync().ContinueWith(task => {

これは、
scoreを降順で並び替えたデータの最後から1つ目までのデータを取得する
という事を行っています。

DataSnapshot snapshot = task.Result;

上述していますが、Firebaseで取得したデータをshapshotと呼称しており、
取得した結果(task.Result)をDataSnapshot型のオブジェクトに突っ込みます。

IEnumerator result = snapshot.Children.GetEnumerator();

snapshotに含まれる結果セットをIEnumeratorに一度突っ込み、後のデータを取り出しやすくします。

while (result.MoveNext())

ここで、取得した結果セットをあるだけwhileを回し、データの中にアクセスします。
このwhileの中で、Rankingの子要素にアクセスして、データを受け取っています。

駆け足でしたが、ここまででデータの取得処理が完了です。
一度実行してみましょう。

UnityEditor上だと、Firebaseの接続がうまくいかない事があるので、実機で確認します。
以下は、XCode上からiPhoneで起動してDebugLogの中身を表示しています。

f:id:project-unknown:20170902211227p:plain

無事にデータを取得する事が出来ています。
ただ、スタブデータを1件しか登録していなかったので、OrderByChildやLimitToLastが効いているかわかりにくいので、もう1つデータを登録します。

以下のように、uid2にscoreが200のユーザを追加します。

f:id:project-unknown:20170902211519p:plain

これで再度実行してみましょう。

f:id:project-unknown:20170902211624p:plain

無事取れていますねヽ(=´▽`=)ノ

さて、ここまででFirebase Realtime Database上にあるデータを取得するところまで出来ました。
次は、スタブデータでは無くて、実際にデータを登録します。

UnityからRealtimeDatabaseに書き込みをする

データ取得と同様、Firebaseの設定は終わっているので、コードを書いていきます。
これまでのコードに処理を書き足します。
まずは、最初に完成形のコードをお見せします。

gist.github.com

処理の流れを以下の通りに変えています。

before

  1. Teritterログイン
  2. Firebaseログイン
  3. Realtime Databaseからデータ取得

after

  1. Twitterログイン
  2. Firebaseログイン
  3. Realtime Databaseへデータ書き込み
  4. Realtime Databaseからデータ取得

細かい処理の流れの変更点は上記コードを見てもらうこととして、今回の肝であるデータを追加しているロジックを見ていきます。

WriteNewScoreメソッド

引数に渡されたScoreをFirebase Realtime Databaseへ書き込みに行く用途のメソッドです。
データはDictionary形式でデータ構造を作成します。

しつこいかもしれませんが、今回作成するデータ構造は以下の通りでしたね。

f:id:project-unknown:20170831230734p:plain

「_FirebaseDB」に「UnitySample/Ranking」までのPathを参照するようになっているので、それ以下のデータを作成していきます。

まず、最下層に位置する「name」「id」「score」「updatedate」のデータセットを作成します。

Dictionary<string, object> itemMap = new Dictionary<string, object>();
itemMap.Add("name",       _FirebaseUser.DisplayName);
itemMap.Add("id",         _UserName);
itemMap.Add("score",      score);
itemMap.Add("updatedate", System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));

前回の記事でも書きましたが、Display NameはTwitter Kit for Unityではサポートしていないので、Firebase認証情報から取得するんでしたね。

次に、「uid」部分のデータ・セットを造ります。

Dictionary<string, object> map = new Dictionary<string, object>();
map.Add(_FirebaseUser.UserId, itemMap);

冒頭でも記載しましたが、uidには、FirebaseのAuthenticationが発行するuidを登録したいので、「_FirebaseUser.UserId」からデータを取得しています。
そして、uidをkeyに作成した「name」「id」「score」「updatedate」を纏めたitemMapをvalueに登録します。

最後に

_FirebaseDB.UpdateChildrenAsync(map);

上記、Firebaseへ参照を持ったオブジェクトの、UpdateChildrenAsyscメソッドに、作成したデータをセットすれば、「UnitySample/Ranking」以下にデータを登録できます。

余談

ここまで記載した通り、Dictionary形式でデータセットを作成し、階層構造のデータをつくる分には分かりやすいのですが、毎回このような書き方をすると非常に面倒だったりする時があります。
この場合便利な記載方法があります。

例えば、もう既にuidまで登録されていて、そのuidに紐づくscoreを書き直したいんだと言う場合は、以下のようにも書けます。

Dictionary<string, object> map = new Dictionary<string, object>();
map.Add(_FirebaseUser.UserId + "/score/", itemMap);

_FirebaseDB.UpdateChildrenAsync(map);

このように、書き直したいデータまでKeyに一気にパスを貼ってしまって、それに該当するデータだけセットすれば、データ登録を行うことが出来ます。
極論で言うと、以下のような書き方も出来ます。

Dictionary<string, object> map = new Dictionary<string, object>();
map.Add("/Ranking/" + _FirebaseUser.UserId + "/score/", itemMap);

FirebaseDatabase.DefaultInstance.GetReference("UnitySample").UpdateChildrenAsync(map);

上記の例は、Firebaseへの参照を「UnitySample」までしか貼っていないケースで、RankingからscoreまでのPathを一気に貼る例です。

余談2

Sampleの以下のコードの説明がねーよって思っている人がいるかもしれません、

string key = FirebaseDatabase.DefaultInstance.GetReference("UnitySample").Child("Ranking").Push().Key;

今回の事例では利用していないのですが、Firebaseのデータ管理の意味で重要で便利な意味合いを持つ所なので、今回ご紹介しています。

この部分は、UnitySample/Ranking以下に1つユニークな文字列を作成する
これをどういう時に利用するのか?と言うと、
例えば、今回の例では、ユーザ毎にデータを登録して、更新があれば上書きする仕組みにしていますが、例えばスコアを登録する度に、Updateでは無く追加する場合に大いに役に立ちます。
具体的に言うと、

今回の例

  • 1位 : ゆう@あんのうん
  • 2位 : ぽぽた
  • 3位:どうまず

Push().Keyを使った具体例

  • 1位:ゆう@あんのうん
  • 2位:ゆう@あんのうん
  • 3位:ゆう@あんのうん

上記の用に、ユーザ名でユニークなデータ構造ではなくて、毎回スコア更新する度に別なデータとして登録する事で、まさに昔のゲームセンターにハイスコアを一人のユーザで埋め尽くすような機能も実装出来ます。
ただ、この場合問題となるのが、ユーザ名でユニーク化をしないので、何かしらデータを特定出来るユニークなKeyが必要となり、この例の様なKeyを使うことで同一ユーザでも別なデータとして取り扱うことが出来るようになります。

ただ、Keyは発行する度に異なりますので、自前で何処かに保存しておかないと、自分自身ですら分からないことになるので、取扱注意です。(Firebase上でこれを解決する場合は、「UnitySample/Ranking」とは別に「UnitySample/User/uid/」以下にそのユーザが発行したKeyをぶら下げると言う管理の仕方もありですね。

実行する

余談のほうが長いんじゃないかのレベルで記載してきましたが、さぁ実行してみましょう。
今回は、実際にデータを登録しているので、実機ログではなくて、Firebase Consoleのデータを見てみます。

f:id:project-unknown:20170902224140p:plain

(uid部分は私の実際にuidが入り込んでいるのでモザイクにしています。実際に見てもらえば分かるのですが、英数字の文字列が羅列されていると思います)

これでデータの登録も出来るようになりましたね!

また、例えば、以下の

this.WriteNewScore(100);

をスコア更新の意味で、

this.WriteNewScore(300);

に変更して、再度実行してみましょう。
新規にデータが登録されるんじゃなくて、既にあるユーザのScoreが上書きされたかと思います。

自分自身のデータを取得する

これまではランキングの上位10件を取得する機能を作って来ましたが、自分自身のデータが欲しい時があります。

再掲ですが、以下のデータから、自分自身のuserIDにぶら下がる情報を取得します。

https://cdn-ak.f.st-hatena.com/images/fotolife/p/project-unknown/20170831/20170831230734.png

欲しい情報は、Ranking直下にある、自分自身のUIDの情報です。
このような時は、Childメソッドを使って自分自身のデータを取得します。

_FirebaseDB.Child(_FirebaseUser.UserId).GetValueAsync().ContinueWith(task => {
    if (task.IsFaulted) {
        // 失敗時の処理
    } else if (task.IsCompleted) {
        // 成功時の処理
    }
});

_FirebaseDBは、

_FirebaseDB = FirebaseDatabase.DefaultInstance.GetReference("UnitySample/Ranking");

UnitySample/RankingまでのPathが貼られているので、その直下にある、自分自身のUserIDを指定し取得します。

まとめ

実際にFirebase Realtime Databaseへデータの読み書きを行う所まで行いました。
今回の所で、オンラインランキングシステムが実現できるようになりましたが、何度も記載している通り、今のままだとセキュリティリスクが非常に高いですので、次回はセキュリティ対策の意味を込めた「ルール」造りをしていきます。

参考

本当に書いた、怖いソース(swift編) マジックナンバー

はじめに

どうも、どうまずです。

私が本当に書いて指摘してもらった、汚い・危ないswiftのソースを心霊写真の紹介っぽく記載していきます!

反省も踏まえまして…

恐怖・マジックナンバー

まずは、こちらのソースをご覧下さい・・・。

switch indexPath.section {
  // スケジュール名設定
  case 0:
    return "スケジュール名"
         
  // 曜日設定
  case 1:
    // 曜日の先頭のセル
    guard indexPath.row != 0 else {
  // 以下略






おわかり頂けたでしょうか・・・

一見なんの変哲もないswitch文に見えますが、
case文のところよ〜〜く見て頂きたい・・・。

この0と1、意味を持っているんです!

あれです。
今はわかるけど、後で修正や保守しようとしたときに、 『これ、なんだっけ?』ってなるパターンです。 何とも恐ろしい!!!

これらはマジックナンバーと呼ばれ後々暴れ出すのです。

マジックナンバー (プログラム) - Wikipedia

こういう場合は、enumなどを利用し、 利用し、数字をちゃんと定義してわかりやすくしましょう。

コメントで誤魔化そうとしてもダメです。 最初はコメント書いてても、書き忘れて、結局わからなくなるんですよ。

修正後は下記のような感じです。

enum SectionRowNumber: Int {
    case scheduleName = 0
    case week         = 1
}

switch indexPath.section {
  // スケジュール名設定
  case SectionRowNumber.scheduleName.rawValue:
    return "スケジュール名"
         
  // 曜日設定
  case SectionRowNumber.week.rawValue:
    // 曜日の先頭のセル
    guard indexPath.row != 0 else {
  // 以下略

enum部分が長くなっていますが、ソースだけ見ても、意味がわかるようになりました。

直してやったぜ風に記載してますが、ダメなソース書いたの私なんですよね。

頑張ろう・・・

注意
レビューアの観点によって、諸説あります。

新ブログアイコンつくりました

これまでBlogに、以下のアイコンを使っていたのですが

f:id:project-unknown:20170827023416p:plain

凄い昔に作ったと言うのもあり、ずっと変えたい変えたいと思っていたので、ゲーム開発の素材そっちのけで作りました!

f:id:project-unknown:20170827025326p:plain

どやっ!

このBlogに設定したのですが、キャッシュの兼ね合いで反映は暫く時間がかかりそうです(;・∀・)


この記事の裏のやり取り

ぽぽた「ブログのアイコン変えたから記事に変えておいてー」

ゆう@あんのうん「お、ええでぇー記事の叩きの文章でも良いから書いておいてー」

・・・数分後

ぽぽた「じゃあこれで」

f:id:project-unknown:20170827023754j:plain

ゆう@あんのうん「(これでどないせぇゆうねん(;・∀・))」

written by ゆう@あんのうん&ぽぽた

UnityでFirebaseにTwitterアカウントでログインする機能 - UnityでFirebaseを使ったオンラインランキングシステムを作るvol2

この記事はシリーズ物です。
シリーズの記事は以下を参照ください

www.project-unknown.jp

www.project-unknown.jp

www.project-unknown.jp

やりたい事を簡潔に纏めるskill皆無な為、長いタイトルになってしまった…。

最初に懺悔いたしますと、かなり試行錯誤しながらFirebaseの実装を進めており、思い出しながら書いています。
もしこれで動かなかったなどありましたら、お気軽にTwitter@YuwUnknown までご連絡くださいmm

ここに載せている情報は、公式を参考に記載しているものです、
情報が古くなっている場合は、一度公式を参考くださいませ。

はじめに

Firebaseで用意されているAuthenticationは、簡単に言うとユーザ認証を指します。
独自でユーザ認証システムを行うとシステム構築が大変なので、TwitterやFacebook、Googleアカウント等の認証を作ってユーザのログイン機能を担ってくれます。

前回のUnityでTwitter認証を行うの記事でも書いたのですが、とりあえず今のところの目標はFirebaseでTwitter認証を行い、認証情報で取得したユーザ名でランキングシステムを作ると言う所を目指します。
そこで今回は、Firebase AuthenticationでTwitter認証を行います。

前回は、UnityでTwitter認証をする方法を記載しました。
そこで記載されている、AccessTokenとSecretが必要となるので、まだ見ていない or AccessTokenの取得方法が分からない方は、まず前回の記事を参考に取得できるようにしておいてください。

project-unknown.hatenablog.com

Firebaseの初期設定

Firebaseをまだ登録されていない方は登録しちゃいましょう!

firebase.google.com

また、契約やサービス内容についてヒアリングした結果も過去のブログに載せているので、もし料金が〜など不安な方が居ましたら、以下を一読頂ければと思います。
project-unknown.hatenablog.com

Firebaseのコンソールに移動して、プロジェクトを追加します。(私はfirebase-sampleというプロジェクトを作っています。)
f:id:project-unknown:20170828000653p:plain

プロジェクトの作成が完了したら、作成したプロジェクトをクリックしましょう。Overviewに移動するかと思います。

次に、Authentication -> ログイン方法 -> Twitterをクリックします。

f:id:project-unknown:20170828003602p:plain

ここで、前回のTwitter Developerに登録した発行した、AccessTokenとシークレットを入力します。
(混同しやすいのですが、これは開発者が登録した際のAccessTokenです)

iOS/Android用の設定を行う

OverViewからアプリを追加してください。
iOSとAndroid両方に展開予定であれば、iOS用とAndroid用2つ必要です。

f:id:project-unknown:20170904164755p:plain
追加したらこんな感じになっていると思います。

後は、設定ボタンをタップ

f:id:project-unknown:20170904165013p:plain

以下のようにinfoファイルをダウンロードして、Unityに突っ込みます。

f:id:project-unknown:20170904165101p:plain

ファイル名は以下の通りです。

  • iOS
    • GoogleService-Info.plist
  • Android
    • google-services.json

ここまで実施したらFirebaseの設定は完了です。

Firebase SDKを導入する。

公式からSDKをダウンロードします。
この中に、複数のPackageが梱包されています。
機能毎にPackage名が名付けられているので特に悩まないと思います。

ここでは、以下の2つをimportしてください。

  • FirebaseAuth.unitypackage
  • FirebaseDatabase.unitypackage

(FirebaseDatabase.unitypackageは次回以降で紹介するRealtimeDatabaseで利用しますので、今のうちに入れておきましょう!認証だけでいいんだよと言う人は、FirebaseAuth.unitypackageで十分です)

Firebase Authenticationのコードを書く。

やっとここでコードが掛けます。
やっている事は、以下です。

  • Game起動と同時にUnityからユーザのTwitter認証(Twitterログイン)を行います。
  • Twitter認証が完了したら、取得したAccessToken, シークレットの情報を元に、Firebaseへログインします。

gist.github.com

ここで一点注意点なのですが、今回使ってきているTwitter Kit for UnityにはDisplay Nameを取得する機能はありません。(2017/9/2現在)
Display Nameとは、以下のキャプチャの通り他のユーザに見える名前です。

f:id:project-unknown:20170902215427p:plain

これかなり不便ですね…。
ただ、Firebaseの方で取得する機能があります。
上記の例ですと、以下のところです。

newUser.DisplayName

今回はFirebaseと一緒に使うから良いものの、早めにここは追加してもらいたいですね。

では、これを実機で起動してみてください。
(Unity Editor上でも出来るのですが、Editor上だとFirebaseの動作がなんとなく怪しい動作を行うので、可能なら実機で確認しておいたほうが良いです)
以下はXCodeにFirebaseのログインが成功した際に出力しているログを載せておきます。

f:id:project-unknown:20170828010828p:plain

さいごに

ここまでで、FirebaseにTwitterログインを実現する所まで完了しました。
次はいよいよ、FirebaseのRealtime Databaseに認証したTwitter情報で書き込む所を記載しようと思います。

参考

project-unknown.hatenablog.com

UnityでFirebase Authenticationを使ってみる(公式資料)

SDK配布場所

written by ゆう@あんのうん

個人アプリクリエイター / 個人ゲーム作家が気にしておくべきOSS, Asset, 素材, コード等のライセンスについて

はじめに

(∩´∀`)∩和尚本の影響を受けてゲーム作家と言うワードを使ってみた

最初に記載しておきますが、本稿ではライセンスの考え方等でリスクがあると捉えがちですが、
ライセンスは、少しの意識を持って真摯に捉えていれば恐れるものでは無いと思います。
(とは言え、私自身見たことがないOSSを使う時はビクビクしちゃうのですがw

さて、このblogを読んでいる方、OSSやAsset、他者が作った素材やソースコード等をよく利用されていると思います。

私個人的な考え方も、OSSやAsset, 他人の書いたコードはどんどん利用していくポリシーで、車輪の再発明はすべきではないと考えています。
そんな事に時間を掛けているくらいなら、既にある車輪を活用して新しい価値を作るべきだし、
別な新規性のある価値を生み出して、他の人に使ってもらって、クリエイター全域の生産性を上げるべきだと考えています。

ただ、他者の作成したものを使う時に気をつけておかないと行けない事があります。
それがライセンスです。

ライセンスとは?

ライセンスとは、ざっくり言うと他者が作った成果物を利用する際の制約を指します。
ライセンスは、有償/無償の物共に設定されています。(勘違いし易い所で、有償だからと言って何でもかんでも許されるものではありません。)

ただ、良くライセンスについて取り上げられるのは、オープンソースやフリーなものが取り上げられますので、本稿でもこれ前提で書いています。

ライセンス違反すると何が起きるの?

とんでもないことが起きます

後述しますが、ライセンスには色んな種類が存在し、過去の凡例を見る限りだと、ライセンス毎に酷い目の度合いが異なっています。

具体的に言うと以下が代表的です。

  • 罰金
  • ソースコードの開示
  • ライセンス違反(=コンプライアンス違反)による、社会的信頼の低下

日本だとまだこのライセンスについての意識はそこまで高くないですが、海外だとかなりセンシティブに捕らわれています。
アプリ開発等行って、海外展開を考えている方、是非一度お使いの第三者成果物についてライセンス抵触していないか、確認頂ければと思います。

ライセンスの種類

頭が痛くなる程ごちゃごちゃしています。
批判を恐れず言うと、ここにあるものは全て覚えておく必要が無く、後述しているライセンス以外なものが出てきたら改めて調べると言う感じで十分です。

  • EULA
  • Apache v2
  • GPL
  • MIT
  • LGPL
  • BSD
  • No License
  • etcetc

一覧はこちらのサイト様が分かりやすいと思います。

coliss.com

ライセンスは何処で確認するの?

意識のあるクリエイターの場合は、大体見える位置にライセンスが明記されています。
例えばだと、Twitter Kit Unityのライセンスは以下のGitのReadmeの目立つ位置に記載されています。

github.com

f:id:project-unknown:20170827004309p:plain

また、ソースコードに記載されているケースもありますし、Unityだと特にAssetにライセンスについて記載されていない場合は、EULAが適用されると記載されています。

unity3d.com

ライセンスが何処にも記載されていない場合は勝手に何でもやってよいの?

駄目です
ライセンスが記載されていないものこそ注意が必要です。
ライセンスが記載されていない場合は、著作権が放棄されている訳ではないですし、その利用方法は著作者が決めるものです。勝手な解釈は認められません。

では、ライセンス表記がなかったらどうするのか?
以下が正しい行動になるかなーと思います。

  • 著作者にコンタクトを取ってライセンスの確認を取る。
    • 著作物がコード等公開されているものであれば、ライセンスを明記して配布してもらうようお願いする
  • そもそも使わない

Webサイトに記載されているコードのライセンスの取扱は?

Webサイトで、親切な方がコードを記載しているのをよく見かけますが、これにもライセンスが適用されます。
なので、ライセンスが特に明記されていないコードについて、本来だとシステムに組み込んでは行けません。
(ただ、リバースエンジニアリングでもされない限りバレないと言うと言うのもあり、第一線でも平気でこれが行われているのが現実ですが…特にコピペエンジニアが多い現場だとこれが横行してます

特に、よく見受けられるのがWebサイトを見ながらSampleコードを作って、動いた喜びで自身のblogなどでも取り上げてしまうケース等あると思います。
これは再配布に当たるので本来だとやっちゃ駄目にあたります。
(目くじら立てて怒る人はそういないですけどねw

覚えて置くべきライセンス

さて、本稿の本題です。
色々ライセンスの事を気にしすぎると何もできなくなるので、
誤解を恐れずに記載すると、以下の3つのライセンスについては、特に何も気にしなくて良いです。
(と言うか、OSSなどは、以下の3つが特に多いです。親切なクリエイターさんが多い証拠ですね)

Apache v2 License

www.apache.org

こんな事言うと怒る人が出て来るかもしれませんが、私はApache v2 Licenseだとラッキーだと思ってます。
Apache v2 Licenseは以下を必須とします。

  • 著作権の表示
  • 変更箇所の明示

著作権の表示ですが、良くアプリとか使っていると、ソフトウェアライセンスの項目にこんなOSS使ってますよーと紹介が載っていると思いますが、あれです。
これは諸説あって、ソースコードの方にこのライセンスを使っていると明示するだけで良いと言う説もありますね。(実際にそうやって組み込まれている例をよく見ます)
が、私個人としては著作者へのお礼も込めてユーザが見える位置に良く置きます。

また、Apache v2 Licenseでは以下の事が許可されます。

  • 商用利用
  • 成果物の修正
  • 成果物の配布
  • サブライセンス
  • 特許に組み込んでもOK

ほぼなんでもありです。

MIT License

choosealicense.com

これも特に恐れずに使っても大丈夫です。
Apache v2と同様、著作権の表示さえやっていれば、殆ど何をやっても大丈夫です。

Unity Asset Store EULA

unity3d.com

Unityをやっている人にはおなじみのライセンスですね。
前述していますが、Unity Asset Storeでライセンサ表記が無い場合は基本、このライセンスが適用されます。

ざっくりとこのライセンスは、
ゲーム等に組み込んだ形でのみ再配布が許可されるって感じになる為、Asset Storeで購入したりしたものをゲームに組み込んで商用利用する形とする場合は特に問題が無いと言う話ですね。
(もちろん、ゲームジャム等でもゲームとして組み込んで配布するのも問題無しです。

では、気をつけないと行けないものは?

先に上げた3つ以外のライセンスについては注意が必要です。

GPL

特に代表的なもので、このライセンスを挙げるのですが、
おそらくMIT, Apacheライセンス並に広く浸透しているのがこのGPLライセンスです。

このライセンスは、商用利用も、修正・配布などにも使えるのですが、
ソースコードを明示しないといけません
なので、折角作ったシステムで、このライセンスを利用していると、作ったシステムのコードを開示しないと行けないと言う事態になります。

ただ、GPLライセンスであっても恐れる必要はありません(私は恐れてますが…w)
GPLライセンスの目的の1つは、GPLライセンスで作られた成果物の成長であったり、GPL事態の普及が目的であるため、
利用者に不備があり、問い合わせを受けたとしても速やかに対応を行えばトラブルに発展することは考えにくいです。

ハイブリットライセンス

これは特に意識しないと中々気づけ無いのですが、
その名の通り、ハイブリットライセンスは、著作物に複数のライセンスが混在している事を指します。
作者事例はMITライセンスとして配布していても、その作者が気づいていない所で、GPL等のライセンスの物を使っていた場合、
その成果物はGPLライセンスで配布しないと行けないという決まりがあります。
なので、このケースの場合、MITライセンスで配っている事自体が誤りなのですがね、、、
要するに、MITライセンスで配布されたとして、その中にGPLライセンスが混入していると、その作品事態がGPLライセンスとなる為注意しておく必要があります。

最後に

注意喚起が多くて、ゲンナリしてしまったかもしれませんが、
ライセンスは著作者が、この決まりを守ってくれれば使って良いよと、好意で言っていただいているものであるため、そこは尊守して、生産的な事につなげていきましょう!

written by ゆう@あんのうん

Twitter Kit for UnityでTwitter認証を行う - UnityでFirebaseを使ったオンラインランキングシステムを作るvol1

はじめに

この記事はシリーズ物です。
シリーズの記事は以下を参照ください

www.project-unknown.jp www.project-unknown.jp www.project-unknown.jp

今日はTwitter Kit for UnityでTwitter認証の記事を書きます。

アセットはこれ

最初の背景はどちらかと言うと愚痴りたかったので書いているだけで、中身がありません。急いでいる方は「アセットのimport」から読み進めてください

背景

FirebaseとUnityとを連携させたかったので、公式を見ながら始めようとしたのですが、、

f:id:project-unknown:20170827033146p:plain

思いっきりNativeコードでOAuth認証まで終わらせて来いやって書いてあり衝撃を受け、UnityでのTwitter認証について調べた次第です。

ちなみに、その時の愚痴がこれ

また、何故Twitter Kit for Unityなのかと言うと、よく調べると至るサイトがFabricでやれって書いてあったのですが、

FabricってGoogle(Firebase)に吸収されるから今後どうなるかわからんやん
というか、FabricのTwitterKitが見当たらん

その時の愚痴がこれ

んで、途方に暮れてNativeで書こうか悩んだんですが、折角このAssetがあるなら使ってみようと思った次第です。

なので、最終的にTwitter Kit for UnityでTwitter認証を行い、そこから取得したToken情報を使ってFirebaseまでを目的にしており、
Twitter Kit for Unityの使い方にフォーカスしてます。
(Firebaseだけじゃなくて、このAssetの使い方で戸惑っている人も活用いただけると思い

と言うか、他のサイトで記載されているのが、PINコード認証の古い認証のやり方かFabricでの認証くらいしか見当たらなくて私自身が本当に困ったのが、この記事を書く一番の要因だったのですがね(;・∀・)

アセットのimport

まずは、アセットをダウンロードしましょう。
上記のTwitter Kit for UnityのAsset Storeでimportするか、公式のInstallationからの直リンでpackageを落としてUnityにimportします。
公式からDLする場合は、以下のキャプチャを参考にしてください。

f:id:project-unknown:20170827034004p:plain

Twitter Developerの設定

Twitter API初期設定

https://dev.twitter.comでTwitterの設定を行います。
アカウントを取得していないのであれば、アカウント取得から実施してください。

画面上部のMy Appから、以下の画面が開くのでCreate New Appをクリックします。
キャプチャでは、Firebase用のSampleを造りたかったので、「UnityFirebaseSample」としてます。

f:id:project-unknown:20170827034326p:plain

次が、登録の入力例です。

f:id:project-unknown:20170827034442p:plain

コールバックURLは、Firebaseの場合は指定されています。
これについては、Firebaseの記事を直ぐに執筆予定ですので、そこで説明します。

Twitter APIのPermission設定

ここまで、来ると、以下の画面になっていると思いますので、Permissionをクリックします。

f:id:project-unknown:20170827034621p:plain

特に認証をするだけなら、Read onlyだけで良いのですが、Tweetとかもさせたい場合は、 Read and Writeとかに設定しておきます。

f:id:project-unknown:20170827034724p:plain

Twitter APIのSetting

次はSettingをクリックします。

f:id:project-unknown:20170827034803p:plain

公式にある通り、Call backのロックを解除しておきます。(デフォルトは解除されていると思います)

f:id:project-unknown:20170827034829p:plain

Twitter APIのKeys and Access Tokensの API Keyと API Secretを控える

以下のConsumer Key (API Key)と、Consumer Secret (API Secret)を控えます。後で使います。 f:id:project-unknown:20170827034951p:plain

ここまでで、Twitter APIの設定が完了です。
お次はUnityの設定を行っていきます。

Unityの設定。

Twitter Kitのセットアップ

冒頭で書いた通り、ここまででTwitter Kit for Unityがimportされていると思うので、その体で進めます。

まず、importが正常に完了していると、メニューにTools > Twitter Kitとあると思うので、それをクリックします。

f:id:project-unknown:20170827035202p:plain

inspectorが、以下のキャプチャの通りの画面になっていると思うので、ここに先程控えていた Consumer Keyと Consumer Secretを入力します。

f:id:project-unknown:20170827035233p:plain

TwitterInit.csをGameObjectにアタッチ

importパッケージの中に、「TwitterInit.cs」が梱包されているので、これをScene上のGameObjectにアタッチします。

f:id:project-unknown:20170827035446p:plain

これを忘れると動きませんのでご注意ください(私が、この作業をすっ飛ばしたせいで、3時間位悩みました)

コードを記載

さぁやっとここでコードの記載です。
ここでは、Gameを起動した瞬間にTwitter認証を行おうとしています。

gist.github.com

上記をTwitterKitForUnitySample.csというファイル名で保存して、適当なGameObjectにアタッチします。

注意
ファイル名を別にしたい場合は、クラス部分の

public class TwitterKitForUnitySample : MonoBehaviour {

public class 変更したいファイル名 : MonoBehaviour {

に変更してください。
ファイル名とクラス名が違う場合はアタッチができなくなるのでご注意ください。

Twitterの認証が成功した際に、

public void LoginComplete(TwitterSession session) {

上記メソッドが呼ばれ、TwitterSessionの中に、ユーザを識別する情報が入っています。
ここでは、その他のTweetや、別なサードパーティのシステム(Firebase等)の認証にAccessTokenとAccessTokenのSecretが必要になってくるので、それを抜き出しています。

Build

iOSの場合は、Twitter Kit for UnityがiOS 7.0をサポートしていないので、8とか9以上に設定しておきましょう。
(デフォルトが7になっているはずです)

f:id:project-unknown:20170827040645p:plain

実際に動かす。

すんません、認証のキャプチャ取るのを完全に忘れてました
しかも一度認証すると次は自動で認証が走るので取れませんでした(;・∀・)

XCode等でのログで以下が流れていればOKです

[Info] : Login success. アクセストークン"

さいごに

次はFirebaseと認証して、Firebase上でTwitterユーザでランキングを作るって所まで最終的に記事に書いていきたいと思います。
また、UnityのTwitter認証で調べると、大体がFabricかSocialConnectorとかが引っかかってアプリ内でTwitter認証, Tweetを実施したかった人の助けになれば幸いです。

余談

Twitter Kit for UnityをUnity Cloud buildに掛けると、以下のようなログが出ます。

[Unity] *** {GUID} replaces {GUID} at path assets/plugins/ios/twitterkit.framework/twitterkitresources.bundle/twttr-icn-tweet-place-holder-photo-error@2x.png 

(GUID}は人によって違うランダムな英数が出ると思います。
こちらですが、単純に「twttr-icn-tweet-place-holder-photo-error」のerrorがエラーが起きたかのように解釈されてエラーっぽく見えてしまっていますが、これについては問題ありません。
(私がこれに凄いハマった)

余談2

Twitter Kit for Unityは米国在住の13歳以下の子供への提供は出来ません。
(と言うかTwitterのサービス自体がCOPPA(Children's Online Privacy Protection Act)に引っかかっているので、Twitterを使ったアプリを展開する時点で13歳以下の利用が出来ないように対策を練らないといけないかと思います。)

日本在住の子供向けであれば問題はありませんが、海外展開を考えている場合は十分に注意しましょう。

詳細はTwitter Kit for Unity licenseの「7. End Users」に記載がありますので一読ください。

参考

written by ゆう@あんのうん

Unity Cloud Buildでハマった所 vol2

はじめに

Vol1は↓

project-unknown.hatenablog.com

事象と解決策

Unity Cloud Buildに掛けると、突然以下の様なエラーが出てbuild失敗しました。

 161: [Unity] Shader compiler: internal error compiling shader snippet type=0 platform=5: Protocol error - failed to read correct magic number
 162: [Unity] Shader error in 'Unlit/Transparent': Internal error communicating with the shader compiler process
 163: [Unity] UnityEngine.Debug:LogWarning(Object)
 164: [Unity] Player export failed. Reason: Shader error in 'Unlit/Transparent': Internal error communicating with the shader compiler process
 165: ! build of 'ios' failed. compile failed
 166: publishing finished successfully.
 167: Finished: FAILURE

これが奇っ怪なのが、Androidは成功して、iOSのみ失敗なんですよね。。

グーグル先生にお尋ねした所、Clean buildで治ったとか、昔のOnGUIを使っていたのをuGUIに直したら動いたとかとか。あったので、それぞれやってみようと思います。

Clean -> Buildを試してみる。

Unity Cloud BuildにCleanが見つからへんがな …。

場所が変わった?
そもそも毎回Clean buildになったとか?
とりあえず、見当たらないので諦めます。

古いコードを取っ払う

OnGUI部分のコードがあったので、念のためこれを新しいものに置き換えて見た所、普通に成功しました。

結論

わからん(;・∀・)
再buildで治ったかもしれないですし、OnGUIの部分がやっぱり悪かったのかもしれないですし…。

今日は的を居ない記事になりましたが、こんな所で

written by ゆう@あんのうん

Arbor2とUniRxで指定回数Click/Tapされたら次のStateへ遷移する機能を作る

はじめに

最近、少しずつLinqを覚え始め(C#はまだ毛が生えた程度のSkillなので)、ずっとやりたかったUniRxを使ってみました。
また、折角なので最近一番のお気に入りのAssetのArbor2と組み合わせて何か便利な挙動が作れないかしらと思い、タイトルの通りの機能を造ります。

UniRx

詳しい使い方等は、沢山のサイト様があるので、そちらにおまかせします

Arbor2

project-unknown.hatenablog.com

今回作る仕様

  • 指定回数クリックされたら次のStateに移る
  • クリックを受け付ける入力期間を指定出来るようにする

作ってみた

gist.github.com

上記をコピペするだけで動くと思います。

すると挙動追加で、「Original > Transition > MultiClick」で以下の様な画面が出ると思います。

f:id:project-unknown:20170822004744p:plain

上記のSampleだと、10回クリックされたら次のStateに移るようになります。

実行結果をキャプって見たのですが、動画でも何やっているのかわからなかったのでキャプチャは割愛。

さいごに

UniRxはまだまだ使い慣れていないけど、これまで面倒な処理を書いていたのが簡潔に掛けるのが良いですね。
特に可読性(Linqのskillは必要になってくるけど、ソースファイルの至る所まで処理を追いかけなくても良い意味で)が上がってくると思います。

UnityのuGUI Text周り

はじめに

ずっとTextMesh Pro使ってみたいなぁ〜と思って居た所、

Unity アセット真夏のアドベントカレンダー 2017青木ととさんの以下の記事を読んで、衝撃を受けました。
qiita.com

Alt text
え!?無料なん!?
(2017/8/21現在無料でした)

という訳で、欲しい欲しいと思っていたTextMesh Proを早速導入して、使おうと思ったのですが、
そもそもUnity uGUIのTextを、なぁなぁで使っていた為、ちゃんとプロパティとかの意味をおさらいしておこうと復習がてらにこの記事を書いてます。

当たり前の事含め、はたと私が記憶喪失になった際のマニュアルとして残しておきます。

テキストの作成

Hierarchyで右クリック -> UI -> Textで作成。
(GameObjectメニュー -> UI -> Textでも作成可能)
Textを作成した際に、CanvasがまだScene上に無ければ自動で作成されます。

Textコンポーネント

f:id:project-unknown:20170821012525p:plain
(Fontの部分は第三者の著作権に当たるものを利用させて戴いている為、モザイク加工してます)

Text

表示する文字を入力。

Font

その名の通り表示する文字のFont

Font Style

フォントのスタイルを指定。

  • Normal : 標準
  • Bold : 太字
  • Italic : イタリック
  • Bold Italic : 太イタリック

Font Size

フォントサイズ(ピクセル単位)

Line Spacing

行と行のマージンを指定。
1.0が標準

Rich Text

これをONにすると、Textプロパティの内容をリッチテキストとして取り扱える。

Alignment

配置(左寄せ、中央寄せなどなど

Holizontal Overflow

横の指定領域を文字列がオーバーした際にどうするかを設定。

  • Wrap : 自動折り返し
  • Overflow : そのまま表示(領域無視)

Vertical Overflow

縦の指定領域を文字列がオーバーした際にどうするかを設定。

  • Wrap : 自動折り返し
  • Overfloaw : そのまま表示(領域無視)

Best Fit

文字列がテキストの領域に収まるように自動的にフォントサイズを変更。
BestFitを指定するとFont Sizeで指定したサイズは無視され、Min/Max Sizeプロパティで設定した最大値の間のフォントサイズが採用される。

Color

文字列の色を設定。
リッチテキストで色指定している場合は、この影響を受けない

Material

テキストに使用されるマテリアルを設定。

Rich Text

HTMLライクに装飾出来る。

f:id:project-unknown:20170821013532p:plain

こうすると

f:id:project-unknown:20170821013542p:plain

こうなる。

Font

いずれ書きます

Bitmap Font

いずれ書きます

今日はあまりブログ書いている時間がなかったので、最後尻切れトンボになってしまった。(;・∀・)
端折った部分はいずれ書きます。(一番復習したかったBitmap Fontができひんかった

written by ゆう@あんのうん

KeyHolder2.3.0 リリース前情報やら、今後の展望、今のKeyHolderのユーザ数等のKPIについて展開

はじめに

今日はKeyHolderについてです。
もうすぐKeyHolder - 2.3.0をリリースできそうなので、その前記事になります。
この記事では、2.3.0でやったことや、今後の展開、ずっと公開していなかったKeyHolderのKPIについてさらっと紹介します!

project-unknown.hatenablog.com

Version 2.3.0について

Version2.3.0で何をやったの?

見た目の変化は殆どありません。

  • これまでIDとパスワード、タイトル全てを入力しないと保存できない仕様だったものを、タイトルのみ必須とし、他は任意にしました。
    • (これが何気に一番要望が多かったので…)
  • 後、強いて言うなら設定のレイアウトを今時なものに変更し、公式・TwitterへのURLを追加したくらいです。

じゃあ何が変わったの

内部は全て変わりました。
KeyHolderはこれまでObjective-Cで記載されていた(リリースが2015年なので仕方ないのですが)ものを、swiftにフルスクラッチで書き直しました。
どれくらい変更が加わったかと言うと

f:id:project-unknown:20170820035229p:plain

KeyHolderはBitbucketで管理しているのですが、ざっくり344ファイル分のコードが書き換わってます。
(;・∀・) こんだけ変更を加えているけど、見た目が変わっていないのでメジャーバージョンを変更できないジレンマ。
他ゲーム開発やUnityの勉強と並行して1日辺り30分ずつKeyHolderの対応を行い、約1月位対応に時間がかかったと言う…。

全てSwift化する事によって

Objective-Cでも勿論出来るのですが、今後の機能拡張がすごくしやすくなりました。
どうしてもObjective-Cだとコードが煩雑になって拡張し辛かったのですが、それがなくなったことで、以後のVersion up時の工数負荷が多少なりとも軽減する事が出来ました。

今後の展望について

以下に記載している内容はお約束は出来ません、ただ対応の検討を考えている次第です

バックアップ機能

非常に要望の多い機能ですので、是非とも提供したいとずっと考えています。
が、バックアップ/復元を行うと言う事は、ユーザのデータをAppから外に出す事になるので、セキュリティ上本当にやっても良いのか?に結論が出せておりません。
また、少しでもセキュリティを向上させる意味で、iCloud連携を行い、同一AppleIDでなら復元できると言うところも視野に入れているのですが、
内部のデータロジックがiCloudに対応していない為、中々着手できていない次第です。

ただ、最低限、tsvやcsvで出力だけでも良いから…と言う声も多いので、
責任を丸投げしているようにも聞こえるかもしれませんが、ユーザの責任下の元メールかなにかで外部に出力すると言うところは対応を入れたいと思います。
(ただ、この場合機種変等で復元をしたいとなると思うのですが、このやり方も考えないとですね)

ちなみに機種変時ですが、iTunesのバックアップから復元でパスワードを移すことも出来ますので、新規iPhoneが出るまでにこの対応が間に合わなかった場合は、そちらをお試しください。

指紋認証でマスターパスワードを解除する

これも要望の多い機能ですね。
こちらに関しては前向きに実装していこうと考えてます

2018/1/8 機能実装しました!

www.project-unknown.jp

検索機能の提供

私が一番やりたい機能ですというか、私がまず欲しいです。 KeyHolderはシンプルさを一番のウリにしており、余分な情報は登録出来なくしている為、登録は非常に簡単なのですが、パスワードを探すのが大変になっていると思っています。
実際にカテゴリ機能を提供しておりますが、パスワードの量が多くなると、カテゴリ機能もあまり機能して来なくなると思ってますし、
また並べ替え機能も提供していますが、これに関しては並べ替えに手間がかかる分、KeyHolderのコンセプトと逆行しているんですよね…。
なので、Spotlightライクな検索機能を用意して、文字を入力する毎に絞り込まれていくようにする事で、パスワードを取り出す作業もシンプルに高速に行えるようにしていきたいと考えております。

鍵生成

以外だったのですが、これについても要望がそこそこあります。
KeyHolderのコンセプトを壊さないように機能追加の方向で考えてます。

カテゴリの見た目

これもご要望戴いている所の機能です。
今のところ、どうするのか固まっていない状態ですが、

  • 色の付け方を変える
    • ただ、塗りつぶし等を行ってしまうと、文字色と似た色が設定されている場合、逆に見にくくなってしまう為、慎重に検討中
  • 画像を入れれるようにする
    • 凄い見やすくなって、個性が出るようになるのですが、、、
    • 最初は頑張って登録するんだと思うのですが、数が増えてくると画像を登録するのが億劫になってパスワードを登録しなくなるんじゃないか?の懸念が強いです
  • 文字を1文字 -> 2文字まで表示するようにする
    • AppleやGoogleはこの方式ですね。確かに1文字だけだとわからない時が多いので、これも対応しようと考えてます

広告

インタースティシャル入れたいです。本当に入れたいですが、、実際邪魔だし、KeyHolderは必要な時にさっと取り出して、さっと去っていくアプリで、
他のアプリやWebサイトからKeyHolderでパスワードを見て、またそのアプリやWebサイトに戻っていくまでが一連のUXなんですよね。
インタースティシャルを入れる事で、そのUXを崩してしまう事になり、KeyHolderの価値を確実に崩しかねないので、実装出来ていないです。

ただ、我々もボランティアでやっている訳では無いし、広告収益が無いと確実に赤字なので、広告収益をもっと増やしたい…。
今の画面下部の広告でもそこそこの収益は出していますが、活動資金の確保としてはまだまだ足りていません。

今のKeyHolderのユーザ数等のKPIについて

どこまで情報を出して良いのか判断しきれないので、凄いざっくりと展開します。

DL数

約13,000

DAU

約1,100DAU

MAU

平均7,000MAU

月の収益

ゲームソフトは余裕で余裕で買える程度

総評

DL数は約13,000なのですが、MAUが約7000なので、一度DLして使って頂ければそのままお使い続けて戴いていると言う事がわかります。
アプリの性質上、Push通知などは打ってないので、ユーザが自分の意思でアプリを立ち上げると言う意味で、必須アプリの1つになりえていると伺えて、これは本当に嬉しい限りです。
(ツール系のアプリなので、使ってもらえれば息は長いですしね)

最後に

いつもKeyHolderをご利用戴いている皆様。
本当に有難うございます!これからもご愛用の程宜しくお願い致します!

何か問い合わせしたいこと等ありましたら、以下の公式Twitterか中の人の一人であるゆう@あんのうん宛にご連絡いただくか、「project.unknown.cs@gmail.com」までご一報くださいませ!

twitter.com

twitter.com

まだお使いになられていない皆様。

是非とも使ってみてください!w

project-unknown.hatenablog.com

他のサイト様に掲載されてました

有難うございますmm

applinote.com

trafalbad.hatenadiary.jp

app-field.com

isuta.jp

written by ゆう@あんのうん

Arborを使ってハマったこと - 常駐ステート

はじめに

今日はArbor 2を使っていて少しハマった所を記載。

事象と解決策

前回書いた以下の記事

project-unknown.hatenablog.com


で、扉の開閉を検知してボタンの活性/非活性を行う処理を、
最初以下のように、ボタンを押した時の処理と常駐ステートでボタンの活性/非活性を同一FSM内で定義してました。

f:id:project-unknown:20170815231353p:plain


これを実行すると、以下みたいになります。

f:id:project-unknown:20170815231111g:plain

常駐ステートの方は動くのですが、ボタンクリックの方が検知してくれていない。

原因としては、以下の公式に記載されている通り、常駐ステートの位置付けは「割り込み」である為に、
ボタンよりも常に条件が合致する常駐ステートの方が優先して処理されてしまっていたと推察しています。

arbor.caitsithware.com

この件の対応としては、GameObjectに別なArbor FSMをアタッチして、新規に作成したFSMの方に常駐ステートを置いて想定通りの動作が実現できるようになりました。
↓な感じ

f:id:project-unknown:20170815231829p:plain


今日は簡単ですが、以上で。

written by ゆう@あんのうん

Unity Cloud Buildで、The name `クラス名' does not exist in the current contextでbuildエラーになった時の対処法

はじめに

本日は掲題の通り、Unity Cloud Buildで盛大にハマった事の、私なりの解決法をご紹介。

Unity Cloud BuildでiOS用にbuildすると、以下の様なエラーが発生してbuildが通りません。(該当箇所だけ抜粋しています)
以下は、UK_NumberUtilityというクラスが見当たらないとなっているのですが、Unity Editor上にもMonoDevelop上もちゃんとあるし、ローカルだと正常に実行できているからさっぱり原因が分からず詰んでしまいました。

19: [Unity] Assets/PatapataUnon/Scripts/Behavior/BehaviourUtil.cs(126,10): error CS0103: The name `UK_NumberUtility' does not exist in the current context

グーグル先生にも色々お尋ねしたのですが、ちゃんとした解決法が載っておらず…。

フォルダ名にLibraryを使っているのが原因

色々試行錯誤した結果は後述するとして、結論から先に書くとどうもフォルダ名にLibraryを使っているのが問題っぽいです。
該当するUK_NumberUtilityは以下のキャプチャの用に、「Scripts/Library/UK_NumberUtility」に配置していました。

(キャプチャは試行錯誤の過程でファイル名をNumberUtilitysにリネームしてます)
f:id:project-unknown:20170816124951p:plain

ここで、LibraryをLibrarysにリネームし、buildすると正常にbuildが通りました。

以下、試行錯誤でやったこと

単純に、愚痴りたいと言う意味で書いています。
どれも効果がなかったので、上述のLibraryをリネームすればOKだと思います。

呼び出しているClassをリネームして.meta周りで怒られた事があったので、別ファイルを生成してbuild

ClassをMonoDevelop上で、リネームした際にUnityEditorで何かアラートが出たことがあります(.metaがどうたら…覚えてない)。
なので、この際に.meta情報が欠損して、該当クラスのロードに失敗したかと思い、以下を実施。

  • 前のファイルは残したまま(コメントアウトだけした)
  • 別なファイル・クラスを生成して、メソッドだけコピー

結果 : エラー

呼び出し先のファイルを別ファイルにうつしてbuild

結果 : エラー

Scriptの呼び出し順を変更してみる

該当するクラスは、以下の用にMonoBehaviorを継承していないですし、呼び出し順とかは問題無いかもしれませんが、これもやってみました。

以下のExecution Orderを以下に設定
f:id:project-unknown:20170816125500p:plain

かなり優先度を上げたロードを実施するようにした。
f:id:project-unknown:20170816125634p:plain

結果 : エラー


結論

フォルダの階層を下ったとしても、予約されるものは使わないでおくに越したことないですね。
過去のディレクトリ構成の記事も一緒に更新しておきました。

project-unknown.hatenablog.com

written by ゆう@あんのうん