カテゴリー: IDE・ツール・ライブラリ関連

うにのトゲは刺さると痛い(´・ω・`)-39

それほど必要でもなかったのだが、Unity上でMediaStoreとContentResolverを使って画像を取得する方法を調べて2~3日くらいを潰す…

未だにまともに画像表示出来ていないが50%くらい目的を果たせたので取り敢えず、その苦闘の記録を残すとする(ヽ'ω`)

正直な所、Javaでプラグインを書いた方が早いような気がする(ノ∀`)

※尚、以下のコードは色んなところから切り貼りしたり、適当に書いている為に、変数名等は統一されていないw


AndroidJavaClassとかってよくわからない(´・ω・`)

まず第一にAndroidJavaClassやAndroidJavaObjectや、そのメソッドの呼び出しであるCallやCallStaticがよくわからずに躓く…__○_
どうもReflectionみたいな感じでJavaのオブジェクトを扱ってるのかなぁ?って感じか。

習うよりも慣れろというか、コード実行の成功という或る種の成功体験、つまりは自己の環境に問題がなく、そのコードの内容が完全ではなくてもある程度のレベルで実行出来るという正当性を確認してからじゃないと、中々コードの内容の理解が進まない俺氏なので、色々とぐぐって試した。

他にも見たサイトやコードはあったような気もするけれど、比較的楽に動作を確認できたのが下の4つ。

アラートダイアログの表示
【Unity】Androidのネイティブの機能を使う

インテントでブラウザを開く
UnityC# で完結できるAndroidプラグインを簡単に作っちゃうぞ!☆ミ

インテントでギャラリーを開く? その他色々 5番目のコードだったかな?
在unity中如何高效的使用内置android方法

これは何か書き換えたんだったか間違えたんかわからないけど、JsonUtility.ToJsonが"{}"しか吐かなかったので、普通に文字列化した日時を書き込むように変更して試した。実機デバッグでファイルが書き込まれること、catで内容を確認した。
UnityでAndroidの内部ストレージにファイルを保存する


動作するコードを確認した結果、なんとなくはわかってきたような気がする。

AndroidJavaClassは完全限定名を渡してnewするものみたい。
どういう仕組かようわからんけど、newしてるけど扱いとしてインスタンスじゃなくてクラスなのかな?
メソッド呼び出しもCallStaticというStaticメソッドだし…

AndroidJavaObjectは普通のインスタンスとしてCallでメソッド呼び出しする。
最初のStringがメソッド名でそれ以降が可変長引数のobject配列らしい。
ここの処理もどうしてるのかよくわからない。

多分、基本的に下の2行は常にやる感じ?
UnityPlayerオブジェクトと現在のアクティビティ(つまりはコンテキスト)を取得してる模様。

AndroidJavaClass up = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject>("currentActivity");

関係ないが、完全限定名以外に正規名なんてのもあるのか(´・ω・`)
完全限定名と正規名とバイナリ名


ContentResolverやらMediaStoreで苦しむ

むかーし、Androidのページの翻訳もどきをちょこっとしてた時にContentProviderやContentResolverという言葉を目にしてたが、がっつりとそのクラスを使ったことがなかったので、色々と苦労した…(ヽ'ω`)

ContentResolver.query()等の抽出操作についての理解とそれをC#側から行う為の試行錯誤の為にえらく時間を要した…

最初に参考にしてたページ群で使用されていた画像系のcolumn名がAndroid10では使えなかったようで、それに気がつくまで時間がかかった…
何がいけないのかがわからなかったから(ノ∀`)

たまたま見かけた音楽系のタグを使用して、音楽タイトルの取得に成功した。
尚、このページの内容はよくわかっていないw
ロシア語は全くわからんw

参考?:
Плагин: сканирование устройства на наличие аудиофайлов

Unity完結での音楽タイトルの取得
    public void GetMusicMedia()
    {
        try
        {
            AndroidJavaClass up = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject>("currentActivity");
            AndroidJavaObject contentMusicUri = new AndroidJavaClass("android.provider.MediaStore$Audio$Media").GetStatic<AndroidJavaObject>("EXTERNAL_CONTENT_URI"); 
            AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver");
            AndroidJavaObject cursor = contentResolver.Call<AndroidJavaObject>("query", contentMusicUri, null, null, null);

            int titleColumn = cursor.Call<int>("getColumnIndex", "android.provider.MediaStore.Audio.Media.TITLE");

            while (cursor != null && cursor.Call<bool>("moveToNext"))
            {
                string m = cursor.Call<string>("getString", new object[] { titleColumn });
                Debug.Log("m:" + m);
            }

            if (cursor != null)
            {
                cursor.Call("close");
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError(ex.Message);
        }
    }
ImageのタイトルやIDの取得
public void GetPicMedia()
    {
        try
        {
            AndroidJavaClass up = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject>("currentActivity");
            AndroidJavaObject contentUri = new AndroidJavaClass("android.provider.MediaStore$Images$Media").GetStatic<AndroidJavaObject>("EXTERNAL_CONTENT_URI");
            AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver");

            AndroidJavaObject cursor = contentResolver.Call<AndroidJavaObject>("query", contentUri, null, null, null,null);


            int titleIndex = cursor.Call<int>("getColumnIndex", "android.provider.MediaStore.MediaColumns.Title");
            int IDIndex = cursor.Call<int>("getColumnIndex", "android.provider.MediaStore.MediaColumns._ID");
            while (cursor != null && cursor.Call<bool>("moveToNext"))
            {
              
                if (titleIndex != -1)
                {
                    Debug.Log("title:" + cursor.Call<string>("getString", new object[] { titleIndex }));
                }

                if (IDIndex != -1)
                {
                    Debug.Log("ID:" + cursor.Call<string>("getString", new object[] { IDIndex }));
                }

            }

            if (cursor != null)
            {
                cursor.Call("close");
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError(ex.Message);
        }
    }

EXTERNAL_CONTENT_URIの指定

ちなみにEXTERNAL_CONTENT_URIの指定でもはまった。
これはStack Overflowのページだったかどっかに書いてあったが、何処で見たかわからない(ノ∀`)
複数のページの情報を総合したのかもしれない。

AndroidJavaClass("android.provider.MediaStore$Audio$Media").GetStatic<AndroidJavaObject>("EXTERNAL_CONTENT_URI"); 

コラム名の取得

これはどんなcolumn名があるのか知りたくて調べたんだっけかな?
確かImageのDATAとかがDeprecatedで…

全cloumn名の取得
public void GetColumnsName()
    {
        try
        {
            AndroidJavaClass up = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject>("currentActivity");
            AndroidJavaObject contentImageUri = new AndroidJavaClass("android.provider.MediaStore$Images$Media").GetStatic<AndroidJavaObject>("EXTERNAL_CONTENT_URI"); 
            AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver");
            AndroidJavaObject cursor = contentResolver.Call<AndroidJavaObject>("query", contentImageUri, null, null, null, null);

            string[] colNames = cursor.Call<string[]>("getColumnNames");

            foreach(string colName in colNames)
            {
                Debug.Log("colName: " + colName);
            }

            if (cursor != null)
            {
                cursor.Call("close");
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError(ex.Message);
        }
    }

参考:
Android開発: ”ContentResolver” とは何者か?


enumの取得

AndroidJavaClass BitmapConfig = new AndroidJavaClass("android.graphics.Bitmap$Config");
AndroidJavaObject RGB_F16 = BitmapConfig.GetStatic<AndroidJavaObject>("RGBA_F16");

参考:
How to access enum in Unity AndroidJavaClass


上手く行かなかったもの

ContentResolverへ渡すprojectionを作る方法を探して試してみたが、なんか駄目だった(´・ω・`)
やり方を変えたら上手く行くかもしれないが、

まあ、全部取得しちゃってもよくね( ゜σ・゚)ホジホジ?

という高度な政治的判断により、掘り下げることをやめた(ノ∀`)

配列引数作成?
private AndroidJavaObject javaArrayFromCS(string[] values)
    {
        AndroidJavaClass arrayClass = new AndroidJavaClass("java.lang.reflect.Array");
        AndroidJavaObject arrayObject = arrayClass.CallStatic<AndroidJavaObject>("newInstance", new AndroidJavaClass("java.lang.String"), values.Length);
        for (int i = 0; i < values.Length; ++i)
        {
            arrayClass.CallStatic("set", arrayObject, i, new AndroidJavaObject("java.lang.String", values[i]));
        }

        return arrayObject;
    }

参考:
AndroidJavaObject.Call array passing error (Unity for Android)
Setting fields of an android java object from unity C#, including array


Bitmap => byte配列

immutableだかなんかとエラーが出たのでcopyをしたが、これが本当に正しい対処かどうかわからない。

AndroidJavaClass BitmapConfig = new AndroidJavaClass("android.graphics.Bitmap$Config");
AndroidJavaObject RGB_F16 = BitmapConfig.GetStatic<AndroidJavaObject>("RGBA_F16");
bitmap = bitmap.Call<AndroidJavaObject>("copy", RGB_F16,true);

Bitmapをbyte配列にする

これで一応Byte配列になるような感じなのだが、

AndroidJavaClass ByteBuffer = new AndroidJavaClass("java.nio.ByteBuffer");
AndroidJavaObject byteBuffer = ByteBuffer.CallStatic<AndroidJavaObject>("allocate", bitmap.Call<int>("getByteCount"));
bitmap.Call("copyPixelsToBuffer", byteBuffer);
byte[] bmparr = byteBuffer.Call<byte[]>("array");

その後、以下のようにしてTextureを作成して、

Texture2D texture = new Texture2D(width, height);
texture.LoadImage(bmparr);
texture.Apply();

TextureをSprite.CreateでスライトとしてImageに突っ込んで上手くいかなかった(ヽ'ω`)

なんか反転して、色が赤だけで他の部分は透過して描画されていたような…
もう少し頑張って駄目だったら、素直にJavaでプラグインを作るか…

つーかそもそも必須な機能じゃないんだよな、今調べてることってw

参考:
AndroidでのBitmap/JPEG/byte配列の相互変換


いちいち[デバッグ]メニューをクリックしてから[Unityデバッガーのアタッチ]をクリックするのがめどい(´・ω・`)

普通に設定で表示出来るのかなと思ったが、ちょっと一手間必要だった。
なんで「コマンドの追加」で選択する時の表示名が"Unityデバッガーのアタッチ"ではなくて"cmdldUnityAttach"なのだろうか。
わかりにくい(´・ω・`)

まあでもツールバー上に追加出来たので良しとする。

参考:
VisualStudio2019でUnityデバッガーのアタッチをツールバーに置く


調べ物に疲れてしまったのと日銭を稼ぎに行かないといけないので、しばらく更新は途絶えるかもしれない(ノ∀`)

うにのトゲは刺さると痛い(´・ω・`)-38

スコア用のdbを追加

いまひとつAndroid10での新規データ書き込みがわからず…(´・ω・`)

ぐぐったエントリ等で説明されていて問題ないはずのApplication.persistentDataPathで取れた"~/sdcard/0/~"みたいなパスでは書き込みを拒絶された。 ← 後でちょっと違う他のコードで試したら書き込めた(ノ∀`)ヨクワカラン

実機デバッグで確認したのだがなぜなんだぜ(´・ω・`)

なんかよくわからんのと今まで各ゲームモードでそれぞれ異なるjsonファイルを吐き出させていたのが余り美しくなかったので、取り敢えずsqlite経由でdbに書き込めるか試す。

でけた(・∀・)
というわけでscore.dbを新たに追加。


と書くと事もなくスムーズに行ったように聞こえるが、紆余曲折があった。半分くらいは自分由来のトラブルであったが(ノ∀`)

  • score.dbのレコードで、ユニークなプライマリーキーフィールドをどうするか悩む。唯一、string型のdatetimeがその条件を満たせなくもないが、あんまり宜しくない。(新規データ作成時に同一日時でデータ作成してたり、そもそもstring型をプライマリーキーにするのに何故か抵抗があったw)
    =>結果、AutoIncrement+PrimaryKeyのidフィールドを設定した。
  • 今までは古い10件のレコードをtempリストにコピー&現プレイ結果のレコード追加、pointの多寡で入れ替えて、上位10件を元のリストに戻すという風にやっていたのだが、score.dbのレコードでAutoIncrement+PrimaryKeyのidフィールドを設定してしまったので、ニューレコードだった場合にidをどうすればいいかわからなくなる(ノ∀`)
    => 結果、取り敢えずnullを入れればInsertは出来るとわかり、そうした。
    => 最終的に並び替えた一番最後(点数が低い)レコードのidを取得、レコードを順番になめていってidがnullのものがあったらidを代入して、UPDATE文を呼んでdb更新するようにした。
  • 当初、使ってるDataTableクラスがC#のSystem.Data.DataTableクラスだと思い、Copy()メソッドを使おうと思ったが、これはSQLiteUnityKit独自のクラスでCopy()メソッドを持ってなかった(ヽ'ω`)

    => 結果、 単純にRowsをコピーするメソッドとついでにリスト入れ替えメソッドを追加した。
    C# Listを自由に並び替える

  • 当初、StreamingAsset内のdbの中身を見て、「あれー、vsとeditor上では更新出来てるのに、dbの中身は変わってない…だと……( ;・´ω・`)ゴクリッ」と悩んだが、
    SQLiteUnityKitの挙動として、Application.persistentDataPathにdbをコピーして使用しているらしい。Windowsで言うと"C:\Users\ユーザー名\AppData\LocalLow\パッケージ名\ゲーム名"の下にdbがあり、きちんと更新されていた(ノ∀`)
    UnityでSQLiteを使用する方法

参考:
SQLiteで最も速く複数行INSERTする方法
Insert into … values ( SELECT … FROM … )

なんでUPDATE文だとINSERT文のようにフィールド名を最初に書くやり方が出来ないんだろうか(´・ω・`)?
まあ今回は一件のみの更新なのでいいんだけども。まあ対象が沢山ある場合は更新用SQL文を生成するメソッドを作ればいいのか。
SQLite3でデータを更新:UPDATE


何もしてないのにadmob関連が壊れた(・∀・)

なんかエラーが出るようになったので、resolverを使ったり再インポートしたけど、他には何もしてないのに壊れた(・∀・) ← やっぱりしてる

ぐぐる。

なんか以下の太字部分を削ると直るとか…

"Plugins/Android/GoogleMobileAdsPlugin.androidlib/AndroidManifest.xml");

[Unity] AndroidManifest.xml is missing. の対処法

なんかバグじゃなくて、フォルダ構造が変わっていて古いバージョンのadmobからアップグレードすると発生するとかどうとか…

This happened because you upgraded from an old version of admob.
From the version 5.2.0 the folder structure was changed.

Build Error. AndroidManifest.xml is missing. #1493

結論から言うと試してみても直らなかった(ノ∀`)

最終的にadmob絡みを全部削除して改めてUnityパッケージで入れたら解決した。


若干、呼び出すコードが変更されていたので書き換えた。
appidは"Assets\GoogleMobileAds\Resources\GoogleMobileAdsSettings.asset"のインスペクターで設定したけど、これでいいんだろうか?
editor上ではTestAdのバナーが表示されてるけど、実機だと出てきてないな…
まあこれは後回しでいいわ(・∀・)

参考:
バナー広告


bundletool

今回は実際の使用はほとんどしなかったけれども、aarからapkを生成したり、端末へと手動インストールする際に使用するものらしい…

bundletool
App Bundle対応


エミュレータ絡みで上手く行かない(´・ω・`)

なぜかうちの環境ではam64-v8a系のAVDを作成しても、"amdvlk64.dll"等のエラーで起動しない。
Can't change emulated performance of AVD in Android Studioにあるように、コマンドラインから起動したり、gpuとかのオプションをいじくったりしたが上手く行かず…(ヽ'ω`)

s86_64系のAVDは起動するけれども、Unity側でx86系でx86系用のサポートが選択できない…

Android サポートに関するお知らせ:64 ビット対応および App Bundle サポートの 2017.4 LTS バックポート

Unity では、Android の ARM 64 ビットサポートを追加した一方で、x86 ベースの Android の使用状況の調査も行いました。その結果、x86 ベース Android デバイスの市場への供給は非常に限られたものであり、Unity の x86 ベース Android サポートの導入も非常に狭い範囲に留まったことが分かりました。このため、x86 ベースの Android サポートはバージョン 2019.2 をもって廃止となり、Unity 2019.3 をもって完全に削除されます。

とあった…(ヽ'ω`)

セカンドPCに2019.1の環境を作ってなんとかしようとするも、今使っている2020.x系でC#8の記法等を利用しているために色々と書き直しの問題が……つーかプロジェクトのダウングレード時になんかエラーが出て先に進まない…_| ̄|○

取り敢えず、今の所諦めることにする。
今使ってるPCが第5世代のCore i5を積んでる古いPCだから駄目なのだろうか…
Hyper-VやHXAM辺りはきちんとやっているんだけども…


コードの改修はそれなりにしたけれども、特筆すべきことは少なく、いつも以上に内容のないエントリになったが、こういう日記的な作業内容を記録しておかないと後々苦労するので、怠らないようにしなければならない(`・ω・´)

うにのトゲは刺さると痛い(´・ω・`)-37

フォント変更

以前からずっと漢字の字体がおかしいなとは気づいてはいたが、面倒くさかったのでずっと放置していたのだが、ようやく重い腰を上げる。

が、フォントを読むがいまいちピンと来ない(´・ω・`)

Editor上で検索して一括指定、及び動的生成のTextに対してはその時に指定する感じにした。

一括変換するエディタ拡張とかも色々あったが、動的生成するTextの量が圧倒的だったので、あんまり恩恵を受けられないと思って取り敢えず手出しせず。

つーかなんでUnity側でそのプログラムで使用する基本フォントの指定が出来るようになってないんだろう。テキストが主体ではないゲームがメインターゲットだからだろうか?

実際に同梱するフォントはまだ決めていない(ノ∀`)


スコアのカウントアップをDOTween化した。

今まではUpdate()から呼び出していたカウント&テキスト更新する関数のその部分を前回のコードの感じでDOTween.To()に変更。

カウントアップ中のクリックでカウントを切り上げ最終結果画面に移行する部分は、DOTween.To()実行時にTweenerを受け取っておいて、Tweener.killを使う方向で書き換えた。

参考:
DOTweenのTweenerを使って途中終了、 一時停止、再開、リスタート【Unity】【DOTween】
[Unity][DoTween]DoTweenで調べまくって辿りついた いくつかの事

最終得点やnew recordの点滅もDOTweenにした。

参考:
【DOTween】Flashというイージングをちゃんと解説する
[Unity] DOTweenを使ってUI要素を点滅させる

……ハイスコア画面がなんかおかしい…だと……( ;・´ω・`)ゴクリッ
どうもAndroid10でのファイル保存の変更でファイルが保存出来なくなってる?
点数の格納方法を変えるか、そこを修正しないといかんみたいだな…(ヽ'ω`)


ボタンを押した時にOnGUI()でMousedownが行かないようにしたい(´・ω・`)

具体的に言うと、カードの裏返しと消滅を自動で処理しない設定の時にOnGUIでEventType.MouseDownを拾って裏返しと消滅処理を実行するようにしていたのだが、メニューボタンを押した時にもMousedownが拾われてしまう状況。

「まあ別にいいんじゃね ( ゜σ・゚)ホジホジ ?」と思わなくもなかったが、やはりきまりが悪いというか挙動的におかしい気がしたので、色々と試す。

最初はIPointerEnterHandlerIPointerExitHandlerを継承したスクリプトで各々の関数でフラグの立て伏せを行い、それを判定条件に追加してみた。デバッグした。
上手く行った(・∀・)

実機にデプロイした。実行した。
駄目だった…_| ̄|○

そうだった、マウスと違ってタッチの場合は必ずしもIPointerEnterが先に発生するわけではなかった…(ヽ'ω`)

その後もIPointerDownHandlerなどを試しても上手く行かず…

結局、メニューボタンのアンカーをトップレフトかなんかにしてピボットも0にしたりして、xを0、yを-heightにして、
ボタンのRect内にEvent.current.mousePositionが含まれているかどうかで判定という泥臭い感じに(ノ∀`)

もう少し綺麗な方法はないのか…
そもそもの書き方や設計が悪いのだろうか…(´・ω・`)
何はともあれ、一応解決したからいいか。

if (Event.current.type == EventType.MouseDown && !rtf.rect.Contains(Event.current.mousePosition))

UnityとかC#と関係ないが

上のコードをSyntaxHighlighter Evolvedで修飾表示させたら"&"が"&amp;"になった。
プラグインのバグということなのか、そういう仕様なのかわからないけれども、以下の関数を使ってるテーマのfunctions.phpに追加すればいいらしい。取り敢えず直ったので深く調べることはしない…そんな余力はない……(ヽ'ω`)

function kagg_syntaxhighlighter_precode( $code, $atts, $tag ) {
	if ( 'code' === $tag ) {
		$code = wp_specialchars_decode( $code, ENT_QUOTES );
	}
	return $code;
}
add_filter( 'syntaxhighlighter_precode', 'kagg_syntaxhighlighter_precode', 10, 3 );

参考:
SyntaxHighlighter Evolvedのブロックエディタで「&」が「&」になる問題の対応
Ampersand character


相変わらずの一進一退少女隊で中々やりたい部分まで到達しない…(ヽ'ω`)

うにのトゲは刺さると痛い(´・ω・`)-36 : DOTween絡み

今までのあらすじ

誰もやっていないので、神経衰弱ゲームはこのまま放置してしまってもいいかなと思わないこともなかったが、常用漢字データの追加だけは実装しておきたかったので、去年から断続的にデータ作成をする。
 ↓
音訓や部首のデータも追加したので、ちょっとプログラムをいじくろうと考えて久しぶりにMole's Match-upのコードを眺める。
 ↓
なんじゃい、この糞コードヽ(`Д´)ノ
 ↓
凄く読みにくくて、処理がよくわからない…(ヽ'ω`)
 ↓
致し方なく、リファクタリングしたり、大幅な改修をする。ちょっと前に読んでいたKotlin絡みの知識が役に立った。つーか今まで余りにもスマートな書き方を知らなすぎだっただけとも言う(ノ∀`)

Switch式便利(・∀・)
だけど値を返さなくていいSwitch式みたいなのはないのだろうか。
あとC#ってenumをsealedとか出来ないのか? 出来るのか?
まあswitch式でdefaultないと警告みたいのが表示されるので、キーッヽ(`Д´)ノってなりながら"_=>"を追加するのが嫌ってだけなのだけども。
 ↓
大分進んだけど、1月が終わってしまう…(ヽ'ω`)
 ↓
プレイ結果を表示する部分の改修をしつつ、なんか綺麗なコードじゃないなぁと思っていたところで、たまたま目にしたツイートでDoTweenの紹介をする動画(実は配信)があったので観てみる。

 ↓
DOCounterとかDoTextなんていう便利そうなのがあるやんけ(`・ω・´)
 ↓
そんなことしてる場合じゃないけど書き直してみるか(`・ω・´) ← イマココ


アセット管理

DoTweenを、つまりはアセットを最新にするのは自分で削除して追加しないといけないのかのぅ(ヽ'ω`)メドイ…と思っていたが、実はパッケージマネージャーのマイアセットから更新というかダウンロードと再インポートが出来ることを初めて知った(ノ∀`)
もしかして、これ結構前から出来たのかな?

Asset側に有る古いものをPluginフォルダの下に移してから更新すべきだったらしい…_| ̄|○
Unityを再起動したら二つDoTweenが有るとかどうとかで怒られた。
古い方を削除してPluginフォルダにあった方を再インポートしたが、特に問題はなさそうだ…

マイアセットからのアセット削除(?)はhttps://assetstore.unity.com/account/assetsに行って、対象のアセットを非表示にする感じでいいのかな?


俺氏、すっかりUnityの使い方を忘れる(ノ∀`)

上記の配信のプロジェクトってGithubにあるのかなと思ったが、ぱっと見、なかったようなので自分で環境というかプロジェクトを作ろうとする。

が、しかし…
余りにもUnity Editorでの操作が久しぶりだったために何をどうしたらいいかわからない(ノ∀`)

致し方なく、昔kindleで購入したUnityの寺子屋を見ながら設定等を始める。

[Mobile 2D]や[Mobile 3D]といったテンプレートが増えてる Σ(゚∀゚;)
でもまあダウンロードだけはしておいて、作成は従来通りの[2D]でしてから
Androidへプラットフォームを変更する。Canvas作ってカメラとかの設定を変えて、buttonを配置。

なんかようわからんけど、Textの代わりにTMP(TextMeshPro)が使えるだか使えとかいうようなダイアログが出たので言われるがままにダウンロードして使用する。

紆余曲折の果てに気づく…

DOCounterはPro Onlyやんけ…_| ̄|○


まあDoTween.To()を使って似たような挙動が出来たからいいか…(ヽ'ω`)
UpdateとかでCountupするよりは楽だし。

配置したButtonに追加するスクリプトは以下の通り。
もっと真っ当な書き方があるのだろうけれども、取り敢えず今の所は適当に。

参考:
DOTweenの使い方 Tweenアニメーション入門【Unity】
Unityでスクリプトからボタンのイベントリスナーを取り付ける


disp
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.EventSystems;
using DG.Tweening;

public class buttonTest : UIBehaviour,IPointerEnterHandler,IPointerExitHandler
{
private Button testButton;
private TextMeshProUGUI buttonText;
private Image buttonImage;
private Color baseTextColor;
private int points = 0;

void Start()
{
testButton = this.gameObject.GetComponentInParent<Button>();
buttonImage = testButton.GetComponentInChildren<Image>();
buttonText = testButton.GetComponentInChildren<TextMeshProUGUI>();


testButton.onClick.AddListener(OnClickButton);
buttonImage.fillAmount = 0;
baseTextColor = buttonText.color;

}

public void OnClickButton()
{
DOTween.To(() => points, (n) => {
points = n;
buttonText.SetText(points.ToString());
}, 1000, 1.0f)

.SetEase(Ease.Linear)
.OnStepComplete(() => {
this.gameObject.transform.DOScale(2f, 0.25f).OnComplete(() => {
this.gameObject.transform.DOScale(1f, 0.25f);
});

points = 0;
});
}

public void OnPointerEnter(PointerEventData eventData)
{
buttonImage.DOFillAmount(1f, 0.25f).SetEase(Ease.OutCubic).Play();
buttonText.DOColor(Color.black, 0.25f).Play();
}


public void OnPointerExit(PointerEventData eventData)
{
buttonImage.DOFillAmount(0f, 0.25f).SetEase(Ease.OutCubic).Play();
buttonText.DOColor(baseTextColor, 0.25f).Play();
}

}


adbによる実機での録画

adb shell screenrecord /sdcard/test.mp4

参考:
AndroidでPCからadbコマンドで動画・静止画キャプチャする

ポインタがないと何やってるかわからんなw


データ埋め込み表示文を作るのに凄まじい時間がかかった…(ヽ'ω`)
本当はkotlinとcompose辺りで上記のようなデータ埋め込み表示文を作る為のエディタのようなものを早く作りたいのだが、取り敢えずMole's Match-upの更新を済まさないと落ち着かないので、こっちを先に頑張るしかないな。

つーかそれよりも早く仕事を見つけないといかんな(´・ω・`)