白黒地帯

ゲームとか色々、Twitterに書ききれないことなど。

【Besiege】AutomationUtil(message一括変更mod)v0.1.0

steamcommunity.com

はい、ということでタイトルの通りBesiegeのmod作りました。
複数選択したすべてのブロックのすべてのmessageについて、最後の整数をインクリメント/デクリメントします。
と書くとややこしいですが、例えばup1というmessageがあったらインクリメントでup2に、デクリメントでup0になります。

多脚歩行機等でパーツをコピーした時に、そのままではmessageもまるまるコピーされているのでコピー元と同じ信号で動いてしまいますが、このmodでコピーしたパーツ全体を選択→インクリメント・デクリメントでmessageを変更することで素早く別のmessageを割り当てできます。

仰々しく書きましたがまだUndoすらない状態です。
自分の欲しい機能を作ったつもりなので使いながら調整やUndoの実装をしていきたいなと。

また、この機能のためだけのmodだとちょっと細かすぎるなと思いAutomationUtilという名前にしていることもあり、他の便利機能をつけたり、もう少しmessage変更の柔軟性を高めたいと思っています。
全て実装できるかはわかりませんがこんなのあればなあ、というのがあれば要望いただければ頑張って実装するかもしれません。

Besiege Mod作成について

大したものではないですがUnity知識ゼロからひーこら色々調べて作った結果
こうかなあと思ったこととか、作るにあたって参照したソースをメモも兼ねて書いておきます。
操作改善系などコードベースの場合の話なので多分コンテンツ追加系のmodを作りたい人には当てはまらないということと
自分の言及としてはまだあんまりまとまっていたり自信持って言える内容も多くはないので、余談的なものとして見ていただければと思います。


とりあえず以下のページの通り1回作るのが初めてのmod作成の近道な気がします!神…
w.atwiki.jp

自分はとりあえず細かいGUI設定は一旦なしにすることにしたので、「GUIの追加」までやってから他のソースをあたり始めました。
(GUIで色々設定を受け付けたい場合も、今はUIFactory等UI作りやすくするmod用mod等あるので、必ずしもブロックのUIを通す必要はない…かも?)

一通り作った後に、createmodとかcreateassemblyが何をしているのか知っておくといいかなと思います。
これはこちらの公式ページの方に記載されていますね。
mod.besiege.co.uk
ページとしてはこのあたり。
http://mod.besiege.co.uk/articles/ModDevelopment.html
http://mod.besiege.co.uk/articles/Code.html
ざっくりと、createmodはmodであるために必要な最小限の構成だけ(重要なのはMod.xml)を作成しますが、createassemblyはそこにさらにC#コードでmodを実装するためのプロジェクトファイルを作ってくれます。
コンテンツ追加系のmodだとcreateassemblyしなくてもmod作れるらしいのですが、自分のようなUtil系だと確実に必要かなと思います。

あとはやっぱり他のmodの中身を見てパク…学ぶのがいいと思います。
自分がやりたいことと似たことをしているmodならなおのこと近道ですしね。
wikiではILSpyが挙げられていますが、自分はdnSpyExを使っていました。
github.com
modに入ってるdllを左カラムにポイとドロップすればすぐに見られるお手軽さです。
BesiegeのフォルダのBesiege_Data/ManagedからAssembly-CSharp.dll(Besiegeバニラ)とUnityEngine.dll(Unity)のdllも持ってくると、ちゃんとmod内からの参照も辿れていい感じです。
操作はだいたい直感でできますが、1点だけ。あるクラスや変数の使用箇所は右クリック>Analyzeをして、下画面に出てるUsed by表示を転回して見ることができます。
なお、ワークショップでサブスクライブしたmod本体(dll等)はC:\Program Files (x86)\Steam\steamapps\workshop\content\346010フォルダにあります。

自分の場合は選択範囲の全てのブロックの操作はSelection Hiding、messageの編集はDefaultSettingModを参考にさせていただきました。
steamcommunity.com
steamcommunity.com

コントローラークラス・オブジェクトをどのように持つか

ここまで書いておいて、一番情報があんまりなくて難しいのが「どうやって処理のメイン動作部をスタートさせるか」かもと思います。
wikiの通りであればここ

 			// modゲームオブジェクトを初期化し、GUI等で使うクラスのインスタンスを子に指定する。
 			mod = new GameObject("WikiTutorialController");
 			SingleInstance<Gui>.Instance.transform.parent = mod.transform;

の通りコントローラーオブジェクトはSingleInstanceでアクセスと同時にオブジェクト化されて、親をmodのメインのGameObjectにする、でいいのですが。
他のmod覗くと色々やり方があるんですよね。
自分はdagriefaa氏を真似して、Unityスクリプトクラス(=MonoBehavior継承クラス)をメインのGameObjectにAddComponentで追加、にしています。
以下のページの2個目の方法ですね。
scrapbox.io
※dagriefaa氏:ColliderscopeやBlock Scaling Tools等数多のmodの製作者。すごいmodder。

違いがあるかというと自分にはまだわかりません…
ただ、Besiegeやmodに限らず、Unityで「ゲームオブジェクトにスクリプトを追加する」という操作は、MonoBehavior継承クラスを作ってGameObjectにAddComponentする形でするようなので、AddComponent使うほうがよりUnity向けのスタンダードな書き方に近いのかな…と思ってこちらにしています。
自分ももともとC#はやってましたがUnity開発経験は無で、GameObjectって何!?から始まったのでほぼ素人考えではありますが…

なお、何の子にもしないGameObjectを1つのmodでたくさん作ると、Object Explorerで見る時に大変なのでやめてください。
…ってfandom wikiに書いてありました。
besiege.fandom.com
(Keeping Objects Organisedのところ)
(このページの著者もdagriefaa氏)

Object Explorerはmodで、シーン中のブロックやら裏のコントローラーオブジェクトやらなんやらを全て一覧できる大変勉強になるものです。
mod制作勉強の際は一度除いてみることをおすすめします。
steamcommunity.com
当然なのですが、Object Explorerでは他modの作ったオブジェクトも見えてしまうので、あまりにもmodの余計なオブジェクトが多いと目的のものを探しにくくなってしまいます。
親子構造をツリー形式で見る形なので、1つのmodのコンテンツが1つのオブジェクト下に収まっているのであれば邪魔になりません。
ということでmodでコントローラーオブジェクトが必要な場合はAddComponentでスクリプトの追加やGameObjectの親子設定を使おうね…となるわけですね。

さらに自分が作ったmodは同じGameObjectを参照するようにすると、細かいmodをたくさん作っても1つのオブジェクト下にまとめられてユーザーに優しいです。
実際dagriefaa氏はdagriefaa's toolboxという形で細かな便利modを複数出しているのですが、それらはまさに上記ページに書いてあるとおり"ModControllerObject"という同じGameObjectの下に追加されているようです。
(存在チェックが挟まっており、すでに存在する場合はそれを使うことでロード順やmod数に関わらず同じGameObjectを使っています)
自分もたくさんmodを作るかはわからないのですが、将来的なことも考えてこの1つのGameObjectを参照する方式にしています。

おわりに

mod告知だけにしようかと思ったんですが雑多なmod制作メモも付きました。
後から分けてもいいかな。とりあえず置いておきます。