Unity+NCMBでiOSビルドしたときのどえりゃあエラー

Unityでビルドして、xcodeにいき、そこでビルドしたときに出るなんだかよくわからんエラー。ぞろぞろ出てくるもんだから とっても怖い。

Undefined symbols for architecture arm64:
  "_OBJC_CLASS_$_UNUserNotificationCenter", referenced from:
      objc-class-ref in NCMBAppControllerPushAdditions.o
  "_OBJC_CLASS_$_ASAuthorizationController", referenced from:
      objc-class-ref in NCMBAppleAuth.o
  "_OBJC_CLASS_$_ASAuthorizationAppleIDProvider", referenced from:
      objc-class-ref in NCMBAppleAuth.o
  "_ASAuthorizationScopeEmail", referenced from:
      -[NCMBAppleAuth loginWithAppleId:] in NCMBAppleAuth.o
  "_ASAuthorizationScopeFullName", referenced from:
      -[NCMBAppleAuth loginWithAppleId:] in NCMBAppleAuth.o
  "_OBJC_CLASS_$_WKWebView", referenced from:
      objc-class-ref in NCMBRichPushView.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

UnityFrameworkが不足しているだけである。

あわてず、+ をクリックし以下を追加する
WebKit.framework
UserNotifications.framework
AuthenticationServices.framework
そこまでやって、再度ビルドしよう。いちおうxcodeもクリーンして、再起動かましとこう。

Unityとニフクラ mobile backendでプッシュ通知の設定するまで、iOS編

特に迷わなかった。証明書.p12を書き出すときに間違ってパスワードを設定したくらいである。
ニフクラのドキュメントにきれいに書いてある。

念の為、ざっくりと手順だけかいておく。

1)Appleデベロッパーにアクセスして準備

https://developer.apple.com/にて
・「バンドル識別子」を使用します。
・証明書はめんどくさいので、本番用をいきなり作りました
・こちらにきれいに書いてある。

mBaaSとAPNsの連携に必要な設定
https://mbaas.nifcloud.com/doc/current/tutorial/push_setup_ios.html#gsc.tab=0

証明書を.p12形式に変換するとき、パスワードを設定しちゃいかんぞ

プッシュ通知の設定はiOSの方が簡単じゃのお

Unityとニフクラ mobile backendでプッシュ通知の設定するまで、Android編

ほんとさあ、プッシュ通知まじでめんどくさい。何がめんどくさいって最初がめんどくさい。ほんとめんどくさい。最初はFirebaseだけでやろうと思ったんだけど、どーもUnityでのビルドでひっかかってしまう。何が悪いかわからない。

そういうわけで、我らがニフクラでプッシュ通知を実装したので、以下手順を書く。Unity + ニフクラ + Firebaseということになる。挫折したひと、いると思うのよね。

つかうもの
1)Unity(プロジェクトつくっておく)
2)Firebaseを使う
3)ニフクラを使う

1)Unityでプロジェクト作る
 まず、Unityで適当なプロジェクトを作る。別になんでもよい。プロジェクトを作成したらビルド設定をひらき、プレイヤー設定をクリックして

バンドル識別子を設定しておく。

2)Firebaseの設定を行う
 プロジェクトを追加にて新しくプロジェクト追加する。

Unity アプリに Firebase を追加 にて、バンドル識別子を入力。iOS app にもプッシュ通知したいのでここにもバンドル識別子をいれる。もちろんAndroid appにもいれる。アプリのニックネームは適当に。

秘密鍵のダウンロードをする

google-services.json をダウンロードしておく(Android用)

GoogleService-Info.plist をダウンロードしておく(iOS用)

ここまでで、Firebaseの設定は終わります

3)ニフクラの設定
 プッシュ通知設定ファイルの選択 をクリックして、firebase上でダウンロードした秘密鍵をアップする

4)Unityの設定
 基本的にはニフクラのドキュメントに沿って行えば良い。以下、簡単に書いておく。

 1.NCMBのSDKをインポート。
 2.Prefabsフォルダ内の「NCMBManager」「NCMBSettings」をドラッグしてシーン直下へ。
 3.NCMBSettingsのUse Pushにチェックをいれる。
 4.google-services.jsonを配置する。(google-services.jsonは、プロジェクト内のAssets/Plugin/Android直下に配置。)
 5.アプリケーションキーとクライアントキーを入力。(アプリケーションキーとクライアントキーはニフクラからコピペ。)

5)ここまででいったん、ビルドしてAndroid端末にいれてみよう
 もしビルドエラーが出た場合、Unityを再起動する。どういう理屈なのかはわからないが、なんらかのSDKをインポートしたとき、ビルドでめっちゃエラーがでてくるときがある。

6)プッシュ通知をするためのコードを書く。
 PushObjectをいうゲームオブジェクトを作成し、PushObjectソースコードファイルをアタッチ。

コードは以下。
using UnityEngine;
using System.Collections;

/////////////////////////ここから追加コード////////////////////////
//SDKの利用を宣言
using NCMB;
/////////////////////////ここまで追加コード////////////////////////

using System.Collections.Generic;

public class PushObject : MonoBehaviour {

/////////////////////////ここから追加コード////////////////////////
    private static bool _isInitialized = false;

    /// <summary>
    ///イベントリスナーの登録
    /// </summary>
    void OnEnable()
    {
        NCMBManager.onRegistration += OnRegistration;
        NCMBManager.onNotificationReceived += OnNotificationReceived;
    }

    /// <summary>
    ///イベントリスナーの削除
    /// </summary>
    void OnDisable ()
    {
        NCMBManager.onRegistration -= OnRegistration;
        NCMBManager.onNotificationReceived -= OnNotificationReceived;
    }

    /// <summary>
    ///端末登録後のイベント
    /// </summary>
    void OnRegistration (string errorMessage)
    {
        if (errorMessage == null) {
            Debug.Log ("OnRegistrationSucceeded");
        } else {
            Debug.Log ("OnRegistrationFailed:" + errorMessage);
        }
    }

    /// <summary>
    ///メッセージ受信後のイベント
    /// </summary>
    void OnNotificationReceived(NCMBPushPayload payload)
    {
        Debug.Log("OnNotificationReceived");
    }

    /// <summary>
    ///シーンを跨いでGameObjectを利用する設定
    /// </summary>
    public virtual void Awake ()
    {
        if (!_isInitialized) {
            _isInitialized = true;
            DontDestroyOnLoad (this.gameObject);
        } else {
            Destroy (this.gameObject);
        }
    }


/////////////////////////ここまで追加コード////////////////////////

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

}

「Awake」内の処理、これを書くことでPushObjectが別のシーンに入っても生き続けることができる。OnEnable内の処理で端末をニフクラに登録することが可能となる。

 Unityをビルドし、端末で実行してみる。

 ニフクラのサーバー内にプッシュ通知をおくるべき端末が記録されていることを確認できる。

 あとは、ニフクラのプッシュ通知を使用してプッシュ通知をおくることが可能になる。

FireBaseでのエラー

原因不明だったのだが、なぜか治ってしまった。備忘録として書いておきたい。

経緯/
 Firebaseの公式サイトからSDKをダウンロードし、解凍してインポートした。目的はプッシュ通知である。ドキュメントのとおりに行う。
 しかし、ビルドエラーが乱立してしまった。キャプチャーを撮っていなかったが、JDK周りのエラーのようだった。Firebaseをインポートする前は普通にビルドできていたため、インポートしたファイルの何かが悪いというのはわかるのであるが、原因が探せなかった。

解決方法/
 Firebaseのドキュメントの中に、

iOS の場合 – [GoogleService-Info.plist をダウンロード]
Android の場合 – [google-services.json をダウンロード]

というのが存在した。この2つのファイル「GoogleService-Info.plist」「google-services.json」をUnityのAsset直下においておけ、とドキュメントに書いてある。自分はそのとおりにした。

 結論から言うと、この2つのファイル「GoogleService-Info.plist」「google-services.json」をAssetから外すことでビルドが通ってしまった。なぜかはわからない。

 再度2つのファイルをAsset直下にいれたら今度はビルドが通った。

 なぜかはわからない。誰かおしえてくれろ。

Unity DOTweenのプログラム例

以下に、DOTweenを使用したソースコード例をおいておく。シーケンス準備からコールバック、移動、などまで一通りまとめた。これで大体は事足りるだろう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

//トップページのロゴをびょーんとしたあとに無限にふわふわ動かす
public class TopRogoMove : MonoBehaviour
{

    //RectTransform指定。Getconponentは遅いんで極力つかわんことにする
    public RectTransform titleRogo;

    //アニメーションシーン
    private Sequence _myseq;
    private Sequence _myseq2;

    void Start()
    {

        //アニメーション、シーケンス準備
        _myseq = DOTween.Sequence();

        _myseq.AppendInterval(
            1.0f                            //待ち
        );

        //びよーん
        _myseq.Append(
            titleRogo.DOPunchScale(
                new Vector2(1.2f, 1.2f),    //scale1.5倍指定
                1.0f                        //アニメーション時間
            )
        );

        //数秒まつ
        _myseq.AppendInterval(
            1.0f                            //待ち
        ).AppendCallback(() => {            //コールバック設定、これをいれることで終わったあとに更に処理ができる

            //アニメーション、シーケンス準備、2つ目
            _myseq2 = DOTween.Sequence();

            //ふわふわ(ループ)
            _myseq2.Append(
                titleRogo.DOLocalMove(          //ローカル座標
                    new Vector2(0.0f, 150.0f),  //移動XY
                    2.0f                        //アニメーション時間
                )
                .SetEase(Ease.InOutBack)        //イージング指定
                .SetRelative()                  //いまいる場所から移動
            );

            _myseq2.AppendInterval(
                0.4f                            //待ち
            );

            _myseq2.Append(
                titleRogo.DOLocalMove(          //ローカル座標
                    new Vector2(0.0f, -150.0f), //移動XY
                    2.0f                        //アニメーション時間
                )
                .SetEase(Ease.InOutBack)        //イージング指定
                .SetRelative()                  //いまいる場所から移動
            );

            _myseq2.SetLoops(-1);               //-1は無限ループ

            //再生
            _myseq2.Play();

        });

        //再生
        _myseq.Play();

    }

    private void OnDisable()
    {
        //オブジェクトが破棄されるタイミングでTweenアニメーションもkillしておく
        if (DOTween.instance != null)
        {
            _myseq.Kill();
            _myseq2.Kill();
        }
    }

}

イージングの種類はこちらをよく参考にさせてもらっています。

Unity2Dでのスマホの解像度定番設定、Android、iOS(自分用)

現在、スマホはAndroid,iOSとたくさんの機種があり、解像度もたくさんあるので、なかなか定番の解像度を設定するのは難しい。

たくさんの技術者とか端末が一通り揃っていればいいんだろうけど、個人でやってるときは、そんなわけにはいかない。また、そこまでがっちりと求めれていない場合もある。

自分の定番設定をここに備忘録として残しておく。

前準備としてプラットフォームはAndroid。

そして、自動回転を許可する向きは縦向きのみとしておく。だいたいスマホはこの設定でいけるとおもう。横向きとかで作成したい場合は適時変更すること。

まずはCanvas。レンダーモードを「スクリーンスペース・オーバーレイ」に。Canvas Scaler のUIスケールモードを「画面サイズに拡大」。参照解像度をX=1080,Y=1920にする。多分これがキモですね。将来的にはこの数値が上がっていくんだろうと思う。でもいまのところはこれで十分のはず。

Canvasの中にPanelを入れる。

以降、さまざまな部品はこのPanel内に配置していくことになる。

Panelの設定、middle、centerを中心にする。幅と高さは自動的に1080×1920になっているはず。

以上の設定で、だいたいのスマホに対応できるはず。この解像度の比率はきちっと守られ、余白が出た場合はCameraの背景色が表示される。自分はここを黒にしておきます。

以上です。

自分はこの設定でだいたい作ってます。

Unityで課金するときのOptionsとやらの!について

Unityで課金するとき、Unity IAPなるものをつかうと簡単にできるらしか。じゃあってんで、さっそくUnity IAPをいれる。

サービスウインドでなんかおかしなやつが出現した。

うえのWelcomってのはわかる。多分こう、課金に関係するSDKっぽいものをインポートするぜ!っていうやつだよ。

ただ下のOptionsがわからん。なにこれ?ってなるよね。英語読んでみるとGoogle Play Developerからなんかパブリックキー持ってきて入れろ的なことかいてある。どこにあるのよそれ?ってなるけど、ここにあったよ。

Google Play Console のここにあったよ キーが。つまりこれをいれろってことでしょ?(これをいれることで何がどう特をするのかわからん。Unityで何の分析してくれるのかもわからん。)

でもね、これって、Unityからいれられないの。

ここにはいらないの。何度入れでもエラーんなる。なんでよ?

正解は、サイト上のUnity Dashboardから入れろですって奥さん。

わかるかッ!!

ああ いかんいかん。 自分がマニュアルをきちんと読んでないからよね。でも、普通にUnity側から入るって思わない?おれだけ?

CS0012

 うーん、なんかいきなりVisual Studio 2019(Mac)にて47個のエラー吐きやがった。コンパイルエラーなんだそうだが、いまいち 原因がわからない。

 Ultimate Mobile Proというアセットを使ってるんだけど、こいつがなんか邪魔しよるっぽい。
 Visual Studio 2019(Mac)を再起動したら治った。なんなんだ。

 なんか悔しい。

uGUIオブジェクトをタッチしてズリズリと(ドラッグ&ドロップ)で移動させる

 ボタンやら画像などをオブジェクトを自由な場所に移動させたいときがある。ドラッグのことね。

1)インスペクターにEventTriggerを追加
2)EventTriggerにDragを追加

 ここまでやったら、あとは(2)で追加したEventTriggerのDragにコードに書いたイベントをアタッチすればよい。
 ドラッグしたら呼ばれるイベントを作ると言う事ね。以下、そのイベント内の解説。

 まず以下のように親のオブジェクト情報を取得しておこう。親のオブジェクト(OyaPanel)内に自分自身のオブジェクトがいるていで。

タッチ位置の取得したいとき。

でとれるっぽい。だもんで以下のようにすれば TapPosにタッチしたとこの座標がはいる。

 あとは取得したTapPosにX座標とY座標はいってるから、それをつかって自分自身オブジェクトを移動させる。

 ちなみに、親のRectTransform状態でなんか計算が変わる?今回は「親のサイズを2で割ったものを加える」的なことをしてる。じゃないと変な位置に吹っ飛んでしまう。

 勘だけど親オブジェクトのRectTransformの設定によっては「親のサイズを2で割ったものを加える」的なことをしなくてよいかもね。
 この辺は、よくわからんかった。

 単純に座標いれるだけで解決したらわかりやすくていいのにさぁ。なんかタッチ座標はワールド座標だかららしいよ、よくわからんけども。

uGUIのタップ長押し

 ボタンを長押しすることで処理を変える、というのはよくあると思う。いろいろ探していたら以下のようなものを作ってらっしゃる方がいたので利用させていただいた。

UGuiLongPress
https://gist.github.com/WestHillApps/03e1d7a85856621c478b

 以下のUnityEventが宣言されているのでこれに

長押しした場合のイベントをアタッチする。ちなみに単タップのイベントも用意してある。

 あと長押しする時間帯、単タップとの差時間とかを設定する項目?があるが、自分はlongPressed=0.6に設定。差時間はdeff=3。

 この設定は作ってるアプリによっていろいろ違うだろうから、自分で実験するしかないだろう。

子ノードを一旦全て削除

 自分のノード内にある子オブジェクトを全部削除したいときに使う。

 スクロールパネル内にあるオブジェクトを全部消すときとか。一気にデストロイする、かっこいい響きねデストロイて。

//子ノードを一旦全て削除
foreach (Transform n in transform)
{
    Destroy(n.gameObject);
}

Unityのアセット買わずに自前でなんとかする人はマゾじゃなかろうか

 なんていうか、なんか「全部自分で把握」しないと気がすまんぜ的な人いるよね。アセット買わない人いるの、自前で全部やろうとする人。勉強のためにやってるならまだわかるんだけど。あれどういう精神状態なんだろ。マゾとしか思えん。


 悪いことは言わぬ。1000円、3000円くらいのアセットなら迷わず買って使え。そんで、そのアセットのコードを見て理解した方がいい。というかアセット使わない変態縛りする人は、もう最初からUnity使うんじゃない。

 Java、Swift使ってUnity使わずゼロベースからやっとけ。

SimpleSQL使ってるときの最新のDBファイルどこにあるのか問題(Mac編)

 SimpleSQLにおいてDBは「*.bytes」というファイルがDBのデータらしい。なんというか、このファイルにいろんなテーブルデータが入ってるみたい。

 このDBデータ(以下、test.bytesと呼ぶ)test.bytesは、最初は「DB Browser for SQLite」ソフトを使って作ることになる。適当にテーブル作ってtest.bytesファイルを出力、それをUnity上で使用することになる。

 ただ、Unity上に置いたtest.bytesファイルが常に更新されていくわけではないので注意。アプリ内でテーブルに対してデータのinsertやupdateなんかをしたとしても、Unity上のtest.bytesファイルは新しくならん。これを読むのは最初の最初だけのようだ。

 じゃあ、更新しまくられている最新のファイルはどこにあるのかというと、自分のMacだと以下の場所にあった。

 場所はここ(たぶんユーザーごと、それぞれで変わるべ)

Macintosh HD⁩ ▸ ⁨ユーザ⁩ ▸ ⁨<なんか自分の名前> ▸ ⁨ライブラリ⁩ ▸ ⁨Application Support⁩ ▸ ⁨DefaultCompany⁩ ▸ <なんかアプリの名前> ▸ test.bytes

 ここにおいてある「test.bytes」ファイルを「DB Browser for SQLite」とかのDB管理ソフトで読み込むと最新のテーブル情報が見れます。これを更新表示しつつ、アプリを作っていくといろいろ便利でよか。

 ちなみにアプリキャッシュクリアとかすると、ここのファイル消える。そんでまたゼロから新たに始めるため、Unity上においた「test.bytes」を読込する。こわーい。クリアこわーい。

 つまり、ユーザーがアプリキャッシュクリアしたら消えるというわけよ。

UnityでSQLite使うときはもう、アセットのSimpleSQL買っとけ

 無料のアセットとかあるけどさぁ、いろいろやったけどさぁ。SimpleSQLいちばん。


  4000円出して、SimpleSQL買っとけ。便利だし安定してるし4000円以上の価値ある。
 1から組むとかやめとけ、時間もったいねぇ。SQLマニアというのなら止めん。

SimpleSQL
https://assetstore.unity.com/packages/tools/integration/simplesql-38

SimpleSQL

UnityでSQLを利用するときはDB Browser for SQLite使っとけ

 UnityでSQLを利用したい。ちょっと大きめのプログラムになるとデータを管理するSQLをすぐ導入したほうがいい。

 最初はめんどくさいけど、やっぱりSQL入れた方がいい。SQLiteのことね。サーバーで動作する奴じゃなくて、アプリ内のみで動くスタンドアロン的なSQLね。SQLiteね。その管理DB用のPGはいろいろ使って見たんだけど以下が一番良かった。

DB Browser for SQLite
https://sqlitebrowser.org/

DB Browser for SQLite

シンプルだし使いやすかった。