FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »Unityトラブルシューティング
このページの記事一覧

【C#】【Unity】enum 型と string, int 型の相互変換など  


 enum 型をファイルに保存したり、UIなどのインデクスに対応させたりと、相互変換するとき確認したいことが多くあるので、備忘録的にまとめておいた。今回は通常の C# として書いているが、Unity などでも使用することは多いので、ちょっとしたトラブルシューティングなどもついでに。どちらかというとリファレンス的な使い方になると思うので、解説は少なめに凡例を列挙しておこう。


(※) mono-4.2.1 (C#6, CLI4.5)[paiza.io] / Unity 5.6.3p1 - 2018.1.5f1 / Windows10(x64) で確認



■enum → string 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//enum → string 変換
BloodType bloodType = BloodType.A;
string str = bloodType.ToString();

Console.WriteLine(str);

A

 または以下のようにも書ける。
string str = Enum.GetName(typeof(BloodType), bloodType);

Console.WriteLine(str);

A




■string → enum 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//string → enum 変換
string str = "B"; //"b" でも可
BloodType bloodType = (BloodType)Enum.Parse(typeof(BloodType), str, true); //true = IgnoreCase

Console.WriteLine(bloodType);

B

 ちょっと試しに IgnoreCase のオプションを外して小文字にしてみると、System.ArgumentException が出る。
string str = "b";
//↓このコードはエラーが出ます。
BloodType bloodType = (BloodType)Enum.Parse(typeof(BloodType), str); //System.ArgumentException

Console.WriteLine(bloodType);

System.ArgumentException




■enum → int 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//enum → int 変換
BloodType bloodType = BloodType.AB;
int i = (int)bloodType;

Console.WriteLine(i);

3




■int → enum 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//int → enum 変換
int i = 3;
BloodType bloodType = (BloodType)Enum.ToObject(typeof(BloodType), i);

Console.WriteLine(bloodType);

AB

 試しに範囲外の値を入れてみると、そのまま整数値が出てくる。
//int → enum 変換
int i = 4; //範囲外の値
BloodType bloodType = (BloodType)Enum.ToObject(typeof(BloodType), i);

Console.WriteLine(bloodType);

4




■enum の名前の配列を取得
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

string[] names = Enum.GetNames(typeof(BloodType));

Console.WriteLine(string.Join(", ", names));

A, B, O, AB




■enum の値(enum)の配列オブジェクト(Array)を取得
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

Array values = Enum.GetValues(typeof(BloodType));

foreach (var item in values) {
Console.WriteLine(item + " = " + (int)item);
}

A = 0
B = 1
O = 2
AB = 3




■enum を long 型で使う
using System;

enum LongRange : long //※enum 型は任意
{
Min = long.MinValue,
Num = 123456789L,
Max = long.MaxValue,
}

long min = (long)LongRange.Min; //キャストが必要
long num = (long)LongRange.Num; //キャストが必要
long max = (long)LongRange.Max; //キャストが必要

Console.WriteLine(min);
Console.WriteLine(num);
Console.WriteLine(max);

-9223372036854775808
123456789
9223372036854775807




■enum の値割当と Unity インスペクタのずれを直す(Unity トラブルシューティング)

 例えば以下のような列挙型があったとき、途中から "Banana" を削除したくなったとしよう。しかし、コメントアウトで消したとするとそれぞれに割り当てられれた値がずれ、インスペクタでの表示(名前)も変わってしまう。

public enum Hoge  //※enum 型は任意
{
Apple,
//Banana,
Cat,
Dog,
}
public Hoge hoge;

 これは、コメントアウト前は {Apple = 0, Banana = 1, Cat = 2, Dog = 3} であったのに対し、コメントアウト後は {Apple = 0, Cat = 1, Dog = 2} になるために出る症状なので、以下のように値を直接割り当てれば、元の並びと同じになる。

public enum Hoge  //※enum 型は任意
{
Apple,
//Banana,
Cat = 2,
Dog,
}
public Hoge hoge;

 また列挙型はデフォルトでは0からの整数連番だが、重複しなければ値は自由に割り当てられるので、飛び番号や負の値なども使える。色々やってみると良いだろう。



■enum の PlayerPrefs 保存と読み込み(Unity)

 Unity でユーザーデータとして enum 型の保存と読み込みをやってみよう。といっても内容的には先に述べた「enum←→stringの相互変換」をやっているだけである。ここでは Load と Save の機能を持ったメソッドを2つ作ったとする。シーンに UI-Button を2つ置いて、それぞれの OnClick() で呼び出すなどすれば、簡単に確認できるだろう。

using System;
using UnityEngine;

public enum Hoge { //※enum 型は任意
Apple,
Banana,
Cat,
Dog,
}
public Hoge hoge = Hoge.Apple;

string prefsName = "hoge";

public void LoadHoge() //UI-Button の OnClick に登録する等
{
string str = PlayerPrefs.GetString(prefsName, hoge.ToString());
hoge = (Hoge)Enum.Parse(typeof(Hoge), str);

Debug.Log("Loaded : " + hoge);
}

public void SaveHoge() //UI-Button の OnClick に登録する等
{
PlayerPrefs.SetString(prefsName, hoge.ToString());
PlayerPrefs.Save();

Debug.Log("Saved : " + hoge);
}

(インスペクタで「Banana」を選んで保存・読み込みをした場合)
Saved : Banana
Loaded : Banana

 ちなみに int 型で保存と読み込みをする場合には以下のように書ける。

・・・(略)・・・
public void LoadHoge()
{
int i = PlayerPrefs.GetInt(prefsName, (int)hoge);
hoge = (Hoge)Enum.ToObject(typeof(Hoge), i);

Debug.Log("Loaded : " + hoge + " (" + i + ")");
}

public void SaveHoge()
{
PlayerPrefs.SetInt(prefsName, (int)hoge);
PlayerPrefs.Save();

Debug.Log("Saved : " + hoge + " (" + (int)hoge + ")");
}
・・・(略)・・・

(インスペクタで「Banana」を選んで保存・読み込みをした場合)
Saved : Banana (1)
Loaded : Banana (1)

 stringint のどちらでも良いが、後から値の割当を変えたくなったときにも対応できるように、string 型で保存しておいた方が無難ではあるだろう(※public で宣言してる場合、後から変更するとインスペクタでの名前表示のずれが発生するので注意)。


(関連記事)
【Java】enum を int で取得する
【Java】文字列を enum 型に変換する
【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする


スポンサーサイト

category: C#

thread: プログラミング

janre: コンピュータ

tag: C#リファレンス  Unityトラブルシューティング 
tb: 0   cm: --

【Unity】Unity2018 でビルドエラー「CommandInvokationFailure: Gradle build failed.」が出る  


 Unity2018 はどうも内部的なシステムの開発要件が上がったのか、インストして既存のプロジェクトをビルドしてみようとしたら、いくつかエラーが出たので備忘録。ちなみに 2017.4.2f2 までは何のエラーも出なかった状態からなので、開発環境によってはサードパーティの SDK など(Java SDK, Android SDK/NDK, Android Studio 等)のアップデートも必要になるかも知れない。結構大変なので、開発中であったり、Unity2018 の必要がないのなら、アップデートは先送りした方が良いかもね。またプラグインも使ってみようと思ったらビルド中にエラーが出たので、その辺りの対処方法も書いておこう。



(※) Unity 2018.1.0f2 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認



■新規プロジェクトでいきなりエラー「ArgumentException: Value does not fall within the expected range.」が出る

 インストして起ち上げたら、いきなり出たのがこれ(笑)。ググったらすぐに対処法が出てきたので正確にはメッセージは覚えてないが、要するにインストールされている Visual Studio 2017 のマイナーバージョンが合ってなかったらしい(?)。なので、最新版にアップデートすればエラーは出なくなる

Visual Studio Tools for Unity (最新版をインストール)
Error with Unity and Visual Studio Bridge (VS project not updating when new scripts added)



■「CommandInvokationFailure: Gradle build failed.」以降のエラーメッセージに「failed to find Build Tools revision 28.0.0」のようなバージョン番号が出ている。


 これはどうやらインストしてある Android Studio(ないし SDK)にある Build Tools のバージョンが合ってない(?) みたいなのだが、私の場合「28.0.0rc2」が入っていたのにダメだった(SDK Manager で "28.0.0" を探したが、なぜか "~rc1", "~rc2" しか無い(笑))。仕方がないので試しに "28.0.0rc2" を削除して「27.0.3」を残したらエラーが出なくなった(Android Studio で「Tools>SDK Manager」を開き、「SDK Tools」タブでダイアログの下の方にある「Show Package Details」にチェックを入れると細かいバージョンを追加・削除できる)。ただこれはかなりいい加減な応急処置なので(笑)、バージョンが上がって安定版が出たら設定し直したほうが良いかも知れない。





■「CommandInvokationFailure: Gradle build failed.」以降のエラーメッセージに「Cannot read packageName from~(パス)\AndroidManifest.xml」と出る。

※このエラーは Unity2018.1.7f1 で fix されたようです。
Unity 2018.1.7f1 リリースノート
[ANDROID] $APPLICATIONID TAG IN A MANIFEST CAUSES GRADLE BUILD TO FAIL


 これはプラグインを使ってみようと思ったら出た。普通にビルドする分には関係ないかも知れない。「AndroidManifest.xml」をオーバーライドしている場合、Unity2018 の仕様(バグ?)なのか、「Build Settings...」で「Build System」を「Gradle」にしていると、でパッケージ名が追加されないようだ(Unity2017.4.2f2 までは自動で追加される)。なので独自に「AndroidManifest.xml」を設定している場合、「manifest」タグに「package」属性を手動で追加しておく必要がある。「package」にはプロジェクトのパッケージ名「Edit>Project Settings>Player>Other Settings>Identification>Package Name」と同じものを書いておく。または「Build System」を「Internal」にするとエラーは出なくなる(ビルドできるようになる)。

● "AndroidManifest.xml" に追加する部分(※"package" はプロジェクトのパッケージ名にする)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company.productName">
・・・(略)・・・
</manifest>

●PlayerSettings

※パッケージ名(com.company.productNam)は必ずアプリ固有の名前(ID)として設定する必要アリ。

または「Build System」を「Internal」にするとエラーは出ない


 当プラグインでもエラーが出たときは、上記の方法でビルドできるようになる(※スマホ [Android7.0] でも動作確認済み)。




(関連記事)
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】【C#】モバイルビルド中の警告:Game scripts or other custom code contains OnMouse_ event handlers.~ を消す
【Unity】アイコン画像のフォーマット警告:Compressed texture XXX is used as icon. This might compromise visual quality of~ を消す
【Unity】5.6 の Canvas の警告:Shader channels Normal and Tangent are most often used with lighting~ を消す
【Unity】InitializeUnityExtensions: Must have a valid path for the plugin [XX] (XX:番号) というエラーの修正方法


category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityトラブルシューティング  Unityライブラリ  Unityプラグイン 
tb: 0   cm: --

【Unity】5.6 の Collider2Dは非アクティブ化で On~Exit2D イベントが発生する(5.6のコライダ2D挙動の違い)  


 これも前回同様、単なるバグっぽい気がするのだが、パッチリリースバージョン(掲載時点:5.6.0p2, p3)でも同じ挙動だったので、念のため書いておく。

(※) Unity 5.5.3p2, 5.6.0p2-p4 / Windows10(x64) で確認

 簡単に説明すると、全体を囲むような領域に何らかの Collider2D を設置し(形状は何でも良い)、その中に Collider2D を持ったオブジェクトを置いたとき、そのオブジェクトを「非アクティブ化」または「破棄(Destroy)」したとき、5.5以前では何も起こらず、5.6では OnCollisionExit2D や OnTriggerExit2D のコールバックイベントが発生するという挙動だ。ちなみに 3Dのコライダでは発生しない。以下の動画を見てみると簡単にわかるだろう。


 この挙動は「ある一定エリアから外れた場合は破棄(Destroy)し、エリア内で非表示(非アクティブ)にしたときはメモリに残す」ように作ってあったものが上手く動かなくなっていたので気づいた。つまり 5.6 では非表示にしたオブジェクトがすべて破棄されてしまい、再表示ができなくなっていた。キャッシュシステムのようなものを組んでいる場合、この挙動は気をつけておいた方が良いだろう。


 前回の 5.6.0f3 のアニメーション挙動バグ のように特定のバージョン不具合もあるようなので、特に必要性が無いならアップグレードしない方が良いかも知れない。開発中のものがあるなら、5.5.3p2 までにしておいた方が無難だろう。結構面倒臭い修正が多い。以下に参考URLを載せておこう。

(参考資料)
【Unity】「Unity5.6のわりと地雷なバグ」についての補足


(関連記事)
【Unity】5.6 のアニメーションは非アクティブ化でリセットされない(5.6のアニメーション挙動の違い)
【Unity】【C#】モバイルビルド中の警告:Game scripts or other custom code contains OnMouse_ event handlers.~ を消す
【Unity】アイコン画像のフォーマット警告:Compressed texture XXX is used as icon. This might compromise visual quality of~ を消す
【Unity】5.6 の Canvas の警告:Shader channels Normal and Tangent are most often used with lighting~ を消す
【Unity】InitializeUnityExtensions: Must have a valid path for the plugin [XX] (XX:番号) というエラーの修正方法
【Unity】"~\Temp\Assembly-CSharp.dll.mdb" is denied. と出たら…


category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityトラブルシューティング 
tb: 0   cm: --

【Unity】5.6 のアニメーションは非アクティブ化でリセットされない(5.6のアニメーション挙動の違い)  


 これは正直マイッタ…。エラーや警告も出ず、旧機能廃止(obsolute)でもない、ロジックも合ってるハズなのに、なぜか以前のように上手く行かない…。5.5以前のものを5.6に読み込んでみたら何もおかしくないのにバグった(笑)。…と思ったらどうやら 5.6 ではアニメーションの挙動が変わってしまったようだ。Animator の継承関係も変わってるのでメソッドも違うしね。どうやら内部的に変わってしまったらしい。道理でおかしな所が無いわけだ(笑)。

(※) Unity 5.5.3p2, 5.6.0f3 / Windows10(x64) で確認

※この挙動は 5.6.0p1 以降(パッチリリース)では元に戻っている(非アクティブでアニメーションが最初からになる)。

 たぶん、他にも色々変わったところもあるだろうけど、一番困った挙動を書いておこう。それはプレファブを「インスタンス生成→非アクティブ化→再アクティブ化」したとき、アニメーションはリセットされず、終了位置のままになる点だ。以下の動画を見てみると簡単にわかるだろう。


 5.5以前ではオブジェクトを非アクティブ化するとアニメーションはリセットされ、再びアクティブ化すると初期位置からアニメーションが再生されていたが、5.6では非アクティブ化でリセットされなくなった。なので、最適化などインスタンス生成の負荷を減らすため、使い終わったオブジェクトをプールしておき、再利用するようなキャッシュシステム等は注意する必要があるだろう。アニメーションは初期位置から自動で再生されることはないので、手動でリセットする必要がある。

(元ネタ) 最適化編 オブジェクトプーリング

 例えばコードでリセットするなら以下のようにできる。

Animator animator = GetComponent<Animator>();
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
animator.Play(stateInfo.fullPathHash, 0, 0.0f); //初期位置に戻す

 他にはアニメーションファイルの設定を「ループ(Loop TIme をオン)」にしておき、アニメーションイベントなどを最後のフレームに入れ、そのイベントをスクリプトで受信して SetActive(false) で非アクティブ化する方法でも上手く行った。

 実は 5.6 って obsolue(廃止予定・非推奨)も多くなったし、実際に廃止されてエラーも出たりするのもある。またアニメーションだけでなく、他にも挙動が変わってしまったものがあるようだ(コライダやライティング、更にバグもあるらしい)。特に必要性が無いならアップグレードしない方が良いかも知れない。開発中のものがあるなら、5.5.3p2 までにしておいた方が無難だろう。結構痛い目に会うかも(笑)。以下に参考URLを載せておこう。

(参考資料)
【Unity】「Unity5.6のわりと地雷なバグ」についての補足
UnityのGameObjectを非アクティブにするとAnimatorがリセットされる挙動、その対処法


(関連記事)
【Unity】5.6 の Collider2Dは非アクティブ化で On~Exit2D イベントが発生する(5.6のコライダ2D挙動の違い)
【Unity】【C#】モバイルビルド中の警告:Game scripts or other custom code contains OnMouse_ event handlers.~ を消す
【Unity】アイコン画像のフォーマット警告:Compressed texture XXX is used as icon. This might compromise visual quality of~ を消す
【Unity】5.6 の Canvas の警告:Shader channels Normal and Tangent are most often used with lighting~ を消す
【Unity】InitializeUnityExtensions: Must have a valid path for the plugin [XX] (XX:番号) というエラーの修正方法
【Unity】"~\Temp\Assembly-CSharp.dll.mdb" is denied. と出たら…


category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityトラブルシューティング 
tb: 0   cm: --

【Unity】【C#】モバイルビルド中の警告:Game scripts or other custom code contains OnMouse_ event handlers.~ を消す  


 Unity5.6 で obsolute になったものも多いけど、エラーや警告もやたら出るようになったね。しかしファイル名や行番号はおろか、ある一定のビルドでしか出ない警告は非常に直しずらい。とりあえず英文を翻訳にかけて、色々試してみたら警告が消えたので記録しておく。


(※) Unity 5.6.0f3 / Windows10(x64) で確認

●コンソールログの警告
Game scripts or other custom code contains OnMouse_ event handlers. Presence of such handlers might impact performance on handheld devices.
(※) Android ビルド中に出た

●Google翻訳
ゲームスクリプトやその他のカスタムコードには、OnMouse_イベントハンドラが含まれています。 このようなハンドラが存在すると、ハンドヘルドデバイスの性能に影響を与える可能性があります。

●対処法
1.MonoBehaviour を継承した OnMouseDown() などを使っているスクリプトを探す(Visual Studio の場合「Edit>Find and Replace>Find in Files」[Ctrl+Shift+F] で探すとラク)。

2.モバイル時のビルドで除外するようにスクリプトを修正する → 例えば以下の例のようにプリプロセッサで囲んでしまうとか(または OnMouseXXX() 以外の方法にする等)。

●モバイルビルド時に OnMouseXXX() を無効にする例(プリプロセッサで囲む)
public class Sample : MonoBehaviour {
#if !UNITY_ANDROID && !UNITY_IOS
void OnMouseDown()
{
//(なんらかのコード)
}
#endif
}

 ちなみに実際に使用してなくてもプロジェクトにあるだけでも警告が出るようなので注意。私の場合アセットストアからダウンロードしたものの中にこれが含まれていたため、警告が出ていた(使用はしてない)。

 どうやら MonoBehaviour を継承した OnMouseXXX() [XXX は Down/Up/Drag など] はモバイルなどでは負荷が高いようだね。 また、このイベントハンドラはドキュメントを読むと「GUIElement」または「Collider」でクリックが取得できるとなっていて、「uGUI」では無論使えなかった。もしかしてレガシーなものになるのかもね。場合によってはこれからは使わない方が良いのかも。


(関連記事)
【Unity】アイコン画像のフォーマット警告:Compressed texture XXX is used as icon. This might compromise visual quality of~ を消す
【Unity】5.6 の Canvas の警告:Shader channels Normal and Tangent are most often used with lighting~ を消す
【Unity】InitializeUnityExtensions: Must have a valid path for the plugin [XX] (XX:番号) というエラーの修正方法
【Unity】"~\Temp\Assembly-CSharp.dll.mdb" is denied. と出たら…


category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityトラブルシューティング 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop