UnityのHandleを使用してシーンビューのオブジェクトを操作する

今回はUnityのHandleを使用してシーンビューに配置したゲームオブジェクトを操作出来るようにしてみます。

ゲームオブジェクトを選択しシーンビューを見ると

デフォルトのハンドル

↑のようにゲームオブジェクトを操作するハンドルが表示されると思います。

今回はこのオブジェクトを操作するハンドルを自分で作ってゲームオブジェクトを操作していきます。

スポンサーリンク

操作するハンドルを作成する前に

ゲームオブジェクトを操作するハンドルを作成するにはゲームオブジェクトに取り付けるスクリプトを拡張する必要があります。

拡張される側とする側のスクリプト

ゲームオブジェクトに取り付けるスクリプトをHandleDataという名前(名前はご自由に付けてください)にして作成します。

↑のように通常のスクリプトを記述しハンドルで操作したいゲームオブジェクトに取り付けます。

次にこのスクリプトを拡張するスクリプトをAssets/Editorフォルダ以下にHandleTestという名前(名前はご自由にお付けください)で作成します。

CustomEditorアトリビュートを取り付けtypeofでさきほど作成したスクリプトを設定します。

クラスはEditorクラスを拡張して作成します。

ハンドル操作処理はOnSceneGUIメソッド内に記述する

ハンドルで操作する処理を記述するにはOnSceneGUIメソッド内に記述します。

このOnSceneGUIメソッドはハンドル操作のスクリプトを設定したゲームオブジェクトを選択しシーンビュー内にマウスポインタが来ると呼ばれます。

Handles.color

Handles.colorはハンドルの色を変更する事が出来ます。

ハンドルの色を引数に設定するメソッドで色を変更した時にうまく反映されない事があります。

そんな時はHandles.colorに白色を設定すればうまく反映されると思います。

操作するハンドルの表示

操作するハンドルの形状はいくつかありますので表示してみます。

スクリプトはOnSceneGUIメソッドの中に記述します。

HandleDataスクリプトはヒエラルキーに設置したデフォルトのCubeに取り付けて確認していきます。

これから描くハンドルをハンドル関数として渡すとスクリプトリファレンスにはあるんですが、使い方がよくわかりません。(^_^;)

とりあえずハンドルの形状を描画するものとして紹介しておきます。

ArrowCap

ArrowCapは矢印のハンドルの表示です。

第1引数はハンドルのコントロールID、第2引数はハンドルの位置、第3引数はハンドルの角度、第4引数はハンドルのサイズです。

コントロールIDは使い方がよくわからないのでとりあえず0にしています・・・(^_^;)

あとは位置とハンドルの角度を設定し、最後にハンドルのサイズを指定しています。

シーンビューで拡大や縮小(マウスのホイール操作)をするとハンドルの大きさは固定なのでゲームオブジェクトから遠ざかれば段々と小さくなります。

しかしHandleUtility.GetHandleSizeを使用すると拡大・縮小に合わせてサイズを拡大・縮小し同じ大きさで表示する事が出来ます。

引数は3D空間でのハンドルの位置を指定しますが、この指定を色々変えてみたんですがよくわかりません・・・・(^_^;)

ArrowCapのサンプル

シーンビューで拡大・縮小をすると固定の矢印と大きさが変わる矢印が確認出来ると思います。

CircleCap

CircleCapは円のハンドルの表示です。

引数はArrowCapと同じです。

CircleCapサンプル

円の操作ハンドルが表示されました。

SphereCap

SphereCapは球のハンドルの表示です。

引数はArrowCapと同じです。

SphereCapのサンプル

ちょっとサイズを大きくし過ぎたので設定したCubeが見えなくなってますね・・・(^_^;)

ConeCap

ConeCapは円錐のハンドルの表示です。

引数はArrowCapと同じです。

ConeCapのサンプル

CubeCap

CubeCapは立方体のハンドルの表示です。

引数はArrowCapと同じです。

CubeCapのサンプル

↑のように立方体が表示されました。

CylinderCap

CylinderCapは円柱のハンドルの表示です。

引数はArrowCapと同じです。

CylinderCapのサンプル

DotCap

DotCapはドットのハンドルの表示です。

引数はArrowCapと同じです。

DotCapのサンプル

↑のように2Dのドットハンドルが表示されました。

オブジェクト操作ハンドルの作成

ここまではハンドルの形状を表示しているだけでしたが、ハンドルをドラッグした時にゲームオブジェクトを操作するメソッドを使ってみましょう。

HandleDataスクリプトを更新します。

このスクリプトを設定したゲームオブジェクトの位置や角度を変更する時のフィールドを宣言し、DataUpdateメソッドが呼ばれると値が更新されます。

LookAtUpdateはゲームオブジェクトをlookAtPointの方向に向けるメソッドです。

次にHandleTestスクリプトに追加します。

targetに関してはEditorの拡張の記事でもやりましたが、

UnityのEditor拡張をしてインスペクタをカスタマイズする
UnityのEditor拡張を利用してインスペクタのカスタマイズをしてみたいと思います。

HandleDataのフィールドを取得出来ます。

OnSceneGUIが呼ばれるたびにHandleDataが設定されているゲームオブジェクトの位置や角度の情報をHandleDataのフィールド値に反映させています。

これをしている理由はハンドル以外で位置や角度を変更した時にハンドルの位置や角度もそのゲームオブジェクトに合わせて移動させる為です。

EditorGUI.BeginChangeCheckとEditorGUI.EndChangeCheck

オブジェクトを操作するハンドルを作成する時に登場するEditorGUI.BeginChangeCheckとEditorGUI.EndChangeCheckについて見ておきます。

EditorGUI.BeginChangeCheckメソッドとEditorGUI.EndChangeCheckメソッドとの間で変更が行われた時にアクションを起こします。

FreeMoveHandle

FreeMoveHandleはドラッグすると位置を自由に変更出来るハンドルを作成します。

第1引数が表示位置、第2引数が表示角度、第3引数がサイズ、第4引数がSnapの移動値、第5引数がハンドルの形状ですが、物によっては違う形状が表示されます(謎)

SnapはWindowsならCtrlキーを押しながらハンドルをドラッグした時の移動値です。

↑のスクリプトではHandles.FreeMoveHandleメソッドの第1引数にスクリプトが設定されているゲームオブジェクトのフィールドデータを設定し、第2引数ではTransform情報を指定しています。

第5引数ではHandles.SphereCapを指定し、ハンドルの形状を球にしています。

ここをHandles.CubeCapとして立方体を表示しようと思ってもなぜか2Dの四角形になってしまいます・・・(謎)

FreeMoveHandleの戻り値はVector3の移動値が返ってくるのでその値をdata.posに入れ直し、DataUpdateメソッドを呼び出します。

こうすることでハンドルをドラッグした先のVector3の値の位置にHandleDataを設定したゲームオブジェクトが移動する事になります。

FreeMoveHandleのサンプル

ScaleValueHandle

ScaleValueHandleは1つのfloat値を得られるハンドルを作成します。

引数はFreeMoveHandleとほぼ同じですがSnapとハンドルの形状の引数の位置が逆になります。

今回はfloat値をVector3の値に割り当てゲームオブジェクトのScaleを変更しています。

ScaleValueHandleのサンプル

Slider

Sliderを使用すると一方向にスライドさせるハンドルを表示します。

第1引数はハンドルの位置、第2引数はスライドさせる方向、第3引数はサイズ、第4引数がハンドルの形状、第5引数はSnapです。

↑のサンプルではハンドルを緑色にし、ゲームオブジェクトの位置+Vector3(0, 1, 0)からVector3(1, 0, 0)の方向にスライドさせるハンドルを表示しています。

Sliderのサンプル

Slider2D

Slider2Dを使用すると2方向に移動出来るハンドルを表示します。

第1引数がハンドルの位置、第2引数がハンドルの方向、第3引数が一つ目の移動出来る方向、第4引数が二つ目の移動出来る方向、第5引数がハンドルサイズ、第6引数がハンドルの形状、第7引数がSnap、第8引数がハンドルの周りに矩形を表示するかどうかです(2Dの薄い平面図が表示されます)。

スライドする1つ目をVector3(1, 0, 0)、2つ目をVector3(0, 1, 0)の方向にしています。

その為得られる値をdata.posに入れればX軸とY軸方向にスライドする事が出来ます。

Slider2Dのサンプル

原因不明ですが、ドラッグ開始時に現在の場所から右上の方向にワープしてしまいます・・・。

Disc

Discを使うとゲームオブジェクトの回転をするディスクハンドルを表示する事が出来ます。

第1引数がディスクの回転、第2引数がディスクの中心、第3引数が回転軸、第4引数がディスクのサイズ、第5引数がディスクを半分だけ表示するかどうか、第6引数がSnapです。

スクリプトを設定したゲームオブジェクトの回転をゲームオブジェクトの位置を中心にY軸で回転します。

戻り値をdata.rotに入れ、ゲームオブジェクトの角度を変更しています。

Discのサンプル

FreeRotateHandle

FreeRotateHandleは回転軸を意識せず自由に回転させるハンドルを表示します。

第1引数は角度、第2引数は中心位置、第3引数はサイズになります。

FreeRotateHandleのサンプル

PositionHandle

PositionHandleは位置変更のハンドルを表示する事が出来ます。

第1引数がハンドルの位置、第2引数がハンドルの角度です。

ハンドルはゲームオブジェクトのデフォルトのハンドルと同じなので、表示位置をX軸方向にずらしました。

data.posにはずらした分のデータを引いて入れます。

PositionHandleのサンプル

RadiusHandle

RadiusHandleは指定した半径の球のハンドルを表示します。

第1引数は角度、第2引数が位置、第3引数がサイズ、第4引数はハンドル以外の球の線を表示しないかどうか

RadiusHandleのサンプル

RotationHandle

RotationHandleはゲームオブジェクトを回転するハンドルを表示します。

第1引数は角度、第2引数が位置になります。

RotationHandle

ScaleHandle

ScaleHandleはゲームオブジェクトのScaleを変更するハンドルを表示します。

第1引数は変更するScale、第2引数がハンドル位置、第3引数がハンドルの角度、第4引数がハンドルサイズです。

ScaleHandleのサンプル

DrawLine

DrawLineを使うと2点間に線を引く事が出来ます。

第1引数が開始点、第2引数が終了点になります。

DrawLineサンプル

DrawLines

DrawLinesを使用すると複数の2点間に線を引く事が出来ます。

引数にはVector3型の配列を指定しますが、2点を1組にした配列にしておく必要があります。

↑の例では6点のVector3の点を作成しますが、lines[0]→lines[1]、lines[2]→lines[3]、lines[4]→lines[5]という3つの線を描きます。

DrawLinesのサンプル

DrawSolidRectangleWithOutline

DrawSolidRectangleWithOutlineを使うと四角形とその周りに太い線を表示する事が出来ます。

第1引数は矩形を作る4点かRect型の値、第2引数は矩形の面の色、第3引数はアウトラインの色になります。

↑の例ではDrawSolidRectangleWithOutlineを使う前にハンドルの色を白に設定し直しています。

これ以前にハンドルの色を変更していた場合、矩形の面の色とアウトラインの色がうまく反映されないことがあるので、

ハンドルをデフォルトの白色に設定し直しました。

矩形の面の色は赤の半透明、アウトラインは黄色に設定しています。

DrawSolidRectangleWithOutlineのサンプル

DrawDottedLine

DrawDottedLineを使用するとドットの線を表示する事が出来ます。

第1引数が開始点、第2引数が終了点、第3引数がラインの長さとライン間の幅になります。

DrawDottedLineのサンプル

DrawDottedLines

DrawDottedLinesを使用すると複数の2点間にドットの線を引く事が出来ます。

引数はDrawLinesとほぼ同じで、第2引数にはドットの長さとドット間の長さを指定します。

DrawDottedLinesのサンプル

DrawSolidArc

DrawSolidArcを使用すると扇形を表示する事が出来ます。

第1引数は位置、第2引数は円の法線(向いている方向)、第3引数は扇形を開始する方向、第4引数が扇形の角度、第5引数が円の半径です。

DrawSolidArcのサンプル

DrawWireArc

DrawWireArcはDrawSolidArcのワイヤーフレーム版で、引数は同じです。

DrawWireArcのサンプル

DrawSolidDisc

DrawSolidDiscを使用するとディスクを表示する事が出来ます。

第1引数は位置、第2引数は円の法線、第3引数は円の半径です。

DrawSolidDiscのサンプル

DrawWireDisc

DrawWireDiscはDrawSolidDiscのワイヤーフレーム版で引数は同じです。

DrawWireDiscのサンプル

DrawPolyLine

DrawPolyLineを使用すると複数点を繋いだ線を表示する事が出来ます。

引数にはVector3型の複数の点を指定します。

↑の例ではHandleDataのTransform型のpointsにゲームオブジェクトを設定し、その位置を繋いでいきます。

ヒエラルキーに複数のゲームオブジェクトを配置し、HandleDataのインスペクタにそれぞれのゲームオブジェクトを設定してください。

DrawPolyLineのサンプル

↑のようにゲームオブジェクトの位置が線でつながれました。

DrawAAPolyLine

DrawAAPolyLineはDrawPolyLineをアンチエイリアス(ギザギザ感がない)の線で表示します。

DrawAAPolyLineのサンプル

DrawAAConvexPolygon

DrawAAConvexPolygonを使用するとアンチエイリアスの線を繋いだ面にポリゴンを張ります。

DrawAAConvexPolygonのサンプル

DrawBezier

DrawBezierを使用するとベジェ曲線を表示する事が出来ます。

第1引数が始点、第2引数が終点、第3引数が接線の始点、第4引数が接線の終点、第5引数が色、第6引数が使用するテクスチャ、第7引数が幅になります。

ベジェ曲線はよくわからないので説明出来ません・・・・(^_^;)

DrawBezierのサンプル

Label

Labelを使用するとシーン上にラベルを表示する事が出来ます。

Lableは複数のコンストラクタが用意されているので、渡す引数の数と型がいくつかあります。

今回使用するのは第1引数に位置、第2引数に表示する文字列、第3引数にスタイルを設定します。

↑の例ではHandleDataのインスペクタのStyleを使用してラベルを表示します。

Styleの色を変更してラベルの色が変わる事が確認出来ます。

Labelのサンプル

BeginGUI、EndGUI

BeginGUIとEndGUIの範囲に囲まれた部分は2DのGUIの処理になります。

2Dのボタン等を表示する時はこの範囲に処理を記述します。

2Dのボタンを表示してみましょう。

GUILayout.BeginAreaとGUILayout.EndAreaで領域を作成し、data.areaTexに設定したテクスチャを表示しています。

領域の中にGUILayout.Buttonでボタンを作成し押した時にコンソールに文字列を表示しています。

2Dボタンサンプル

Button

Buttonを使用すると3Dのボタンを表示する事が出来ます。

第1引数が位置、第2引数が角度、第3引数が見た目のサイズ、第4引数がクリックを検出するサイズ、第5引数がハンドルの形状になります。

Buttonのサンプル

GetMainGameViewSize

GetMainGameViewSizeを使用すると現在のゲームビューの画面サイズを取得する事が出来ます。

GetMainGameViewSizeのサンプル

終わりに

今回Handleを使ってみましたがいまいち使い方がわからないものがありました。

UnityのスクリプトリファレンスではHandles.CubeCapの説明に

キューブを描き、これをハンドル関数に渡します。

と書いてあるんですが、ハンドル部分を描くだけでハンドル関数に渡すという意味がわかりませんでした。

またHandles.FreeMoveHandle等のハンドルを描画する為に使用する関数を引数に渡しますが、渡すハンドルの形状によってはうまく作用しない事があります。

あとは、ハンドルのカメラ関連の操作もわかりませんでした。

Handles.SetCamera、Handles.ClearCameraですね。

その他にもわからないものがありましたが、とりあえず試して出来たものだけを紹介しました・・・(-_-)

とりあえず量が多すぎて途中から紹介文以外のわたくしの言葉が減っていってますね・・・・、見る人にとってはいいかもしれません。

デフォルトのハンドル操作以外に自分で作成したハンドルを使ってみたい方は今回の記事を参考にしてみてください。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます