文字のアウトライン処理と、その高速化シェーダー


宴3までのLegacyText用のアウトライン処理についてです
宴4ではTextMeshProでのアウトライン処理を使用するのでここでのやり方は関係ありません。

Unityのアウトライン処理の基本

アウトラインとは「縁取り」のことです。
UnityのUIの基本コンポーネントとして、「Outline」というものが既にあります。公式ドキュメント
これは、黒など色違いのものを上下左右4方向にコピーして、背後に表示するというものです。
仕組みとしては単純ですが、4方向だけですと、縁取りを太くした場合に若干不格好になるという問題があります。

宴のアウトライン処理

宴では、Outlineを改造した「UguiRichOutuine」という専用のコンポーネントを用意して、ある程度太い縁取りも可能にしています。

アウトラインコンポーネントのデメリット

UguiRichOutuineはその名の通り「Rich(リッチ)」で、負荷のかかる贅沢な使い方です。
Unityの基本のOutLineにしても、UguiRichOutuineにしても、描画するためのポリゴンの頂点数がとても増えるというデメリットがあります。
そして、Unityが用意しているUIの頂点をカスタムする仕組みの構造上、頂点数が増えた場合にとてもCPU負荷が高くなってしまいます。
(内部的な細かい話としては、大サイズのstructのListを扱う構造になっているため、値を変更するためには参照ではなく必ず大サイズstructのコピーが発生してしまうのが原因。C#のバージョンによっては回避できない)
さらに、ノベルゲームでは文字送り(1文字ずつ表示する)のために、毎回テキストの頂点編集を行う必要があるため、文字送りの最中ずっと重いCPU負荷がかかります。
通常の使い方であれば文字数は多くても200程度なのであまり問題ないのですが、英語圏の場合文字数が増えるため1ページに500以上の文字の表示が必要なケースもあります。
ここまでの状況になると、FPSが10近くに落ち込むなど、ゲームとしては致命的な状態になります。

アウトラインシェーダー

上記のアウトラインコンポーネントのCPU負荷の高さは、Unityの構造上問題があるため、宴で解決することは困難です。
対策としてシェーダーを作成することで、CPUではなくGPU上でアウトラインを描画をするようにして、負荷を軽減できるようにしました。

アウトラインシェーダーの適用方法

アウトラインシェーダーはデフォルトでは設定されないため、必要に応じて手動で設定する必要があります。
ProjectWindowで「Material」を新規作成する。

作成したマテリアルのシェーダーに「Utage>UI>OutLine9Pass」を設定する。

作成したマテリアルをテキストコンポーネントに設定する。

UguiRichOutuineコンポーネントは削除する。

アウトラインの色や太さはマテリアルから設定する

アウトラインシェーダーの注意点

アウトラインシェーダーは、一度に描画される文字数が多い場合には有効ですが、UIのボタンのテキストなど細かいテキストがあちこちのオブジェクトにある場合、
バッチ処理が効かなくなる可能性があるので、かえって負荷が高くなる可能性があります。
また、内部で9パスを使って描画しているため、(あるのかわからないですが)マルチパス描画に制限があるデバイスがもしあった場合は、危険かもしれません。
そして、UguiRichOutlineと違って、コピーカウントは制御できません。
UguiRichOutlineでいうと、CopyCount=8に相当します。つまり、あまり太いアウトラインは描画できないということです。
シェーダーのパスを増やさないとコピーカウントは増やせないため、どうしても太いアウトラインが必要な場合は、シェーダーをコピーして新たに16パスや32パスのシェーダーを書くなどして対応してみてください。

TextMeshPro

Unityは、TextMeshProというのテキスト描画の拡張機能を用意しています。
これを使えば、上記のアウトラインや文字送りの問題もほぼ解決すると思われます。
宴3.7.1から対応を開始しているので、お試しください。TextMeshPro対応