本当は怖い
Unityスクリプトの日本語文字化け問題
~「Unityエディター上でプレビューが文字化けする」だけでは済まないかもしれない~
~「Unityエディター上でプレビューが文字化けする」だけでは済まないかもしれない~
デフォルトのUnity環境では、プロジェクト内でC#スクリプトを作成すると、ANSI(Shift-JIS)で作成されます。
(※日本語環境では「ANSI=Shift-JIS」と考えて良いようです → 参考)
ですが、スクリプトの文字コードがANSIになっている場合、次の問題が起こります。
エディターからスクリプトをプレビューしたときに日本語部分が文字化けして見える
Unityバージョンのアップデートに伴って自動変換が行われた場合、その文字化けが永続化してしまう
より怖いのは2の方。これが発動してしまうと日本語部分が二度と読めなくなる可能性もあります。
(アップデートをする前には必ずバックアップをとっているであろうので大丈夫だとは思いますが)
1の方は、Unityエディターからスクリプトをプレビューしたときに、
←このように日本語の部分が文字化けして読めないというものです。
でもこれはプレビュー上で文字化けしているだけなので、気にしてない人も多いかもしれません。
自分も「プレビューで見えないだけでVisualStudioでファイルを開けば見えるし、別に放っておけばいいか」という感じでした。
しかし、これがプレビュー上での文字化けでは済まなくなるパターンもあります。
それが起こりうるのが、Unityプロジェクトを新バージョンのエディター向けに再コンバートするときです。
アップデートの時の自動変換機能の一つとして、「Unityバージョンのアップデートで名前が変更された変数や関数をスクリプトが参照していると、Unityがそれを検出してコード自体を上書きし、参照名を書き換えてくれる」というものがあります。
例えばRigidbodyコンポーネントは「drag」(抵抗)というパラメーターをもっていましたが、Unityのどこかのバージョンでこれが「linearDamping」という変数名に変更されました。
そのため、このバージョンを跨いでスクリプトをアップデートすると、Rigidbodyインスタンスのdragにアクセスしている行がそのスクリプト内に含まれていれば、「drag」の部分が「linearDamping」に置換されます。
こんなコードを記述したファイルを作りました。
旧形式の記述「Rigidbody.drag」を含めておき、新バージョン向けのコンバート時に自動置換されるようにしておきます。
(テスト用の適当なものなので、なんでインスタンスにnullを入れてるのかとかは気にしないでください)
これをそれぞれUTF-8とANSIで保存して、プロジェクトをアップデートしてみた結果が以下です。
UTF-8のC#ファイル
↓
問題なく変換
ANSIのC#ファイル
↓
日本語部分が文字化けしてゐる
コードの部分は「drag → linearDamping」となっており、どちらも問題なく置換されていますが、元々の文字コードがANSI(Shift-JIS)だったほうのC#スクリプト(右)は、ソースコードの日本語コメントが文字化けしたままに。
Unityは自動置換の対象となるメンバへのアクセスがそのC#ファイル内に含まれる際に、内容を置換した後でUTF-8として上書き保存します。
もともとUTF-8だったら問題ありませんが、元がANSIだと文字化けした状態で上書きしてしまうのです。
(元ファイルがUTF-8でないという事態がそもそも想定されていないんだろうと思います)
さらに、コメントだけでなく、コード自体の変数名などにも日本語を使っている人が少数派ながらいるかもしれません。
その場合、コードの変数名も文字化けしてしまいます。
このパターンでは更に悪く、読めなくなるだけでなく、エラー化してしまいコンパイルさえできなくなる可能性が高いです。
変換前
→
変換後
エラーになってコンパイルもできない
プレビュー時の文字化け(左)と同じような状態にファイル自体がなってしまいました
このように、元が何であろうとアップデート時にはUTF-8のファイルとして上書きされてしまうので
元のC#ファイルの文字コードがUTF-8になっていない
アップデートに伴う自動置換の対象となる記述が含まれる
という2つの条件を同時に満たしたスクリプトは、日本語部分が文字化けしたまま永続化されてしまうのです。
特に、2番目の条件も満たしているときのみ発動するという部分が、事態を看過する原因になりがちです。
1の条件を満たしていても、2の「自動置換の対象となる記述」が含まれていない場合には、そのC#ファイルは文字コードが保持されたままスルーされます。
あくまで「たまたまアップデートでUnity側が加えた変更に伴うコードの自動置換が発動した」回だけにこのジョーカーを引く可能性が出てくるため、
油断していると「これまでのアップデートでは何も問題なかったのに、今回一部のファイルだけいきなり文字化けした!何で??」ということになる可能性があります。
こうしたことを防ぐため、スクリプトは全てUTF-8で扱わせるよう対策をしておく必要があります。
対策自体はシンプルです。
予防的対策: 新規C#ファイルをANSI(Shift-JIS)で作らせないようにする。
既存ファイルへの対策: 既存のANSI形式のC#ファイルはUTF-8に変換する。
文字コードの確認方法:
スクリプトをメモ帳で開いて右下を見れば、文字コードが何かを判別できます。
プロジェクトフォルダ(.slnファイルと同じフォルダ)に、メモ帳で「.editorconfig」というファイルを作り、その中身を以下のようにして保存する。
### UnityでC#スクリプトを新規作成したときにANSIでなくUTF-8で作成させるためのコンフィグファイル ###
# 上位ディレクトリから .editorconfig 設定を継承する場合は、以下の行を削除します
root = true
# C# ファイル
[*.cs]
# 改行設定
end_of_line = crlf
# 新規作成時にUTF-8(BOM)を指定する
charset = utf-8-bom
(※1) Windowsを使っているので改行設定は「crlf」にしていますが、Macとかなら「lf」になるようです(※2) ここではUTF-8(BOM)を指定していますが、Unity的にはBOMは「有り/無し」どっちでも問題ないはずですこれで次にUnityでC#スクリプトを新規作成した際、UTF-8で作成されるようになります。
ファイルが少ない場合:個別にメモ帳で開いてUTF-8で保存しなおす。
手作業で処理できる程度のファイル個数ならこれで充分です。
メモ帳でファイルを開き「名前を付けて保存」
エンコードで「UTF-8」または「UTF-8(BOM付き)」を指定して保存
ファイルが多い場合:フリーソフトを使って一括変換
使ってみてオススメだったのは「FCChecker」というフリーソフトです。大変役に立っています。
複数ファイル、あるいはフォルダから「.cs」ファイルのみなど条件に合致するファイルを列挙して、一括で文字コードを変換することができます。
以下はC#ファイルを一括変換する際に使用している設定です。
(このような設定にして、あとはファイルやフォルダをドラッグ&ドロップして変換するだけ。)
FCCCheckerで使用している設定
※この画像では保存先の設定は「元のファイルを置換」になっていますが、置換する設定で実行する場合、変換する前に念のため元ファイルのバックアップをとってください。
または「保存先を指定」して出力することをお勧めします
「ファイル名が条件に合致するファイルのみチェックする」
「リストの文字列を終端文字列として使用する」
「リスト」では「.cs」ファイルを指定して変換対象となるファイルを絞り込み。
おわり