UnityのInputManagerで指定できるボタン名とKeyCodeの相互変換を試みます。
その前にいくらか前提を説明します。
タイトルの通り、キャメルケースの分割(split)をします。実装はC#。
正規表現で頑張る方法もあるようですが、ちょっとややこしいのとパフォーマンス的に嬉しくないことは容易に想像できるので、愚直な方法で実装します。
厳密なキャメルケースであれば、IDのような単語は、idやIdとなると思いますが、そのままIDと書くこともあるため、そのパターンにも対応します。スネークケースとの混用も対応します。先頭と末尾のアンダースコアは無視します。
例えば、_abcFOOBar123_456hoge__HOGE_
ならばabc
、FOO
、Bar
、123
、456
、hoge
、HOGE
に分割します。
(2017/11/20 「参照としてのスライス」節を追加、Span構造体について言及)
スライス(slice)とは、列(sequence)から部分列(subsequence)を取り出す操作のことを呼ぶもの、とここでは定義しておきます。
スライスは色んな言語に実装されている機能で、特に文字列(string)から部分文字列(substring)を得る機能を実装している言語は多いでしょう。文字列に限定しないときスライスという言葉が用いられている気がします。どこ由来なのか知らないため定義もわかりません。
C#にもそれっぽい機能はありますが、ちょっと使いにくいので、Pythonのスライスに近い機能を実装してみます。
出現確率が一様な抽選は、インデックスを一様乱数で求めればいいので実装が簡単です。
public static T sample<T>(T[] values)
{
return values[UnityEngine.Random.Range(0, values.Length)];
}
public static T sample<T>(List<T> values)
{
return values[UnityEngine.Random.Range(0, values.Count)];
}
ちなみに、この抽選は引いたくじを除外せずに次回も有効となる独立試行です。このような抽選を復元抽出と呼ぶそうです。
各要素の出現確率(重み)を設定して復元抽出したいとき、上の手法ではうまくいかないので、ひと工夫する必要があります。例えば、レア度によって出現確率の異なるガチャを実装したいといったケースですね。
以下、Unity向けに実装しますが、乱数取得部分を変えればUnity以外でも使えます。
C#のstring.Format()は便利ですが使いにくいです。大まかな理由は下記にまとまると思います。
1.と2.に対して、C# 6.0でひとつの解決法は示されました。
ただ、私はPython使いでもあるので、Pythonぐらい文字列操作が柔軟であると嬉しいなと思ってしまうわけです。
詳しいことは順に説明することとして、名前をキーにしたDictionaryに対応したFormat()を実装するというゴールを目指します。
C#の書式指定文字列の仕様はC#独自のものであるため、色んな言語を経験していると混乱します。そして、覚えられません。多機能かもしれませんが、かえって使いにくくなっています(※個人の感想です)。
C#自体は好きな言語なのですが、数少ない気に入らない点のひとつがこのフォーマット仕様です。
例えば、
この書式をC#で実装してみます。
var format = "{0:+0,00000000;-0,00000000}";
var result1 = string.Format(format, 0);
var result2 = string.Format(format, 1280);
var result3 = string.Format(format, -1280);
ゼロパディングするだけならd9
のようにd(10進数)書式を採用すればいいのですが、これはテンプレ書式であって、正の数値に対して符号を出すためにカスタム数値書式を採用すると使えなくなります。このように書式が複数のルールから成り立ち、複雑です。記述も長くなりがち。
ドキュメントがもうね、膨大すぎて読む気が起きないですよ・・・。
やりたい内容からググって逆引き的に情報探したほうが実装が早いという始末。
ちなみに、さっきの例をPythonで書くとこうなります。
format = "{:+010,}"
result1 = format.format(0)
result1 = format.format(1280)
result1 = format.format(-1280)
各条件に対応する記述が最小限ですし、記述する順序もあまり混乱しないと思います。
ドキュメントもすっきり。
Pythonの場合、波括弧で囲んだ中に書式を書くという点ではC#に似ていますが、細かい書式オプションについては、C言語のprintf()ベースになります。
C言語がとても古い言語であるということもあり、その書式が理想的かと問われれば首を傾げますが、たくさんの言語に取り入れられた実績のある仕様です。従って、ある程度共通化された文化であると言えます。しかし、この知識がC#で使えないし、C#の独自仕様は遥かに仰々しい。つらい。
どうしても多機能を実現したいなら、独自フォーマッタをクラスで定義できるようにすれば、それで十分だと思うんですよね。
基本機能はわかりやすくシンプルに。プログラミングの鉄則だと思います。
Unity 5.5からC#コンパイラがアップデートされたので、C# 6としてのコンパイルが可能です。
但し、標準ライブラリ側が.NET Framework 3.5相当のまま古いので、C# 6の言語機能をすべて使えるわけではありません。async/awaitなど新しいライブラリに依存する機能は使えず、シンタックスシュガーである文字列補間などは問題なく使えます。
そういった事情からか、Unity 5.5~5.6ではデフォルトでC# 4としてビルドされるようになっています。これをC# 6でビルドさせるように修正する方法をまとめます。