おもちゃバコ

中身スカスカ♡

「スクリプト言語による効率的ゲーム開発 C/C++へのLua組み込み実践」を読んだ

ちは

スクリプト言語による効率的ゲーム開発 C/C++へのLua組み込み実践」を読んだ感想,レビュー,備忘録です。


Amazon

改訂版です。

自分が読んだのはこっち。
2008年10月7日の初版でした。

読み始めた経緯

就活が終わって暇な時期に,RPGでよく使われるLuaについて知りたくてAmazonで中古で買いました。

買って満足して放置してたけど,本棚の整理と積み本消化を兼ねて読みました。

対象

  • RPGを本格的に作りたいけど,会話関係をどうしたいかわからない人。
  • ソースコードにゲームのパラメータを直書きしている人。
  • LuaC/C++連携を知りたい人。
  • 実践的なゲーム開発スキルを身に着けたい人。
  • 開発速度の改善を図りたい人。
  • コンシューマゲームを開発することが決まった学生。
  • luaを内製エンジンに取り込みたいけどやり方がわからない人。

内容は古く,UnityやUE4などのゲームエンジンが蔓延る現代で必要かと言われると答えづらいですが, コンシューマゲーム開発にはLuaC/C++連携は今でも必要な知識だと思います。

エンジン開発やスクリプト導入したい人は読んでおいて損はないはず。

後はUnityなどでも利用されているみたいなので,ゲーム開発者でLuaを知らない人は読む価値は十分にあると思いました。

参考
執筆時点(20220717)では,まだCEDEC2022で発表されていませんがソーシャルゲームでも使われていますね。
cedec.cesa.or.jp

DQXやFFXIVでも使われているみたいですね。
atmarkit.itmedia.co.jp
game.watch.impress.co.jp

本書では,WoWやシムシティラグナロクオンライン,ナイツなどが紹介されていました。

2022/12/25: C++Luaの連携について書きました。 良かったら読んでね。
lambda00.hatenablog.com

注意

サンプルコードの公開は終了していたので,基本的には独学になると思います。
(執筆時点: 20220717)

まあ,C/C++Lua連携の参考として読むのが良いと思います。
www.sbcr.jp


メモ

第1章 ゲームの開発速度は十分ですか?

スクリプト言語の必要性についてがメイン。
・「敵の速度パラメータを5.0fから6.0fにして...」とか「10フレーム以内にウィンドウを出して…」とかをプログラマが逐一修正して,ビルドしてからプランナに確認してもらうのは無駄だよねって話。
 ゲームに限った話じゃないけど,細かな修正によって製品の品質は左右されるので修正の繰り返しは仕方がないよね。
 でも,プログラマでなくてもこの修正は出来るよねって話かな。
・プログラム修正のサイクルは「コーディング」,「ビルド」,「修正箇所に移動」,「結果確認」の4工程。
 ビルドが30秒かかると,細かな修正の度に30秒失うのは馬鹿にはできない。
 けど,良ゲーがクソゲーにもなり得るから妥協はしたくない。
・ビルド時間はプログラマが働いていない時間。
 これはマジでそう。
 大規模になると1つの修正にソースコードの依存関係から1分待つとかザラにある。
 C++テンプレートは結構時間かかるよね。
 distccやIncrediBuildで並列コンパイルするよねとかも書いてあった。
・ゲームに詳細な仕様書が存在しない。
 これもあるあるだよね。
 業務システム開発とゲーム開発の決定的な違いは,作ってみるまで面白いかはわからないこと。
 つまり,作る前から詳細に仕様書を作成しても没になるかもしれないから作りづらいってことでもあるね。
 (なるべく詳細な方がいいけど。。。。)

第2章 ゲーム開発をスピードアップする

スクリプト言語とは。
・ロジックとデータの分離。
 move(x, y)て関数を考えるとmove(10, 20)てハードコードするのはダメだよね。
 最低でもデータファイルなどにパラメータをまとめて,参照するようにしようね。
スクリプト言語
 スクリプトを組み込んだプログラムからすれば,スクリプトは「データのように扱えるロジック」に見える。
 RPGならイベント制御,SLGなら思考ルーチンとかのロジックをデータ化できるよ考えると凄さがわかるはず。
・オレオレスクリプト言語
 用途: シナリオ面の演出や分岐の表現など。
 メリット: 用途に適した実装が可能。
 デメリット: 言語処理系の独自開発コスト,公開ツールをそのまま使えないなど。
 後は,そのゲーム開発にしか役に立たないとかかね。
・汎用スクリプト言語
 LuaPythonとか。
 メリット: 高度な言語機能が多く,開発効率が高い。豊富なドキュメントなど。
 デメリット: 汎用故の速度やリソースが使用用途に合わないなど。
スクリプト言語による高速化。
 スクリプト言語はデータとも考えられるので,プログラム実行中にリロードが出来るよねって話。
・何をスクリプトにすべきか。
 ・敵キャラのAI部分。
 ・UI定義や動作調整。
 ・シーン遷移。
 ・ゲーム勝敗条件のチェック。
 など,たくさんあるけど要は「高速性を要求される以外ほとんど」と言えるかも。
 速度が気になるなら後でC/C++で置き換えればいいし,とりあえず開発速度重視でスクリプトで開発するのはいいかも。

第3章 スクリプト言語の選択

スクリプト言語の位置づけなどについて。
・ライセンス。
 無視したいけど,無視できない要素だよね。
・動作環境。
 ターゲットとするデバイスで動作しないなら意味ないしね。
・メモリ管理機構。
 プログラム終了せずにリロード出来るけど,雑に作るとメモリリークするから気を付けようね。
 マーク&スウィープ方式とリファレンスカウント方式の2つに大別される。
 さらに進化したインクリメンタルGCや世代別GCといった手法もあるよ。
・速度。
 C/C++よ比較するとかなり遅いかもよ。
 特にメモリ管理速度は重要だよ。
・バインド機能。
 C/C++の関数をスクリプトから呼べるようにする作業をバインドすると表現する。
 この作業は大変だからなるべく自動化したいね。
・リロード機能。
 実行時に動的ロード出来るか。
 実行時に関数やクラスを再定義出来るかが焦点。
・メモリ消費や安定性,記述性。
 そらそうよって話。
スクリプト言語の候補。
 Lua, Squirrel, Python, PAWN, Ruby, GOAL,
 AngelCode Scripting Library "AngelScript", GameMonkey Script,
 Xtal, CRI Script, Io, Erlangなど。
 詳細は本書に書いてあるから気になったら読んでね。
 ゲーム向けではLuaが強い。

第4章 スクリプト言語 Lua

基本的なLua文法の解説がメイン。
気になったとこだけメモ。
・Virtual Machineとは。
 他のOSを動かすものではなく,ここではLuaスクリプトを実行するエンジン部分のこと。
グローバル変数とローカル変数。
 変数前にlocalをつけるとローカル変数。
 do~endなどのブロックも意識しようね。
・ブロックコメント。
 --で挟む。
三項演算子

x = a and b or c

・配列に穴があると動作は未定義。
 配列の途中でnilがあるなど。

第5章 LuaC/C++プログラムに組み込む

本書のメイン。
Lua C API
 Lua標準で用意されてる機能。

// LuaのVMを生成。  
lua_State *L = lua_open();
// Luaの標準ライブラリを開く。
luaL_opemlibs(L);
// Luaスクリプト実行。
luaL_dostring(L, "print('Luaだよ!')");

・スタック。
 Lua VM内の値とC/C++の値のやりとりはスタックを使用する。
 スタックはLuaの管理する領域の内側ということを意識しようね。
・tolua++
 C/C++の各種要素をLuaから使えるようにするためのグルーコードを自動生成するツール。
 MITライセンスらしい。

第6章 プログラムを止めない開発環境を作る

リロードするときのエラー処理などのお作法について。
・リロードと言語要素との相性。
 関数は◎,変数は△,クラスは〇。
 AIは〇,GUI周りは◎,グラフィックエンジンは△。
 グラフィックエフェクトは◎,シナリオは◎。
 ゲームのコア部分は〇,デバッグ用は◎。
 まあ,何となくわかるよね。
スクリプトでもDRYの原則。
 そうだね。

第7章 ゲームシステムを作る

RTSを作りながら実際にLuaC/C++連携を体感する会。
・描画などのややこしい部分はC/C++がお勧め。
 スクリプトはゲーム構成の上位概念を担当するのが良さそう。
 ようは,低レイヤーっぽいところはスクリプトはノータッチ(がいいかも)。
・コルーチン。
 協調的マルチスレッドを実現する機能。
 OSのマルチスレッドと似てるが,適用範囲が結構違う。
 比較的簡単で,雑な理解でもどうにかなる気がする(体験談)。

第8章 「ゴチャキャラ」ゲームを作る

前章の続き。
SDLとOpenGL2系の解説もちょいちょいあるが,現代(20220718時点)では流石に古いかな。
でも,ゲーム開発を流れを理解するという点では何も問題ないはず。

第9章 スクリプト採用への疑問に答える

割と本書のメインコンテンツな気がする。
スクリプトの速度。
 C/C++と比較すると遅いのは事実(20220718時点)。
 詳細は省くけど,代入から関数呼び出しなどの速度まとめの表がある。
グローバル変数よりローカル変数のほうが速い。
 グローバル変数は1つのテーブルなので,テーブルから検索処理を行うから遅い。
 ローカル変数は,VM上の非常に高速に取り出せる領域に置かれるから速い。
・文字列連結は最低限に。
 Luaは新しい内容の文字列が扱われると,それを新しいオブジェクトとして扱う。
 この時,ハッシュ値をセットして管理するため遅くなる。
スクリプトコンパイルはゲームループでは行わない。
 まあ,そうだよね。
 イベントハンドラ経由がいいかもね。
スクリプトからC/C++言語への置き換え。
 スクリプトで書いて遅いと感じた時にC/C++に置き換える。
 UE4とかでも同じ考え方があるよね。
・メモリアロケーション
 スクリプト言語は動的メモリ確保が基本条件の1つ。
 ゲーム開発に付き物のフラグメンテーションとの戦い。
 プレステとかだと結構気になるよねって書いてあるけど,現代だとそんなに気にしなくても良い気がするね。
ガベージコレクション
 マーク&スウィープ方式: 循環参照に強いけど,GCが開始するとスクリプトが停止する。
 インクリメンタルGC方式: リアルタイム用途に適しているが,制御がやや難しい。
・世代別GC方式。
 Luaでは採用されてないらしいけど,比較的有名らしい。
 最近確保されたメモリに対して,マーク&スウィープ方式を適用するイメージ。
・リファレンスカウント方式。
 オブジェクトに参照カウンタを持たせる方式。
 割と一般的な気がする。

付録A Lua C API リファレンス。

付録B tolua++リファレンス。

省略。


感想

既にC/C++Luaを頻繁に使っているのでメモする箇所が少なかったですが,Luaについて曖昧だった点が明確になった気がします。
購入した学生の時に読んでおけばよかったな~と思う1冊でした。

C/C++Luaの連携やLuaについて詳しく知りたい人は読むと幸せになれると思います。
所々でプレステ2の話などがあって,時代を感じました。

初心者の.vimrc

こんちは

何となくvimrcを晒します。
vimは初心者なので多めに見てね…


関連記事

こっちも見てね。
lambda00.hatenablog.com

参考文献

vimrcを書くにあたって以下の記事を参考にしました。
vim-jp.org
www.soum.co.jp
vim-jp.org
qiita.com
wonderwall.hatenablog.com
www.lecu1012.com

vim

vimのバージョン。
msys2のものを使用しています。

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Nov 22 2021 19:31:05)
Included patches: 1-3582
Compiled by <https://www.msys2.org/>

とりあえず晒してみる

基本的にプラグインとかは使用せず,vimの標準機能のみです。
多分コピペしても動くはず。

コメント有り版

流石に解説なしだとアレなので,コメントを足してみた。

noremapで.h/.cppを切り替えるヤツがありますが,使わない人は抜いてください。


vim戦闘力

vim戦闘力は57でした。
初級者にもなれない初心者です。
vim-jp.org


まとめ

プラグインを入れないにしても,もう少しvimrcを改造したいね。

次はVisual StudioVisual Studio Code用のvimrcを作る。

「実践Vim 思考のスピードで編集しよう!」を読んだ

こんにちは
最近,夜お家に帰ると室温が40℃でヤバいです。

「実践Vim 思考のスピードで編集しよう!」を読んだ備忘録です。
紙は絶版(?)で高かったので,Kindle版で読みました。


Amazon

Kindleのダークモードで読むと,ハイライトの文字が全く見えなかったので注意ね。

おススメな人

・素のVimを使いこなしたい人。
Vim入門したいけど,取っ掛かりが欲しい人。
 (セキュリティの関係で素のVimを使う必要のある人は多いはず...)
Vimをなんとなく使ってて,本格的に使いこなしたい人。
・hjklでファイル内を移動している人。
 (自分もこの本を読むまではhjklで移動していました...)

プラグインマシマシウェイしたい人はあまりおススメできないかも.

自分のVimレベル

hjklと検索,画面分割など,基本的なことぐらいしかできない.
ちょっと高度なことをやろうとするとすぐ調べる.

この本のおかげでVim初級者に成れた気がする…!

備考

メモの中で出てくるvimプラグインのバージョン。
(自分が勝手に書いてるだけで,本の内容とは関係ないです。)

VSCode

名前: Vim
ID: vscodevim.vim
説明: Vim emulation for Visual Studio Code
バージョン: 1.23.1
パブリッシャー: vscodevim
VS Marketplace リンク: https://marketplace.visualstudio.com/items?itemName=vscodevim.vim


メモ

実質,チートシートになってるかも。
かなり雑メモなので,気になった人は購入してしっかり読んでね。

序文

この本の読み方や考え方について。
レシピ本なので,最初から最後まで読み進める内容では無いよ的なことが書かれてます。
Vimを学ぶ前にタッチタイプは出来るようにしようね。
この本を読むときは,GVimVimどっちを使ってもいいよ。

$ vim -u NONE -N
「-u NONE」フラグは,vimrcを読み込ませないことやプラグインを無効化する。
「-N」フラグは,nocomaptibleオプション(vi互換ではなくvimのデフォルト設定)を適用する。
つまり,バニラvimを立ち上げるってこと。

第1章 Vimのやり方

ドットコマンドは神ということ。

.
ドットコマンド。直前に行った内容を繰り返す。
これをいかに使いこなすかで,タイプ量が変わります(実感しました)。

?
前方検索(/)の後方検索版。

*
カーソル上の単語を検索する。
検索(/や?など)を使用する手間が不要。

cw
カーソル上の単語を削除して,挿入モードへ。

第1部 モード

第2章 ノーマルモード

Vimを初めて使用したときに,多分テンパるだろうモード。
できる限り変更は繰り返し可能なものとする習慣を身に着けると,Vimが報いてくれるぞ!

u
アンドゥ。
単位は「挿入モードからノーマルモードに戻るまでの間に入力した変更」。
アンドゥ単位を意識すると便利。
手が止まるなら挿入モードから抜けるなど,中断セーブ的に扱うといいかもね。

<C-a>
数値の加算を行う。10<C-a>で+10など。 減算は<C-x>。
C言語などと同じで8進数などをVimは認識する(「set nrformats =」で10進数認識)。

dap
d{motion}の一種。pでパラグラフ指定。

g~
大文字小文字の入れ替え。
guとgUだね。

オペレータ待機モード
dwコマンドを使う場合,dとwの間にあるモード。

第3章 挿入モード

いわゆる一般的なエディタとしての機能。
<C-h>などを使いこなせるとモード切替不要かつ,手の移動も少なくできるかもね。

<C-h>
挿入モードで直前の1文字を削除(BackSpaceと同等)。

<C-w>
挿入モードで直前の1単語を削除。

<C-u>
挿入モードで行頭まで削除。

<C-[>
が信念上使えない人用(嘘)。

<C-o>
挿入モードで挿入ノーマルモードに切り替え。
(Visual Studioで<C-k><C-o>を酷使する自分は,キーバインドの悩みどころ。)

zz
画面再描画とカーソル行を中央に移動。

Caps Lockキーの再マッピング
CapsLockをキーに割り当てるべきかの議論。
Emacsでもたびたび上がるよね。

<C-r>{register}
挿入モードでレジスタの内容をペースト。

<C-r>=
挿入モードでExpressionレジスタを呼び出す。
<C-r>=33*4で134が挿入される。

<C-v>{code}
挿入モードで指定文字コードを挿入。
<C-v>u{code}で16進数指定。

ga
カーソル上の文字コードを表示。

<C-k>{char1}{char2}
挿入モードでダイグラフを入力。
<C-k>12で½など。

R
置換モード。と同じ。
gRで仮想置換モード。

第4章 ビジュアルモード

V
行指定。

<C-v>
ブロック指定。

gv
直前のビジュアルモード範囲を再選択。

o
ビジュアルモードで始点と終点をトグル。

第5章 コマンドラインモード

:で始まるモード。

GUICUIのどちらでVimを使うかの議論も書かれてる。
シェルをVimで利用したいならCUI一択。
(ちなみに,サスペンド(Ctrl-z)についても言及されてる。)

:h vi-differences
viとvimは違うものです。間違えないようにしましょう。

:{num1},{num2}p
{num1}行と{num2}行の範囲を表示。

:/{pattern1}/{offset1},/{pattern2}/{offset2}p
{pattern1}と{pattern2}の範囲を表示。
{offset}に+1とか指定できて超便利。

<C-r><C-w>
コマンドモードでカーソル上の単語をコマンドラインプロンプトに挿入。

set history={num}
Exコマンド履歴保持数を変更。

q:
コマンドラインウィンドウ表示。

第2部 ファイル

第6章 複数ファイルの管理

:ls
メモリに読み込まれてる全バッファを表示。
:bnextなどで移動。

<C-w>s
水平分割。<C-w>vで垂直分割。
<C-w>wと<C-h,j,k,l>で画面移動。
<C-c>と<C-o>で閉じる。

:lcd {path}
現在のウィンドウごとに作業ディレクトリを設定。

<C-w>T
タブ移動。

第7章 ファイルのオープンとディスクへの保存

:set path+=**/**
パスを追加する。
:findでファイルを開きたいときによく使う印象。

netrw
Vimのネイティブファイルエクスプローラー。
set nocompatible
filetype plugin on
の記述が必要。

<C-^>
代替ファイルを編集する。
大抵は1つ前に編集してたファイルのはず?

<C-g>
現在のファイル名をエコーする。

第3部 スピードアップ

懺悔: ここを読むまではhjkl移動してました。

第8章 モーションによるファイル内の移動

h,j,k,l
お馴染み。昔のキーボードが発祥の地。
ホームポジションをずらしてまで多用するコマンドではない。
論理行を移動する。表示行はgをつける。

w,b,e,ge
単語移動。

f{char}
文字検索。;と,でがんばれ。
t{char}やF{char}などある。

m{a-z,A-Z}
マークを付ける。`{mark}で移動。

自動マーク
'{', ., ^, [, ], <, >}に読み込まれてる。

%
対応する括弧に移動。
``(ジャンプ前の位置へ移動)を組み合わせると便利。
matchitで機能拡張可能。
set nocompatible
filetype plugin on
runtime macros/ matchit. vim

第9章 ジャンプによるファイル間の移動

<C-i>
進む的な奴。対は<C-o>。

gf
テキスト中のファイルに飛ぶ。イメージはハイパーリンク
:set suffixesadd +=. cpp
サフィックスを指定すること。

m{letter}
小文字でローカル,大文字でグローバルなマーク。
ファイル間移動の際はグローバル。

第4部 レジスタ

懺悔: ここを読むまではクリップボードコピーをOSの機能に頼ってました。

第10章 コピー&ペースト

"{register}
使用するレジスタを指定。
指定しない場合は無名レジスタ("")が使われる。

"0
ヤンクレジスタ。y{motion}専用。

"_
ブラックホールレジスタ
"_d{motion}でコピーすることなく削除。

"+
システムクリップボードレジスタ
普通にコピペしたのをVimに張り付けるときに使用する。
"+pで貼り付け,挿入モードでは<C-r>+。
"+にヤンクすると逆にシステムクリップボードにコピーできる。

"=
Expressionレジスタ。計算に使ったやつ。

<C-r>{register}
挿入モードでレジスタ内容を貼り付け。

:set paste
システムレベルのクリップボードでインデントがおかしいとき使うと気持ち良くなれるやつ。

第11章 マクロ

q{register}
qを押すまでマクロ保存。:reg {register}でレジスタ内容表示。
@{register}でマクロ再生。@@で直前に呼び出されたマクロ再生。

:set visualbell
ビープ音の代わりに可視化表示する。

:normal @{register}
選択範囲に対してマクロを実行(並列)。
ちなみに,VSCodeVimプラグインでは「Command: norm[al] is not yet implemented(PRs are wellcome!)」と表示された(220705, 現在)。

qA
マクロに追記を行う(Aは大文字の{register}と読み替えてね)。
実際は,:put {register}でレジスタ内容を吐出しから編集し,"{register}yでヤンクし直すのが良い(と思う)。

:wall
バッファリストの全ファイルを保存する。

第5部 パターン

第12章 パターンとリテラルのマッチ

:set ignorecase
大文字小文字を無視。
smartcaseで小文字検索で大文字小文字を無視。

\v
/検索でvery magicを使用する。
スラッシュ多すぎ問題(vim標準はmagic検索なので)を回避したい場合に利用する。

\V
/検索でnomagic検索を利用する。
メタ文字回避に使用する。

\v{strings}
/検索で{strings}に完全一致するものだけを対象とする。
theで検索するときに,theとthereなどを区別したい時に利用。
(ちなみに,VSCodeVimプラグインでは使えなかった(220705))

第13章 検索

:set incsearch
インクリメンタルサーチを有効化(まんま)。便利。

<C-r><C-w>
/検索で検索文字を全部入力しなくても補完してくれる。

:%s///gn
:substituteコマンドを呼び出している。マッチ数をカウントするのと同じ。
nでキャンセルしているので置換はされない。

*
カーソル位置の単語を検索。

第14章 置換

:[range]s[ubstitute]/{pattern}/{string}/[flags]
置換コマンドの構文。
特殊文字は:h sub-replace-specialで確認してね。

:set hlsearch
検索結果をハイライトする。

cフラグ
マッチした結果に対して,置換してよいか聞いてくれる。
l回答はこのマッチを置換して終了。a回答はこのマッチとこれ以上の全マッチを置換など。

<C-r>/
置換コマンドで直前の検索レジスタの内容をペーストする。
<C-r>{register}で任意のレジスタ内容を挿入。

%s//\=@0/g
置換フィールドに\=要素でVimスクリプト式を評価。
この場合は@0(ヤンクレジスタ)の内容を返している。複数行ヤンクされている場合に便利。

g&
:%s//~/&と同じ。ファイル全体に対して直前の置換を繰り返すように指示。
置換時に%Sの%を忘れたときなどに便利。

第15章 グローバルコマンド

:[range] global[!] /{pattern}/ [cmd]
指定したパターンにマッチする各行に,Exコマンドを実行する。
:vglobalで逆を行う(:v/abc/dでabc以外を削除)。

第6部 ツール

Unix哲学の根源とか,いろいろ書いてあった。
自分は基本的に流し見ぐらいで,必要そうならまた読み返す感じ。

第16章 ctagsを使ってソースコードのインデックスを作成し、ナビゲーションを行う

ctagsはVimのバージョン6から独立したらしい。
デフォルト機能ではないので,特に自分は触れない。

第17章 quickfixリストを使って,コードのコンパイルとエラー発生箇所への移動を行う

quickfixリストは外部ツールをVimで行う作業に組み込むための機能。
makeコマンドの例で説明されてた。

第18章 grep/vimgrepなどを使ってプロジェクト全体を検索する

:grep
外部プログラムのgrepのラッパー。
プログラマ用のgrepにackとかも紹介されてた。

:vim[ grep][!] /{pattern}/[ g][ j] {file} ...
Vimのネイティブ正規表現エンジン。
*ワイルドカードディレクトリ内の全ファイルにマッチ。
**ワイルドカードは指定ディレクトリまたはそのサブディレクトリにある全ファイルにマッチ。
##もいける。

:grepとの差別点は,Vimの検索コマンドと同じパターンで検索可能なこと。
(:grepを使う場合はPOSIX正規表現に変換する必要があるなど。)

第19章 ダイヤルXを廻せ! 自動補完だ

Vimとは関係ないけど,「cd -」で直前の作業ディレクトリに移動できることを知った。
<C-p>
挿入モードで自動補完起動。<C-n>で汎用キーワードなど。
ポップアップメニュー操作でも<C-p>と<C-n>などは使う。

<C-e>
挿入モードで自動補完時に終了する。

<C-x><C-i>
挿入モードでインクルードされているファイルのキーワード。

<C-x><C-k>
挿入モードで辞書のルックアップ。
Vimに単語リストを与える必要がある(:set spell)。

<C-x><C-l>
挿入モードで行単位の自動補完。

<C-x><C-o>
挿入モードでオムニ補完。

第20章 Vimのスペルチェッカを使ってタイプミスを発見,修正する

スペルチェッカがあることを知らなかった...

:set spell
スペルチェッカ起動。
デフォルトでは英単語辞書に対してスペルチェック。
移動は]sや[sなど。

:set spelllang
スペルチェッカの変更。
:set spelllang=en_usでアメリカ綴りだけをチェック。
自分のシステムに入っていないスペルファイルを有効にしようとすると,インストーラーが起動する。
(set nocompatible
filetype plugin onを忘れずに。)

第21章 それからどうする

実践を続けよう!
:x
:wqみたいなもん。ファイルに変更があった時だけ保存する。


感想

自分はVimを使いこなせていないことが理解できる良書でした。
エディタ操作は作業速度に直結するので,Vimの理解度が自分と同等の人は読んでおいて損はしないはず。

この本を読むまでは,テキストファイルの修正などはVSCode(+Vimプラグイン)で行ってましたが,結構対応していないコマンドが多かったので素vimに戻ろうかな~と考えています。
Vimプラグインも便利だけど,シェル+素vimの方が使いやすいかも。

あとは,お仕事ではVisual Studio(+Vimプラグイン)を使用しているので,キーバインドをどうするかを検討しなければ。

Unity: 2D Pixel Perfect Cameraを使ってレトロゲームを再現したい

こんちは

Unityで「レトロゲーム風を再現するためにはどうすんの?」を調査しました.


参考文献

まずはこれを読みましょう.
blog.unity.com


スプライトの設定

16×16のスプライトをUnityにそのまま持ってきて,拡大するとボケますよね.
f:id:lambda410:20220122163300p:plain

そこで,Inspectorの
・Filter Mode -> Point(no filter)
Filter Modeは標準だと「Bilinear(バイリニア補完)」がかかっているので,補完しないようにします.

・Compression -> None
また,Compressionは標準だといい感じに圧縮しようとするので,圧縮設定を切ります.

にすると,スプライトの味をそのまま生かせます. f:id:lambda410:20220122163655p:plain


2D Pixel Perfect Camera

次は画面の解像度をいじります.

Package Managerから2D Pixel Perfectをインストールします.
f:id:lambda410:20220122164000p:plain

これはピクセルパーフェクト対応のカメラを簡単に作るためのものです.

ピクセルパーフェクトは人によって説明の仕方が変わりますが,ファミコン時代の画面を再現するためのもの位の認識で大丈夫です(適当).
気になる人は復刻盤のファミコンゲームが収録されているゲームは大体設定できるようになっているので試してみてください.
(↓ ゲーム開発的には,このサイトで説明されている内容が重要です.)

https://aibars.com/mini-famicom-pixel-perfect

Main CameraにPixel Perfect Cameraをアタッチします.

大まかな設定項目についてです.
f:id:lambda410:20220122173130p:plain

1 Assets Pixel Per Unit
Unity世界の1ユニットのサイズです.
今回は16×16を1マス単位にしたいので「16」を設定しました.

2 Reference Resolution
アセットを表示する解像度のことです.
ファミコン風にしたいので「256×240」にしました.
(ちなみに「256x224」説もあるみたいです.)

注意点として,あくまで「アセットを表示する解像度」の設定なので画面の解像度を設定しているわけではありません.
いい感じに画面に合わせてアスペクト比を変更してくれるわけではないです.

解像度「256×240」に1PPU「16」を横に「16」個突っ込めますって設定です.

3 Upscale Render Texture
基準解像度に近い解像度で描画してくれます.
設定すると画面全体を使ってくれるらしいです(?)

4 Crop Frame
設定すると余った余白を黒で塗りつぶしてくれます.
ファミコン移植作品でそのゲームのラベルが設定されているやつみたいなのです.
f:id:lambda410:20220122173041p:plain

5 Stretch Fill
Crop FrameをXY両方設定すると出てきます.
有効にするとアスペクト比を維持したまま拡大してくれます.
が若干ボケます.
f:id:lambda410:20220122173100p:plain

カメラの緑線について

Sceneのカメラについて補足です.

緑の太線が「画面サイズ」.
緑の破線が「Reference Resolution」です.
f:id:lambda410:20220122173226p:plain

スマホの画面に合わせて拡大したいみたいな要望はこの辺を設定してあげると良さそうですね.
多分スクリプトでできるのかな?

面倒だと思う人は「Stretch Fill」を使うのが良いと思います.
簡単だしね.


まとめ

レトロゲームを再現するのも簡単ではないね.

Unity: トランジションを利用して画面遷移を作る

こんちは

RPGのエンカウント演出とかってUnityでどうやって作るのか調べました.
(フェードイン/フェードアウトってやつです.)
そのときの備忘録です.


参考文献

ルール画像(マスク画像?)はこちらのサイトで配布されているものを使用しました.
4you.bz


開発環境

Visual Studio Code 1.63.2 (ShaderToy拡張機能)
Unity 2020.3.25.f1
Windows 10 Home 21H2


トランジションとは

場面切り替え用の演出のことです(多分).
pangaea.top

ゲームだけでなく映像作品にもよく使われていますね.


原理

ルール画像と呼ばれるモノクロ画像の画素値を利用して演出を作るみたいです.

画素座標(X,Y)における元画像の画素値をA,ルール画像の画素値をB,閾値の画素値をTとすると,

B < T ならば 0
B >= T ならば 1

をAに乗算すればいいのではないかと思います.

ShaderToyで実験

我流なので正しいかは分かりませんが,とりあえずShaderToyで実験してみました.

他にもやり方はあるっぽいですが,簡単なので今回はこれで行きます.

ルール画像は参考文献のを使用しました.
元画像は画像処理で有名な人です.

なぜか画像を保存すると黒くなるはずの箇所が白いんですよね.
勘違いしているのかなぁ.


じゃあUnityではどうやるの?

本題のUnityです.

Unityのイロハが分からないので先人達を頼ります.
blog.cfm-art.net

シェーダーを使ってアルファ値でうんぬんするみたいですね.

前準備

フェード処理を作ってみます.

とりあえずGUIトランジションするために必要なものを用意.

  1. Unlit Shader
    光は関係ないのでこれで良いはず.

  2. Material
    シェーダーをアタッチします.

  3. Imageを付けたCanvas
    初期状態だと小さいので,画面全体にサイズを変更します.

シェーダ1

手始めにアルファ値をいじってみます.

透明にするために以下の設定をします.

Blend SrcAlpha OneMinusSrcAlpha

docs.unity3d.com

UNITY_APPLY_FOGはいらなそうなのでコメントアウトしました.
あっても大丈夫だとは思いますが.
light11.hatenadiary.com

実行結果1

アルファ値をスライダーで変更しています.
これだけでもフェードイン/アウト出来てそうですね.

シェーダ2

次はルール画像を使用してみる.

ソースコードのアルファ値を閾値として,ルール画像の画素値と比較する方針で行きます.
ShaderToyの奴と同じ感じです.

ルール画像はモノクロなのでRGBのどの値を使用しても良いです.
あと,閾値の範囲を[-1.0f, 1.0f]にして計算結果を[0.0f, 1.0f]になるように調整しました.

シェーダのTextureにルール画像をセットするのを忘れずに.

実行結果2

ルール画像の通りになってますね.

出力にルール画像のRGB値を使用しているので変な感じですが,returnを変更すれば色も変えられます.

// 黒のフェードアウト
return fixed4(0.0f, 0.0f, 0.0f, output);


まとめ

トランジション処理で表現の幅を広げよう!!!

Unity: アスペクト比を固定する方法を考える(2D/縦持ち)

こんにちは

Unityでスマホ用の2Dゲームを作る際にアスペクト比はどうするんだろうと思って調べました.
今回はその時の備忘録です.

カメラは平行投影(Orthographic)を対象としているので,透視投影でも使えますが見栄えが変わるかも...
また,スマホ縦持ちを想定しています(横持でも考え方は一緒のはずです).


参考文献

ほとんど参考にさせていただきました.
pengoya.net


開発環境

Unity 2020.3.25.f1
Windows10 Home 21H2


Orthographic Sizeとは

アスペクト比の固定はOrthographic Sizeを弄ることで実現します.

Orthographic Sizeとは,画面縦半分に何Unit入るかです(多分).

The orthographicSize is half the size of the vertical viewing volume.
The horizontal size of the viewing volume depends on the aspect ratio.

docs.Unity3D.com

docs.unity3d.com
ogamita777.hatenablog.com


スクリプト

メインカメラにアタッチするスクリプトです.

特に解説することは無いのでプログラムコメントに書いておきます.

画面サイズ変更時の処理

画面サイズ変更はUpdate()で解像度を見張ることで実現しています.

画面サイズ変更用のコールバック(イベント)はまだなさそうです(?).

answers.unity.com
stackoverflow.com

注意点

メインカメラのSizeはあらかじめターゲットとする解像度のサイズに合わせておいた方が良いです.

スクリプトを実行したときに設定されるSizeに変更するとSceneを弄るときに楽です.
f:id:lambda410:20211231115759p:plain


追記(22/01/04)

上のコードだと解像度によっては上手く固定されないことが発覚しました.

以前アスペクト比を無理やり固定したことがあったので,その時のソースコードを共有します.
アスペクト比は固定されますが,上下の余白にゴミが表示されたかも.


まとめ

縦持ち用のアスペクト比固定について考えてみました.

もしかしたらビルドしたとき余白にゴミが映るかもしれないので,次はその対策について考えたいと思います.

Unity: 旅の扉風のエフェクトを作る

こんにちは

今回はUnityで旅の扉(DQ3)に入った時風のエフェクトを作った時の備忘録です.

2Dテクスチャ用のエフェクトなので画面を歪めるわけではないです.
f:id:lambda410:20211229214933g:plain


開発環境

Unity 2020.3.25.f1
Windows10 Home 21H2


雑解説

テクスチャをsin波に従ってずらすだけです.

プログラム量も少ないので,シェーダを触ったことなくても理解できると思います.
(自分がシェーダを理解していないので.)

f:id:lambda410:20211229213812p:plain


シェーダ作成

まず,Unlit ShaderとMaterialを作成し,MaterialにShaderを結びつけます.

次にCreate Emptyで空っぽのオブジェクトを作成し,SpriteRendererを付けてMaterialに作成したのを結びつけます.

f:id:lambda410:20211229213248p:plain

ちなみにUnlit Shaderはライトの影響を受けないシェーダです(下記参考).
styly.cc

シェーダ

なんかごちゃごちゃ書いてありますが,大体はテンプレートです.

コメントで「ここ」と書いてあるところが追加したところです.
sin派でuv座標をずらしているだけですね.


スクリプト

スクリプトでシェーダの数値を変更します.

今回は10秒後に元に戻るようにしました.
かなり雑なのでここはお好きにカスタマイズしてください.


実行結果

sin波を別の曲線と合わせるとよりそれっぽくなるかもね.
f:id:lambda410:20211229214933g:plain


まとめ

シェーダとエフェクト入門として作ってみました.

シェーダ書くのは楽しいのでもう少し勉強してみようと思います.