エフアンダーバー

個人開発の記録

Unityと改行コード

Visual Studioを利用してUnityのスクリプトを書いているとよくこんな警告が出ます。

There are inconsistent line endings in the 'Assets/XXX.cs' script. Some are Mac OS X (UNIX) and some are Windows. This might lead to incorrect line numbers in stacktraces and compiler errors. Many text editors can fix this using Convert Line Endings menu commands.

和訳するとこんな感じ。

'Assets/XXX.cs' スクリプトの改行コードに一貫性がありません。Mac OS X (UNIX)のものとWindowsのものがあります。 これはスタックトレースの行番号の誤りやコンパイラエラーを引き起こすことがあります。多くのテキストエディタでは「改行コードの変換」メニューコマンドによりこの問題を修正できます。

今回はこの警告の意味するところと解決方法について。

改行コードとは?

実は現在よく使われている、コンピュータで改行を表す方法は二つあります。 ひとつはLFという特殊な文字のみの一文字で表す方法、もうひとつはこれにさらにCRという特殊な文字を加えたCR+LFの二文字で表す方法です。 この改行を表す文字の組み合わせのことを改行コードといいます。

なぜ二通りあるかというと、タイプライター時代の名残なのだそうです。 CRはキャリッジリターン(Carriage Return)の略で印字位置を現在の行の行頭に戻すという命令で、 LFはラインフィード(Line Feed)の略で印字位置を一段下にずらす命令です。 もともとタイプライターではこれらの二文字を組み合わせて改行を表現していました。

コンピュータでもこれらを受け継いで二つの文字があります。 しかし、タイプライターのときのように片方の文字のみ使うということをしなくなったため、 どちらか一方のみで改行を表すシステムやまったく別の文字を改行文字として定義するシステムが現れました。

いろいろな変遷を経て、現在主流のOSでは、LinuxとMacがLFを、WindowsがCR+LFを使っています。 Macで作成されたテキストファイルをWindowsのメモ帳で開くと一切改行されていないように見えるのはこの辺りが原因だったりします。

C#では、\rがCRを、\nがLFを表します。 現在のシステムの改行コードを使いたい場合にはSystem.Environment.NewLineプロパティを使います。

C#に限らず改行コードの扱いというのは結構面倒なため、よくバグの原因になります。 Unityの警告はまさにそのためで、ソースコードを処理するプログラムがバグるかもしれないから直しとけということです。

警告の原因

警告の内容を読む限り、対象のソースコードには改行コードとしてLFを使っている部分とCR+LFを使っている部分があるということのようです。 しかし、なぜ二つの改行コードが交ざってしまったのでしょうか。

Unityでメニューからスクリプトファイルを作成すると、作成されたファイルの初期コードには、例えWindows環境であってもLFが使われます。 一方で、Visual Studioは元々Windowsのみを対象とするエディタ(IDE)なので、ことあるごとにCR+LFを改行コードとして挿入します。 そのため、Unityで作成したファイルをVisual Studioで編集していると改行コードが交ざってしまうのです。

解決方法

ファイルを閉じて再度開く

Visual Studio上で問題が発生しているファイルを一度閉じて、再度開くと「行の終わりの不整合」 *1 というダイアログがでてきます(設定によってはでてこないかも)。 ここで、改行コードの種類を指定すると、すべての改行が指定した改行コードに置き換わります。

UnityがLFを挿入するのはファイル作成時だけなので、 特にWindows環境以外で使う予定がないのであれば、 ここでCR+LFを選択してしまえば同じファイルで警告がでることはなくなると思います。

改行コードをLFにしたい場合にはこの方法は推奨しません。 たとえここで一度変換したとしても、またVisual StudioがCR+LFを挿入してしまうためです。

保存オプションの詳細設定 (~VS2015)

Visual Studio 2015までは "ファイル" > "保存オプションの詳細設定" から改行コードの変換ができます。

しかし、あくまでも変換なので前述の方法と同じ問題があります。

EditorConfig (VS2017~)【推奨】

Visual Studio 2017からはEditorConfigという仕様に対応しました。

EditorConfigは各テキストエディタでのコードの書き方を統一するための仕組みで、 改行コードのほかに、文字コードやインデントスタイル(タブ・スペース)の指定ができます。

使い方は簡単で、プロジェクトフォルダに.editorconfig.を忘れないように注意)という名前のファイルを作成し、次のような記述をするだけです。

root = true

[*.cs]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8

それぞれの意味はこんな感じ。

記述 意味
root = true これより上のフォルダにある.editorconfigを参照しない
[*.cs] すべてのC#ソースファイル(*.cs)に以下を適用
indent_style = tab インデントにタブを使用(スペースの場合はspaceを指定)
indent_size = 4 インデントの幅は4文字分
end_of_line = lf 改行コードにLFを使用(CR+LFの場合はcrlfを指定)
charset = utf-8 文字コードにUTF-8を使用

.editorconfigファイルはエクスプローラ上で作ろうとすると、 最初の.を拡張子の前の.と勘違いして名前を付けろと怒られるので、Visual Studio上で作るのがいいかもしれません。 プロジェクトを右クリックして、「追加」>「新しい項目の追加」>「テキストファイル」と選択して、.editorconfigと名前を付ければOKです。

既存のファイルに設定を適用するには、 メニューの「編集」>「詳細」>「ドキュメントのフォーマット」(ショートカットキー:Ctrl-K Ctrl-D)でコードをフォーマットします。 .editorconfigファイルの作成・変更時に開いていたファイルの場合には一度開きなおす必要があります。

ただ現状この機能は追加されたばかりのせいかバグがあるようで、 フォーマットしても一部の改行コードが修正されないことも多いです (どうもフォーマットが必要かどうかの判断に改行コードの不一致が含まれていないようで、 うまくいかない部分に無意味な空白などを入れてからフォーマットすると正しく変換されます)。 まあ、おそらくそのうち修正されると思うので、しばらくは他の方法と併用してどうにかするのがいいと思います。

おわりに

もともとEditorConfigに関する記事を書くつもりだったのですが、 せっかくなので改行コードうんぬんから全部書いてみました。 本題がわかりづらくなっていなければよいのだけれど。

余談ですが、リパッケージ版ユニティちゃんがUnity 5.6でエラーをはいていたので修正しました。 どうもPlayable APIが変更された結果、Animatorの継承元が変わり、GetTimeメソッドが消えたようで。 そもそもExperimentalなクラスを継承していたこと自体が異常だったのかもしれませんが、 Deprecatedでもなくいきなり消されると代替機能がどこにあるのかわからなくて結構困りました。



執筆時のUnityのバージョン:5.6.0f3

*1:英語だとInconsistent Line Endings、日本語訳はWeb上で調べたのでもしかすると違うかもしれません