9月 052017
 

出現確率が一様な抽選は、インデックスを一様乱数で求めればいいので実装が簡単です。

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以外でも使えます。

Continue reading »

9月 032017
 

Unity 5.5からC#コンパイラがアップデートされたので、C# 6としてのコンパイルが可能です。

但し、標準ライブラリ側が.NET Framework 3.5相当のまま古いので、C# 6の言語機能をすべて使えるわけではありません。async/awaitなど新しいライブラリに依存する機能は使えず、シンタックスシュガーである文字列補間などは問題なく使えます。

そういった事情からか、Unity 5.5~5.6ではデフォルトでC# 4としてビルドされるようになっています。これをC# 6でビルドさせるように修正する方法をまとめます。

Continue reading »

9月 032017
 

これまでC#の安定ソートが欲しくて色々と検討していました。

アロケーションを気にしなければ、LinkedListについては各要素にインデックス振ったListを作ってSort()するのが速いという結果が出ていました。その実装をここにまとめます。List版もありますが、先の記事で検討したマージソートの方が速いので、Listではそっちを使ったほうがいいです。性能比較については前回の記事を参照。

Continue reading »

9月 032017
 

(2017/09/10 パフォーマンス比較にOrderByを追加。それに伴い、結論をやや修正)

ListとLinkedListの挿入ソートおよびマージソートを実装します。どちらも安定ソートです。

何を考えて実装したのか、長々と別の記事に書いてあるので、興味があればそっちもよろしくです。

マージソートを単純に実装するより、対象となる要素数が少ない時は挿入ソートのほうが速いので、挿入ソートに差し替える対応をします。なので、マージソートの実装がメインで、最適化の副産物で挿入ソートもあるよ、という感じです。

Continue reading »

9月 032017
 

Unityでゲームプログラムを書いていると、C#で気軽に使える安定ソートが欲しくなるのですが、これという機能が標準で用意されていません。

今更ソートなんて自前で実装したくないんですが、欲しいものがなければ作るしかない。実装までに検討した色々なことをこの記事ではまとめていきます。

実装したものは別の記事にまとめたので、そちらをどうぞ。

アルゴリズム系の実装コードって何故かほとんど可読性が低いですよね。主に変数名がやっつけすぎて理解に時間がかかります。バグの温床だと思うので、そのへんも私なりに読みやすくしています。

その点、これからいくらか紹介する.NETやMonoの実装はとても綺麗で理解しやすいです。

Continue reading »

11月 142016
 

前回の記事「AndroidのpersistentDataPathがカオス」の続きです。

UnityでAndroidManifest.xmlを利用する方法のメモです。

前回の記事からの続き

※この節は前回の記事からの誘導なので、UnityでのAndroidManifest.xml利用方法を知りたいだけの人は読み飛ばしてください。

「外部」のアプリ固有パスにしかアクセスしないならば、Android 4.4(KitKat)以降は権限が不要ですが、それより前のバージョンも対象にする場合には、互換性のために権限を持たせることになるという話でした。しかし、これは無駄なので、特定のバージョン以降でその権限を要求しないようにする設定項目が追加されました。

ただ、やはりというか、残念なことにUnity側でそれを指定する設定は存在しないんですね。なので、もう少しAndroid側に寄って、自分で直接設定を書くことにしましょう。そのための手段ならUnityも提供しています。

Androidアプリの設定は、AndroidManifest.xmlというファイルにまとめられます。Unityから直接Androidアプリをビルドするときも、プロジェクトのルート直下に一時的に作られるTemp/StagingAreaディレクトリに、自動生成されたAndroidManifest.xmlがあることが確認できます。これだけ見ると、Androidプロジェクトを吐き出させて、AndroidManifest.xmlを編集してから、自前でAndroidのビルドを行わなければいけないようにも思えますが、そこまで不便ではありません。

これから任意のAndroidManifest.xmlをUnityで利用するための方法を説明していきます。

やりたいこと

WRITE_EXTERNAL_STORAGE権限を、Android 4.3以前では要求し、4.4以降では要求しない、という設定を指定したいです。

uses-permissionタグが権限を与える設定ですが、これの属性としてandroid:maxSdkVersionを与えてやればいいです。指定する値は、その権限が有効な最大APIレベルです。

上記記事にも書いてある通り、uses-sdkタグにも同名の属性がありますが、まったく別物なので、調べ物するときには気をつけてください。

WRITE_EXTERNAL_STORAGEをAndroid 4.4(API Level 19)より前のバージョンでのみ要求したい場合、API Level 18を最大として設定すればいいので、下記の設定をAndroidManifest.xmlに書きたいわけです。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />

Continue reading »

10月 112016
 

  • 2017/05/06
    • targetSdkVersionの決定方法が間違っていたので修正。
  • 2017/02/06
    • Unity 5.3.6での仕様変更について追記。
  • 2016/11/14
    • Android 4.4でのREAD_EXTERNAL_STORAGE対応、maxSdkVersionについて追記。
    • Android 6.0でのユーザによる権限の付け外しについて追記。
    • 掲載スクリプトの読み取り可能チェック処理でREAD_EXTERNAL_STORAGEを見ないように修正し、実行結果を更新。
    • 一部、誤植の修正。

Unityで外部ファイルにデータを読み書きするとき、普通Application.persistentDataPathを使うと思うのですが、AndroidだけpersistentDataPathの返すパスが権限によって変わります。

これドキュメントに書かなきゃいけない重要事項だと思うんですが、全く触れられていない・・・。

詳しいことはこれから説明していきますが、やりたいことによっては必要な追加権限があるにも関わらず、それを設定したときには、persistentDataPathはセーブデータの保存先として信用できないという衝撃的な問題が存在します。

(2017/02/06追記)Unity 5.3.6でpersistentDataPathおよびtemporaryCachePathがAndroid 4.4(コードネーム:KitKat、API Level 19)以降、「外部」を指すよう仕様変更となったそうです(リリースノート)。また混乱することを・・・。いずれにせよ、AndroidでpersistentDataPathを利用することは推奨しません。

以下、死ぬほど長いまとめ書きましたので、覚悟してください。

Continue reading »

Top