20200803のUnityに関する記事は5件です。

I2 localization における Font Asset の切り替え設定

概要

Unityで多言語対応するのに便利なアセット I2 LocalizationにおけるFont Assetの切り替え方法のメモです。

参考にしたページ

いろいろとwebを探りましたが、結局のところ以下のマニュアルが情報がまとまっていてわかりやすかったです。
http://inter-illusion.com/assets/I2LocalizationManual/I2LocalizationManual.html

TextMeshPro Font Assetの切り替え設定

事前作成したTextMeshProのFont Assetを活用するには、言語によりFont Assetを切り替える必要があります。この方法がわかりにくくはまりました。
Font Assetの切り替え設定は、Termsタブで行います。

  • Keyにわかりやすい名称をつける(ここではfont)
  • TypeにText Mesh P Fontを設定
  • 各言語にFont Assetを設定

image.png

マニュアルにも以下のように方法が載っています。
http://inter-illusion.com/assets/I2LocalizationManual/HowtoChangeFontperLanguage.html
マニュアルの方法はTypeにFontを指定する方法(これはおそらくビルド時に自動でFont Assetを作成する方式だと思います)をとっています。

コンポーネントでの設定

コンポーネントにI2 Localizeをつけて設定します。
LocalizeのウィンドウにはMainとSecondaryがタブで存在します。
Mainには用語の設定をSecondaryにはFont Assetの設定を行います。

以下がMainタブです。
image.png

以下がSecondaryタブです。
image.png

Font Assetの切り替えはSecondaryに設定する、ということになります。これはマニュアルを見ないと気付きにくいですね。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity / Xcode】Unity で生成したプロジェクトが Xcode でのアーカイブ作成時に失敗する

Unity で作成したプロジェクトを iOS 向けにビルドする必要があったのですが、Xcode でのアーカイブ作成に失敗したので、その対処法を書きます。

環境

  • Xcode 11.6
  • Unity 2019.4.5f1

症状

iPhone を繋いでの実機デバッグはできるのですが、アーカイブを作成しようとするとエラーを吐きビルドに失敗します。
エラー内容としては、Undefined symbol: _UnityPluginLoad のような文言がひたすら並んでいます。
image

解決策

Unity 側で iOS の最低バージョンを 11.0 に変えるで解決しました。

Project Settings > Player > Other Settings 内の Target minimum iOS Version10.0 から 11.0 に変更。

image

再度 Unity でビルドし、生成された .xcodeproj ファイルを開き、アーカイブを実行したところ無事成功しました。

似たような症状を探していたところ、以下のフォーラムを見つけました。
Linker Errors on Vuforia 8.1 Unity 2018.3.0f2 | Vuforia Developer Portal

「iOS 9、iOS 10 と 32ビットのサポートは無くなるため、最低リリースを iOS 11 にアップデートしないといけない」というような記述を見つけたため、試したところうまくいきました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#で汎用性の高いシンプルな乱数テーブルの実装・解説

概要

色々な種類のアイテムや敵をランダムで出現させたい、かつ、
確率だけ異なるパターンを複数用意させたい……。
そんなときにお手軽に使える、乱数テーブルを実装したので、詳しくご紹介します。
実装環境は、Unity C#です。

解説

今回実装するプログラムが最も有効活用出来るのは、
わかりやすい例でいうと、マリオカートのアイテムボックスのような例ですね。

マリオカートでは、8人でのレースの場合、1位~8位の、計8パターンが存在し、順位が低くなるほどレアなアイテムの出現確率が上がります。

例えば、バナナ・こうら・キノコ・スター、それぞれ4種類のアイテムが、1~8位で異なる確率で出現するとして、確率を百分率で表にすると、以下のようになります。

バナナ こうら キノコ スター
1位 60 30 10 0
2位 40 40 20 0
3位 20 50 30 0
4位 0 60 40 0
5位 0 40 40 20
6位 0 20 40 40
7位 0 0 40 60
8位 0 0 20 80

このようなテーブルを実際にプログラムとして実装する場合、通常の配列では1~8位それぞれの順位ごとの出現確率を8個分用意しなければなりません。
そこで今回は「ジャグ配列」という、配列を複数重ね合わせられる機能を使います。

乱数のアルゴリズム

今回は8つのアイテムの出現確率を、状況によって3つの確率パターンに変化させて出現させます。
使用するジャグ配列は、以下の通りになります。

private int[][] itemTable = new int[][]
{
    new int[] { 4, 4, 4, 4, 4, 4, 4, 4},
    new int[] { 0, 0, 0, 0, 4, 4, 4, 4},
    new int[] { 8, 7, 6, 5, 4, 3, 2, 1}
};

まず初めに、
private int[][] itemTable = new int[][]
このコードですが、通常の配列と異なり、かっこが2つ付いていることがわかります。
これがジャグ配列の宣言となります。

そして、itemTableという配列の中で、
new int[] { 4, 4, 4, 4, 4, 4, 4, 4},
new int[] { 0, 0, 0, 0, 4, 4, 4, 4},
new int[] { 8, 7, 6, 5, 4, 3, 2, 1}
これらの3つの配列を宣言しています。
さらにこれら3つの配列には、それぞれ8つの値を持っていることがわかります。
この値こそが、実際に乱数テーブルとしての役割を持つ値となります。

まず配列の1番目の中身の値、
new int[] { 4, 4, 4, 4, 4, 4, 4, 4},
では、4の値が8つ並んでいます。
(以降、この4に該当する値のことを「範囲値」と呼びます)

ランダムなアイテムを1つだけ選ぶ、という機能を実装する場合は「1~範囲値の合計(今回の場合は4*8=32)」の中からランダムな数値を1つ選び、その値がどの範囲値に属するかを調べます。
その計算方法についてですが、例えば範囲値の1番目が4となっています。これは1~4の範囲の値を取る、ということです。
次の範囲値も4なので、前回の範囲値(4)を足して、その次は5~8の範囲の値を取ります。
このように範囲値を足していくことで、乱数が何番目の範囲値に属するかを計算します。

範囲値の確率は「範囲値/合計値」で今回は全ての値が4なので、1~8番目の範囲値のどれに属するか、という確率は全て4/32となり、約分すると1/8となります。
確率的には
new int[] { 1, 1, 1, 1, 1, 1, 1, 1},
と同じですね。

配列の2番目では、
new int[] { 0, 0, 0, 0, 4, 4, 4, 4},
となっています。
配列の1番目と異なり、1~4番目の範囲値が0なので、乱数がこれらの範囲値に属することはありません。
このように選択したくない範囲値に対しては0を入れて、状況によって絶対に選択させない、といったことが可能です。
5~8番目の範囲値の確率はそれぞれ4/16となり、約分すると1/4となります。

配列の3番目は、
new int[] { 8, 7, 6, 5, 4, 3, 2, 1}
となっています。
範囲値の最初が8で、そこから-1ずつ範囲値が小さくなっていき、範囲値の最後は1となっています。
範囲値の合計値は1/2*8*(8+1)=36で、範囲値の確率は、8/36 ~ 1/36となります。
分母が36だと、ちょっとわかりづらいですね。
百分率で確率を表すと、以下の通りになります。

8/36 = 22.222...
7/36 = 19.444...
6/36 = 16.666...
5/36 = 13.888...
4/36 = 11.111...
3/36 = 8.333...
2/36 = 5.555...
1/36 = 2.777..

コードと実装方法

private int[][] itemTable = new int[][]
{
    new int[] { 4, 4, 4, 4, 4, 4, 4, 4},
    new int[] { 0, 0, 0, 0, 4, 4, 4, 4},
    new int[] { 8, 7, 6, 5, 4, 3, 2, 1}
};

private int TableGenerate(int tableNumber)
{
    // 検索用の配列を代入
    var _itemTable = itemTable[tableNumber - 1];

    // 判定値を計算
    var totalNumber = 0;
    var searchTable = new int[_itemTable.Length];
    for (int i = 0; _itemTable.Length > i; i++)
    {
        totalNumber += _itemTable[i];
        searchTable[i] = totalNumber;
    }

    // 乱数を計算
    var randomNumber = Random.Range(1, totalNumber + 1);

    // 乱数がどの範囲値に属するか検索
    for (int i = 0; searchTable.Length > i; i++)
    {
        if (searchTable[i] >= randomNumber)
        {
            // 乱数が、「判定値よりも小さい」ならば結果を返す
            return i + 1;
        }
    }

    //randomNumberがsearchTableの最後の値より大きいことはありえないのでここに到達することはない
    return 0;
}

使い方はとても簡単で、最初(1番目)の配列のテーブルを使用したい場合は、
var itemValue = TableGenerate(1);
と書くだけで、itemValueに配列の1番目を使用した乱数の結果(1~8のどれか)が返されます。
状況合わせて自由に2番目や3番目のテーブルに切り替えることもできます。

乱数のテスト

試しに3つの配列をそれぞれ8000・4000・8000(有効な範囲値の数*1000)回数分、乱数を生成して、それぞれの範囲値の値が返された回数を計算してみました。

1番目の配列 2番目の配列 3番目の配列
1 979 - 1727
2 1029 - 1573
3 1005 - 1360
4 971 - 1149
5 994 983 901
6 1027 1003 656
7 999 1017 402
8 996 997 232

平均出現回数は「試行回数 / 範囲値の数」なので、3つとも平均出現回数は1000となります。
実際の結果も、平均がだいたい1000に違い数値で、しっかりと確率通りになっていますね。

あとはこの結果の値をSwitch文なりで分岐し、それぞれ異なるアイテムをインスタンスとして生成すればOKです。

また、配列テーブルを変更するだけで、確率を自分好みに変更することができます。

お疲れさまでした:bow:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity 3D入門 #12 [HQ Modular RE Mansionによる建物の建築&壁抜け,壁登り修正]

まず、HQ Modular RE Mansionのデモシーンの建築をゲームを作っていたシーンに挿入しましたが、建物があまりにも重すぎてUnityがフリーズしてしまいました。付属のプレハブを使って自分で建物を作ります。

壁を設置した際に片側からはしっかりと壁が見えるのに、反対側から壁が透けて見えてしまい、当たり判定もすけた側には存在しない事態に遭遇しました。

スクリーンショット 2020-07-31 15.59.54.png
見える側

スクリーンショット 2020-07-31 16.00.02.png
透ける側

これは、
スクリーンショット 2020-07-31 16.02.07.png
スクリーンショット 2020-07-31 16.02.29.png
このように同じ位置に180度回転させた同じ壁を配置することで解消しました。

追記:上の画像ではxyz座標が全く同じ所にwallとwall(1)を配置しましたが、その場合見た目上二枚の壁の間に隙間ができてしまいましたので、wall(1)のz座標を変更することで二つが重なるようにしました。

また、プレイヤーが壁抜けをしてしまう不具合がありましたので、http://tsubakit1.hateblo.jp/entry/2016/07/09/235856 を参考にプレイヤーのRigidbodyのCollision DetectionをContinuosに変えることで解決しました。また、FixedTimeStepを0.02から0.01としました・

プレイヤーが一人称視点を上に向けたまま壁に向かって走ると壁を駆け上がってしまう不具合が生じました。
これは視点方向に向けてプレイヤーに特定の力を加えることで移動しているため、上方向に力が働いてしまったことが原因と考えられます。

float h = Input.GetAxis ("Horizontal"); // 入力デバイスの水平軸をhで定義
float v = Input.GetAxis ("Vertical");  // 入力デバイスの垂直軸をvで定義
if (Mathf.Max(Mathf.Abs(v), Mathf.Abs(h)) > 0.1) {
    velocity = new Vector3 (h, 0, v);  // キー入力から方向ベクトルを導出         
    velocity = cameraObject.transform.TransformDirection (velocity);  // キャラクターのローカル空間での方向に変換
    velocity = new Vector3 (velocity.x, 0, velocity.z);  //上下方向の力をゼロにする
    velocity *= forwardSpeed;  // 移動速度を掛ける
    transform.localPosition += velocity * Time.fixedDeltaTime;
}

このようにプレイヤーの移動において上下方向の力をゼロにします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityチュートリアルでビルドエラー解決方法

■現象
公式チュートリアルプロジェクトをインポートしたが、ビルドエラーが発生した。

■参考
https://forum.unity.com/threads/package-manager-throwing-numerous-errors.608191/

I've just found the solution which is working perfectly for me, here it is:
Create a new project, copy the manifest.json file from the "Package" folder(of a new project) and replace the Manifest.json file of your project(in which you're facing errors).

Or You can simply delete the Package folder from your project and unity will recreate it by itself self and the problem will be solved.

■対応
上記に従って、Packagesフォルダを削除すると自動的に再作成してビルドが通るようになった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む