Lapis Lazuli

technical blog for web developer

【Unity】SQLiteがAndroidで更新されなくて困った話

久しぶりにゲーム制作をやったので、今回はその時にハマった事を。

ゲーム自体は某ノベルゲーなのですが、そのテキストや背景、BGMの情報を保存するのに都合が良かったのでSQLiteを使う事にしました。
スタンドアロンなゲームで特に通信はしないので、DB使おうと思ったらほぼSQLiteしか選択肢が無かったです。

仕組み

仕組みとしてはライブラリ経由でDBにアクセスして、一行ずつレコードを取ってくる仕組みになっています。
タップする度にselectしますが、内部DBだしまぁパフォーマンスは問題ないかなと思いこうしました。
チャプター毎に一気に取得するやり方もやってみたのですが、長い章だとメモリ使用量がかなり上がったのでやめました。
Webサーバーと違ってスケール出来ないですからね・・

プラグインをいれる

sqliteを使うにはプラットフォームに応じたプラグインを入れる必要があります。
プロジェクトのPlugin/Androidディレクトリにlibsqlite3.soを入れればいいのですが、ここで一つ問題が出てきました。
古い端末では動くのですが、新しめ(Android9搭載)の端末だと動かなかったのです。
どうやら調べていくとプラグインは64bitと32bitでわけないといけないらしく・・・公式から最新のプラグインを落として2つ入れる事で動くようになりました。
ちなみにaarパッケージでやるのが今風らしいのですが、上手く動かなかったので直接soファイルを配置する方法を選択しました。

DBが更新されない

ここまででAndroid端末でDBから取得が出来るようになったのですが、次にボイスが再生できないという問題にブチ当たりました。
最初は「メモリ的にキツいからかな?」と思ったのですが、取得するデータ量を減らしても問題なかったです(そもそもログに何もでていなかったので当然だが)
もしかしてDB更新されていないのでは・・・と思ってテキスト変更してみたら反映されていなくて当たりでした。

しかし原因は分かったけど、どうしてそうなるのかが不明なままでした。
キャッシュだろうなと思い、ライブラリの動作を追っても普通にstreamingAssetsからコピーしているだけで特に問題なし・・・
そもそもアンイストールしても残っているのでますます?でした。
ならばとDB名を変更して取得するようにすると、正常に反映されるようになりました。
その後、更新してもちゃんと反映されるようになったので、おそらくこれで問題ないはず。
原因はわからずじまいでしたが、ユーザーが触れない領域にキャッシュでもしていたのでしょうか。

最後に

そんな感じで苦労しながら作ったゲーム。無料で配信中です。
play.google.com

2021年の抱負

今年も終わりに近づいてきたので、去年に続き抱負の記事を書きます。
こうして振り返ってみるとブログも1年半くらい続いているんですよね・・・すぐ書かなくなるかなと思いましたが、習慣にすると続けられるものです。
この調子で2年、3年と続けていきたいですね。

ではまずは今年を振り返る事から。

転職先で新しい技術やポジションを経験することが出来た

間違いなく一番これがトピックとしては大きいですね。新職場になってから様々な事を経験しました。
主に以下の3点でしょうか。

  1. 規模の大きいサービスの運営ノウハウ
  2. AWSをガッツリ構築してのインフラ経験
  3. PLとしてのマネジメント仕事

まず、ある程度ユーザー数の多いサービスを触れたのは学びが大きかったです。
負荷のかかり方やDB回りのトランザクション、キャッシュの持ち方など、小規模だと気にしなくても問題ない箇所でも問題になってきます。
この部分はどうしても経験しづらいので、経験できてよかったなと思いました。
AWS経験もモダンなインフラ構築のノウハウを作る事が出来たので、今後のキャリア上でも武器となる事が出来ました。
PL経験は正直前任者がいなくなって流れ的にやることになったのですが、意外にトラブルもなく開発部の運用をすることが出来ました。
開発を誰がやるのか、チーム内の担当はどうするのか、オペレーションフローはどう構築するのか。など、色々な視点を得る事が出来ましたね。
初経験なのでもっと大変かと思っていたのですが、これも今後のキャリアを考える上で良い経験になりました。

副業を本格的に開始したこと

2つ目のトピックは副業を開始したことです。
本業で出来ない事をやろうとプログラミングメンターを2月からやり始めました。
最初はMENTAのプランで数千円程度でしたが、数ヶ月後には数万になりました。
そして、それをきっかけに某プログラミングスクールの講師の仕事を業務委託で請け負えたのは一番大きいです。
本格的に副業収入が伸びてきたので、これを軸にもっと大きくしていきたいですね。


今年は以上2つが今年のトピックでした。
去年の抱負とほぼ被っていますね。では次に来年の抱負を。

転職先でキャリアを積む

全く去年と同じことを書いていますがw実は2月から転職して別の会社でお世話になる予定です。
某メガベンチャーなのですが、キャリア的にも悪くないなと思って行くことにしました。
学ぶことを多いと思いますので、チームの力になっていけるよう頑張っていきます。

副業でも経験を積む

メンターもいいのですが、開発案件で実力を伸ばしていきたいなと考えています。
幸い新規開発案件を獲得できそうなので、副業から本業に活かせる経験を積んでいきたいと思っています。

アウトプットを継続してやっていく

ブログもそうですが、外部向けに発表したりとかもっと多角的な事をやっていきたいと思っています。が、まだ詳しい事までは決めていない形です。

ゲーム開発を続けてコンスタントにリリースしていく

2年前からやっているゲーム開発ですが、今年はリリース出来ないままでした・・・が、ちゃんと進捗はしているので来年春までにはリリース出来る予定です。
これも続けていきたいですね。やっぱり自分が作ったものが世に出るのは面白いので。



ということで今年はこんな感じでした。来年は新しい事というより今までの事をより高みにやっていく方向になりそうですね。
世間はコロナで大変ですが、来年は良い年になりますように。
それではまた2021年の更新で。

【Go】エラー処理にxerrorsを使う

Goでエラー処理する事は頻繁に出てくると思います。
使われるのは大体標準パッケージのerrorsを使う事が多いと思いますが、Goには準標準パッケージとしてxerrorsがあります。
最近使ってみたら良かったので、今回はxerrorsについて書いていきます。

何がメリットなのか

最大の違いはスタックトレース機能がついていることです。
errorsだと、どの関数のどの箇所で落ちたのかがログに残らないのがですが、xerrorsならこれが可能です。
ただ中身の機能的な部分を言うと、エラーをラッパーするだけならerrorsで問題ないので、使うか使わないかの判断基準はスタックトレースが必要かどうかに絞られます。

スタックトレースの使い方

ではまず普通に実行してみましょう。
ひとまずパッケージのインポートをして、簡単なエラーを返す関数を作成します。

package main

import(
    "golang.org/x/xerrors"
    "fmt"
)

func hoge() error {
    return xerrors.New("have error")
}
func main() {
    if err := hoge(); err != nil {
        fmt.Printf("%v", err)
    }
}

これを実行すると

have error

普通にエラー出力されました。
スタックトレースを機能をつけるには、出力部分を下記のようにします。

fmt.Printf("%+v", err)

これを実行すると下記のように発生箇所が分かるようになるので、エラーを追いやすくなります。

have error:main.hoge  /xerrors/sample/sample.go:11

errorsとxerrorsの関係

Go1.13以降はxerrorsの機能がerrorsに取り込まれた為、スタックトレース以外で使うメリットはほぼないです。
Unwrapなども追加されましたので。
それ以前の環境でやっているのなら意味ありますが、おそらく1.13に上げたほうが将来的なコードの保守性的に良いと思います。
ただし、問題がありそうなのは以前からxerrorsを使っていてerrorsに乗り換えるパターン。
fmt.Errorfで%wを使ってエラーのラッピングが出来るようになったが、xerrors.Errorfとは仕様が違ったりするので、そのまま移行するのは大変だったりします。
ほぼerrorsとfmtに機能が取り込まれた今、機能的に十分なら標準を使うべきですね。
その辺りは要件による形になります。