投稿記事

レオ 2023/10/14 20:23

Unity+Live2d(CubismSDK)+macでハマったこと

今日のテーマ

こんばんは!
すごく小さいことではあったのですが,Live2dをUnityで使ったときにはまったことがあったのでメモがてら書いておこうかなと思いました。
もしこれからLive2dを触るって方でMacを使っている方は要注意です。

環境

今回問題が起こったのは
M2MaxのMac(Apple Silicon)でUnity2021.3.16f1で
CubismSdkForUnity-4-r.7.unitypackageを導入しました。

SDKはこちら。
https://www.live2d.com/sdk/download/unity/

何が起こった?

Live2Dを導入する手順は公式さん通りで,Unityパッケージをプロジェクトに突っ込むだけです。本当に簡単なんでうれしいのですが,Windowsでうまく動いていたもののMacで同じリポジトリをGitから落として来たらエラーが発生。

Rebootしろって書いてるけど再起動しても状況変わらず。
SDKをImportするときになんかおかしくなったのか?と思ったけど,もう一度入れても差分は無し(当然エラーも健在)。

解決策

よく見たらdllがプラットフォーム設定に合ってないようなことが書かれてる。
dll....?

これか!


Live2D/Cubism/Plugins/macOS/Live2DCubismCore.bundle
というファイルがあり,Inspectorを見るとCPUの設定が。
M2ってIntelじゃなくてAppleSiliconなんですよね,,,これが悪そう。

ということで他の作業者がどのCPUかなんて考えたくはないので,ここをAnyCPUに変えてやりました。


そうしたらエラーが消えて,ちゃんとLive2dサンプルのPrefabが読み込めました!
これはKoharuちゃんだそうです。サンプルとは思えないくらいみんなサンプルのクオリティが高くて楽しくなっちゃいますね。


さいごに

複数人開発をしなくても,個人で開発しててWindowsとMacを行ったり来たりする人も少なくないと思います。
今回起こった事例は,そういう人の中で,MacがIntelじゃない場合で発生しちゃいます。
デフォルトでIntelにしてある理由は何かあるのかもしれませんが,今のところこれをAnyCPUにしても不具合っぽいものは見られないので,最初からそうしておいてほしいなぁと思いました。

それでは楽しい開発ライフを!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

レオ 2023/09/24 22:32

キーボード制作

今日のテーマ

プログラマーにとって欠かせないキーボード。
巷で噂のGrabshellというキーボードについて記事を見かけたので,
全然関係ないですが現在自分が組み立て中のキーボードについて途中経過を少しですが書こうと思います。


※写真: ファミ通さんより引用
ファミ通さんの記事はコチラ
これでプログラミングしようとは,,,思えないけど発想は面白い!

なに作ってるの?


※写真: 白銀ラボさんより引用

今自分は白銀ラボさんのKeyball61というキーボードを作っています。
完成したら写真のようになるらしく,Grabshellと同じようにキーボードとトラックボールが一体化したキーボードです。
完成したらすごく作業効率上がりそうなのと,デザインも他の人がまず間違いなくびっくりするだろう所が気に入って作りたい!となったものの,半年かけて追いかけてやっとキットを購入できました。

もしこれを今初めて知って,「欲しい!」となった方は
白銀ラボのヨーキースさんのXをフォローしたり,
キーボードショップの遊舎工房さんのDiscordサーバーに参加したりして頑張って追いかけてみてくださいw
最近は以前より量産体制が整ったのか,少し1回あたりの売り出し台数が増えて購入しやすくなっている気がします。

はんだづけムズイ



最初はこちらのPCB基板にはんだ付けを黙々としていくのですが,これが初心者にとってはかなりの鬼門,,,
パーツはめちゃくちゃ小さいし,そもそもはんだ付けが結構大変。
平日仕事終わりに1,2時間,数日かけてキリの良いところまで少しずつ進めるスタイルでやったので2週間くらいかかりました。

それが終わって,キースイッチを埋め込んだのがこちら。それっぽい!


...ですがこれをRemapというキーボードのプロファイルを書き込むサイトでテストした結果,かなりの数のキーが反応が悪かったり,そもそも反応しなかったり,,,
どうやらはんだ付けがうまくいっていないようです。

反応したら青くなるのですが,これを見る限り下の段はもはや全滅。
ちなみにこれは左手側で,右側は接続した瞬間に2列が青に変化。


え...?
押しっぱなしになってる・・・?


キースイッチを外しても状況は変わらず。
基本的にははんだ付けが失敗しているようですが,キースイッチの近くのはんだ付けがミスっていなくてもこういう状態になったりするようで,原因特定までにもかなり時間を費やしました...いつ終わるんだこれ><


ちなみに2列押しっぱなしになっている原因は,こちらのマイコンと呼ばれるパーツのはんだ付けをやり直したら解消されました。
初心者にはまるで理由は理解できませんが,まぁ解消できたのでヨシ!



やすり掛け

Keyball61を作るにあたって,マニュアルには180くらいの紙やすりを用意してくれって書かれています。
ガンプラみたいに,キーボードのフレームについては一部切り離して使う必要があるのですが,そこのやすり掛け用っぽいです。

ところがこの紙やすり,実はめちゃくちゃ酷使することになりました。
というのも,左手側のフレームはキースイッチがすんなりはまるのに
右手側のフレームは固いどころかまるではまってくれる気がしません。

最初パーツの組み立て順番がおかしいのかな,とキースイッチと基盤,フレームの順番をいろいろ入れ替えて試したりしてみたのですが,左手側がうまくいっているのでやっぱり合っていそうでした。

これはもしやフレームの穴が出荷時に想定されている幅以下になってしまっているのではないか,と思ったので右手側のフレームの穴を全部やすり掛けで削ることに。
体力と1時間くらい持っていかれました,,,,この日の作業はこれで終わりました(苦笑)


これからの話

紆余曲折あり,とにかく試行錯誤を繰り返して少しずつ完成しつつある(であろう)Keyball61君。
今後も,まだ反応してくれないキーについて手当たり次第にはんだ付けをやりなおしていく予定です。結構精神力使うので,気が向いたときにぼちぼちと。

まだまだ時間がかかりそうな予感がしますが,完成するが楽しみです!


というところで,ここまでにしようと思います。
ではではー

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

レオ 2023/08/26 20:46

Enumステート管理

はじめに

スマホアプリのときは、表示しているUIボタンとかがRaycastOnでイベント設定がされていれば押したときの挙動を紐づけるだけでいろいろできるので簡単ですが
コンシューマー,,,というかコントローラー操作を想定するとタップ以外でイベントを発火しないといけないのでちょっと手間です.

そこで,ベストプラクティスかはわかりませんが自分の場合最近こういう処理を書くことが多いです.

    enum TitleMenuState
    {
        Campaign,
        Config
    }

    Dictionary<TitleMenuState, IMenu> _stateDictionary;
    MenuState _state = MenuState.Top;
    IMenu current => _stateDictionary[state];

	// 1つ上のメニューボタンにフォーカス
    public void Decrement()
    {
        var beforeState = _state;
        int verticalIndex = (int)(_state - 1);
        if (verticalIndex < 0)
        {
            // ループさせるかどうかで処理かえる...
            _state = TitleMenuState.Campaign;
        }
        else
        {
            _state = (TitleMenuState)verticalIndex;
        }
    }

共通化を試みる

こういうif文をあっちこっちの画面でかくのはちょっと嫌だなぁと思ったので
ちょっとステートを管理するクラスを作ってみました.

Enumを使ったステート管理クラス

	public sealed class EnumState<TEnum> where TEnum : Enum
    {
        private Index _index;
        private Dictionary<int, TEnum> _dic;

        public EnumState(bool loop, TEnum currentEnum = default)
        {
            var values = Enum.GetValues(typeof(TEnum));
            _index = new(
                maxIndex: values.Length-1,
                loop: loop,
                currentIndex: Convert.ToInt32(currentEnum));

            _dic = new Dictionary<int, TEnum>(values.Length);
            int index = 0;
            foreach (TEnum value in values)
            {
                _dic[index] = value;
                index++;
            }
        }

        public TEnum Current => _dic[_index.CurrentIndex];
        
        public void SetIndex(TEnum target)
        {
            _index.SetIndex(Convert.ToInt32(target));
        }

        public bool CanDecrement()
        {
            return _index.CanDecrement();
        }

		// 略---
    }
    
  **  intをつかったIndex管理**
    public class Index
    {
        public int CurrentIndex { get; private set; }
        public int MaxIndex { get; private set; }
        private readonly bool _loop;

        public Index(int maxIndex, bool loop = true, int currentIndex = 0)
        {
            CurrentIndex = currentIndex;
            MaxIndex = maxIndex;
            _loop = loop;
        }
        
        // Indexを1減らす
        public bool TryDecrement()
        {
            if (CurrentIndex - 1 >= 0)
            {
                CurrentIndex--;
            }
            else if (_loop)
            {
                CurrentIndex = MaxIndex;
            }
            else
            {
                // デクリメント失敗
                return false;
            }

            return true;
        }
        
        // 略---
  	}

これを使った処理の例

これで少しは共通化して書きやすくなりました.

    IMenu current => _stateDictionary[state];
    _titleMenuVerticalState = new EnumState<TitleMenuState>(loop: false);

	public async UniTask TryCangeState()
    {
        if (_titleMenuVerticalState.CanDecrement())
        {
            // 減らす前にステートを抜ける処理とか
            await _current.OnEndAsync(ct);

            _titleMenuVerticalState.TryDecrement();

            // 次のステートを開始
            await _current.OnStartAsync(ct);
        }
    }

おわりに

自分で用意したステート用のEnumを使って処理分けするのを共通化するのって意外と面倒くさいことをしないといけないんだなーと思いました.

あとはIncrementとかをasyncにして,変更前と後でActionを登録しておいて勝手に呼ばれるようなObserver的な処理を追加してもいいかもしれませんね。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

レオ 2023/08/26 20:04

Ci-enアカウント作成しました!

ごあいさつ

みなさんこんにちは。

お仕事でプログラマーをしていますレオといいます。
主に趣味で行っているゲーム開発について,気が向いたときに書けたらいいなぁと思っています。

投稿した際には,もしゲーム開発にご興味あれば見ていただけると嬉しいです!


開発中タイトル

・縦スクロールシューティング【LittleBrave】

・協力型ノベルRPG【FANTA ONLINE】


お借りしている素材
七三ゆきのアトリエ
ゆうひな

・3Dシューティング【魔改造タンク!(仮名)】

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索