02/25のツイートまとめ

Revetronique

Japan VR Fest. @ベルサール秋葉原2F!朝から来てるけど、まだ体験し尽くせない!Oculus, HTC, PSVR, Holo Lens, 段ボールまで…楽しすぎる(≧▽≦) #JVRFest https://t.co/QdM9QnUfY2
02-25 15:37

覚えておくと(たぶん)便利な素敵設定たち(主にUnityのインスペクタ関連)

どうも、Reveです。
今回もUnity関係の備忘録兼Tipsです。
(それにしても、最近の投稿がUnityばっかりですね(^-^;)。もう少し別の分野でも記事が書きたい...。)

Unityでは、インスペクタと呼ばれる3DCGなどオブジェクトの設定を確認・変更できるパネルがあります。
(インスペクタの画像)

これが少し工夫をすることで、自作のスクリプト内にあるフィールド(変数)の数値をIDE(統合開発環境)を開かずに編集できたり、使い勝手をよくすることができます。

インスペクタを拡張する理由】
ですが、何故インスペクタ上で変数を変えられるようにするのか。
一言でいえば、ちょっとした調整がすぐにできてとても便利だからです。

わざわざ「あのキャラクターの体力値をもう少し大きくしたい」といった小さな調整で、IDEからキャラに関するスクリプトを開いて数値を変えるのは時間も浪費しますし面倒です(最近のVisual Studioが特に重いもので...。まあ便利だから使いますがw)。

特に長いコードになると、変数を探す作業も時間がかかってしまい、ミスを犯す可能性も高くなるので、GUI上で変更する方がメリットが多いのです。

また、作成した後にUnityエディタ上でテストプレイなどをしてもらい、その場で値を調整してもらうといったことも可能なので、
プログラマでない人との共同作業にもうってつけなのです(さすがにコードを読ませて修正してもらうのはほぼ不可能なので)。

インスペクタを拡張する手法】
(C#前提です。Javascriptは知らん)

とりあえずフィールドなどに属性(Attribute)をつけるだけ。
また、変数の型によってもインスペクタ上での見え方が変化します。なお標準では、数値や文字を入力するフィールドが出てきます。

あるいは、CustomEditorを駆使してエディタ拡張をすれば独自のインスペクタも作成できるのですが、
長くなってしまうので今回は割愛。

【そもそも属性(Attribute)って?】
プログラムに関するメタデータ、砕けて言えば追加の設定を付けるものです。
詳細は以下のリンク先を参照

- ++C++; // 未確認飛行 C
(C#に関するサイトではトップクラスです)
http://ufcpp.net/study/csharp/sp_attribute.html

使い方も簡単で、フィールド変数やクラスなどの上につけたい属性を書くだけでOK

//...
[SerializeField] //属性(SerializeField:クラス内で宣言した変数が、インスペクタ上に反映)
int sampleField; //この変数がインスペクタ上に表示
//...


【各設定の効果】
では、属性の使い方も分かったところで、早速その効果を見てみましょう。
当方がよく使うものを中心にまとめてみました。

[Attribute]
SerializeField
- 変数の入力欄をインスペクタ上に表示 (public変数にした時と同じ効果)
- privateやprotectedなどでも表示可能
- デフォルト値を代入すると、入力欄にもその値が予め入れられる(変更可)
- Unity標準にはないクラス使う場合は、後述のSerializableと併用
System.Serializable
- クラスをインスペクタ上に表示できるようにする(構造体には使えない)
- (a)対象のクラスにこの属性をつけ、(b)このクラス型で宣言したフィールドにSerializeFieldを与えることで、このクラス内部の変数が表示される(アクセシビリティに注意)
Range
- 変数の設定できる範囲を指定
- 入力がスライダーバー形式に
Multilines(TextArea)
- テキスト(string)の複数行表示が可能(改行が反映される)
- 二者の違いは、右端で折り返すかどうか(TextAreaが折り返す)
Header
- 上にタイトルをつける
- 設定値のカテゴリ分けに便利
Tooltip
- 変数名が書かれた部分にマウスポインタを置くと、その説明文が表示される
- 説明文は引数で記載
RequireComponent(typeof("クラス名"))
- クラス自体に付属させる
- そのクラスに必要なクラスを指定できる
- この属性を付けたクラスをオブジェクトにつける際、必要なクラスがまだない場合は自動で一緒に取り付けてくれる。
- また、この属性付きクラスをつけたまま、要求される別のクラスを外そうとするとエラーメッセージが出る

[型宣言]
配列やリスト
- 要素数と、各要素の値を入力する
- 中の要素の表示/非表示が切り替え可能
bool型
- 入力がチェックボックス形式に
enum(列挙型)
- ドロップダウン形式
- enumを定義して、そのenum型の変数をpublic、またはSerializeField属性にする
Vector3(Vector2)、Rectなど一部のUnity標準クラス
- それぞれのクラスに応じた入力形式に

[そのほか]
UnityEngine.Events.UnityEvent
- 手軽にイベント(何かをきっかけに発生する処理)の実装が可能
- このクラスのフィールドを宣言し、そのフィールドがあるクラス内のメソッドでInvokeメソッドを呼び出せばイベント発生
- イベントの割り当て方は、uGUIでのボタンなどへのイベント設定と同じ方法
- UnityEventへ割り当てられるメソッドには制約があるため、それを配慮して中の処理を与えていく

//...
[SerializeField]
UnityEngine.Events.UnityEvent onSomethingHappen;
//...
void Update(){
if(条件を満たす){
if(onSomethingHappen != null) onSomethingHappen.Invoke(); //割り当てられたメソッドを上から順に処理
}
}


と、上記のAttributeをすべて一つに当てはめるとこうなります。
Attributes_Unity.png

ごちゃごちゃじゃねーかw
まあ、こんな風にいっぺんに盛り込む必要はないのですが、仕様に応じて適したものを使っていけば
ゲーム開発の効率も断然よくなる(ようになるかも)。
この情報が開発の手助けに少しでも慣れば幸いです。

続きを読む

テーマ : ゲーム開発
ジャンル : コンピュータ

Unityで角度制限付きの回転を行う方法

どうも、久しぶりの更新になってしまいました。
今日は備忘録を兼ねたUnityの使い方です。

Unityを使ってゲーム作りをしていると、回転が難しいという話があると思います。
実際、スクリプトでの回転操作はなかなか難しいですし、感覚がうまくつかめないところがあると思います。
特に、角度に制限を付けて回転をさせるのはネットでもなかなか見つからず、実装に苦戦している方も少なくないのではないでしょうか。

そこで、当方の実装方法を(備忘録を兼ねて)公開しようと思います。
あまり良い方法ではないかもしれませんが、もし参考になれば幸いです。

【方法とプログラム】
では、さっそくソースからどうぞ。
なお、ここでは前提として上下左右(XとY軸)の方向のみの回転

//現在の角度
Vector2 rotateAngle;
//制限する角度量
Vector2 rotateLimit;

void Update()
{
//対応するキー(デフォルトではa,s,w,dキー)を押すと、このスクリプトを付けた自身が回転
rotateProcess(new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")), 10f); //2番目の引数は、好きな値で
}

void rotateProcess(Vector2 delta, float speed)
{
//回転する方向と速度を決定
Vector2 rotVector = delta.normalized * speed * Time.deltaTime;

float rotH = getRotateAngle(rotVector.x, ref rotateAngle.x, rotateLimit.x / 2);
float rotV = getRotateAngle(-rotVector.y, ref rotateAngle.y, rotateLimit.y / 2);

//砲塔を回転
transform.rotation = Quaternion.AngleAxis(rotateAngle.x, transform.up) * Quaternion.AngleAxis(rotateAngle.y, transform.right);
//transform.Rotate(rotV, rotH, 0); //こちらは失敗
}

float getRotateAngle(float rotDelta, ref float angle, float rotMax = 90)
{
float result = rotDelta;

//予定の回転角度
float nextRot = angle + rotDelta;
//回転できる最大角度を超えたら
if (nextRot > rotMax)
{
result = rotMax - angle;
}
//回転できる最低角度を超えたら
else if (nextRot < -rotMax)
{
result = -rotMax - angle;
}

//回転後の角度も渡しておく
angle += result;
return result;
}


主な手順は以下の二つです。
1. 今の回転角度を求める
2. 1. で求めた角度をもとに、Quaternion.AngleAxitメソッドで回転させる

まず、1. は自作メソッドのgetRotateAngleから求めています。
引数は、左から (回転させたい角度量)、(回転前の角度)、(最大/最小角の絶対値) となっています。
ここでは、2番目の回転前の角度に、1番目の角度量を足して回転後の角度を求め、それが角度の制限値を超えていたら制限に収まるように回転量を調整しています。

戻り値は回転の角度量ですが、2番目の引数が参照(ref)となっているため、回転後の角度値も同時に求められます(実は、こちらの回転後の角度値を2.で使います)。

続いて2.の処理(自作のrotateProcessメソッド)ですが、回転量をQuaternionでもとめて、transform.rotationに入れています。
Quaternionは苦手な方もいらっしゃるかもしれませんが、Unity(に限らないかもしれませんが)で少し複雑な回転処理をさせようとすると必要になってきます。

とはいえ、今回使うのはQuaternion.AngleAxisメソッドのみです。
このメソッドは、引数に (回転させたい角度値)、(回転軸) を指定します。回転軸はVector3で指定するので、軸の伸びている方向と考えるとわかりやすいかもしれません。
オブジェクトに突き刺す軸を決めて、その軸を基に何度回転させるかといったイメージです。

今回のスクリプトは、上下と左右それぞれの回転をQuaternion.AngleAxisで求め、それをオブジェクトのrotationに代入して回転させます。AngleAxisメソッドで求められる回転は、上下、あるいは左右のみのものですが、実はQuaternion同士を掛け合わせると、二つの回転を反映した回転(Quaternion)が求められます。

そのため、以下の式で回転を求められるのです。
(オブジェクトのrotation) = (上下方向のQuaternion) * (左右方向のQuaternion)

なので、計算した角度とAngleAxisで求めたQuaternion同士を掛け合わせると角度制限を設けた回転が求められます。
今回は0°を中心に左右対称で角度の制限値を与えていますが、getRotateAngleの処理を少し変えれば非対称に角度の制限を設けることも可能です。

続きを読む

テーマ : ゲーム開発
ジャンル : コンピュータ

プロフィール

Reveちゃん

Author:Reveちゃん
コンビでやってます。
夢担当と技術担当がいます。

大学院卒業 → ロボットベンチャー(漆黒)就職 → 1年で退職 → ベトナムで仕事中(今ここ) → メディアアーティスト(未来☆)

リンクフリーです。

最新記事
最新コメント
月別アーカイブ
カテゴリ
アクセス数
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR