Unity3dでアウトラインを描画するにはどうすればよいですか?


13

任意の高さの長方形をハイライトしようとしています。これを行う最も簡単な方法は、長方形の輪郭を描く別の「ボックス」ゲームオブジェクトを作成することだと思いました。

MeshRenderer + Transparent TextureとLineRendererの両方を使用して、四角形の4つのポイントの輪郭を描きました。どちらも非常に満足のいくものではありません。

ここに画像の説明を入力してください

(中央にラインレンダラー、右側にスケーリングされたキューブ)

これについて正しい方法は何ですか?私は左の長方形のようなものを得ようとしています-私が選んだ4つのポイントを通して固定幅のシンプルな境界線。

回答:


8

を使用しGUI.Box()ます。

2D四角形のみが必要な場合は、GUIが最適です。テクスチャとして単純な四角形を使用して新しいGUIStyleを作成し(もちろん、四角形の内側は透明である必要があります)、Border値が伸びないように設定し、を呼び出しますGUI.Box(new Rect(...),"",myGuiStyle);

Camera.WorldToScreenPoint何かを世界座標(3Dなど)で輪郭を描きたい場合は、Unityの世界座標ではyが下から上に、GUIではyが上から下に行くことに注意してください。

コード例:

void OnGUI()
{
    //top left point of rectangle
    Vector3 boxPosHiLeftWorld = new Vector3(0.5f, 12, 0);
    //bottom right point of rectangle
    Vector3 boxPosLowRightWorld = new Vector3(1.5f, 0, 0);

    Vector3 boxPosHiLeftCamera = Camera.main.WorldToScreenPoint(boxPosHiLeftWorld);
    Vector3 boxPosLowRightCamera = Camera.main.WorldToScreenPoint(boxPosLowRightWorld);

    float width = boxPosHiLeftCamera.x - boxPosLowRightCamera.x;
    float height = boxPosHiLeftCamera.y - boxPosLowRightCamera.y;


     GUI.Box(new Rect(boxPosHiLeftCamera.x, Screen.Height - boxPosHiLeftCamera.y, width, height),"", highlightBox);
}

誤解しない限り、GUI.Box()は常にシーン内のオブジェクトの上に描画されますか?ゲームオブジェクトの背後または部分的にGUI要素を持つことは可能ですか?
レイヴンドリーマー

はい、GUIは常に他のオブジェクトの後に描画されます。GUIの上に別のカメラをレンダリングするために使用できるハックがありますが、それはちょっと扱いにくいです。
ネバーマインド

この答えは私に必要なものを手に入れましたが、一般的なケースでこれを行うためのより良い方法があることを期待して、今のところ開いています。
レイヴンドリーマー

コードサンプルを追加する編集を受け入れ、GUIの逆さまのバグを修正しました。
ネバーマインド

1

以下は、非シェーダーアプローチです。

2Dボックスは4本の線にすぎないと考えてください。各線は1次元のみに引き伸ばされます(他の2次元はエッジの断面です)。これは、実際にボックスを構築する場合に似ており、すべて同じ断面サイズの可変長の木材をつなぎ合わせています。

それを念頭に置いBoxBuilderて、GameObjectにアタッチすると、4つの子GameObjectsを作成および管理するコンポーネント、たとえばを考案できます。各子ゲームオブジェクトはボックスエッジの1つであり、1次元のみに引き伸ばされた3Dキューブにすることができます。定義されたレベルを使用するwidthと、4つの子エッジの必要な配置と不均一なスケールを計算できます。それは多くのだろう、、...、 、、などのコードの一種。heightBoxBuilderpos.x=w/2pos.y=h/2scale.x=hscale.y=w

2次元のみを要求していると思いますが、必要に応じてこの同じ考え方を3次元ボックスに適用できることに注意してください。ここでは、BoxBuilder12の子エッジを作成および管理する必要がありますが、1つのローカルディメンションで各エッジのみをスケーリングします。


実行可能ですが、あまりにも複雑です。
ネバーマインド

私はこのようにそれをしなければならなかった場合、私は単に... 4ラインレンダラーを使用したい
レイヴンドリーマー

ただし、これは深度を適切に処理します。
DuckMaestro

1

簡単な方法は、2つのパスを持つシェーダーを使用することです。最初のパスは、頂点シェーダーを使用してオブジェクトを少し拡大し、ピクセルシェーダーを使用して、アウトラインに必要な色に一致する単色に色付けします。次に、2番目のパスが通常のレンダリングを実行します。


あなたが意味するものをより良く説明するためのコード例を教えていただけますか
レイヴンドリーマー

これは、原点が幾何学的中心にある凸状オブジェクト(長方形など)でのみ機能します。
rootlocus

1

3Dキューブの「ストローク」を作成する必要があることを除いて、アウトラインの作成と同じ問題があり、オンラインで他に見たことのない新しい方法を見つけました。

下の画像には、輪郭のある2つの形状があります。右側のものはLineRendererで構築されたキューブで、常にユーザーの方向を向く平らな面を構築します。この方法は非常にグリッチで、顔を構成する三角形を模倣したランダムな「ストローク」が表示されました。

左側の1つは、アウトラインのように見えるものを構築する12個の細い立方体を備えた「革新」です。アウトラインの「ストローク」のサイズを変更するには、12個の細い立方体のそれぞれの2辺のサイズを拡大/縮小する必要があります。これは2Dアウトラインでも機能します。素材を塗って色と出来上がりを変えるだけです!

2つの異なるアウトライン

この画像では、このキューブの構造の詳細を見ることができます。これはすべて実行時に作成できますが、手作業で作成し、プレハブとして使用しました。

細部


0

私は現在同じ問題に直面していますが、私のソリューションはまさにDuckMaestroとRaven Dreamerが提案したものです-実行時に4つの子オブジェクトを作成し、それぞれが境界線の側面を表し、それぞれにラインレンダラーをアタッチするスクリプトを持っています。

私の場合、オブジェクト(カスタムテキストフィールド用のテキストメッシュ[メッシュレンダラーを使用])を維持するために、常に境界線のサイズを変更する必要があったため、更新するたびにこれを行いました。


float width = Mathf.Max(renderer.bounds.size.x + paddingX * 2, minWidth);      
float x = renderer.bounds.center.x - width / 2;
float height = renderer.bounds.size.y + paddingY * 2;
float y = renderer.bounds.center.y - height / 2;

AlterBorder(0, new Vector3(x - thickness / 2, y, 0), new Vector3(x + width + thickness / 2, y, 0)); //Bottom edge going left to right
AlterBorder(1, new Vector3(x + width, y + thickness / 2, 0), new Vector3(x + width, y + height - thickness / 2, 0)); //Right edge going bottom to top
AlterBorder(2, new Vector3(x + width + thickness / 2, y + height, 0), new Vector3(x - thickness / 2, y + height, 0)); //Top edge going right to left
AlterBorder(3, new Vector3(x, y + height - thickness / 2, 0), new Vector3(x, y + thickness / 2, 0)); //Left edge going top to bottom

AlterBorder() 適切なラインレンダラー(最初のパラメーターで指定)にアクセスし、その開始と終了をそれぞれ最初と2番目のベクトルに設定します。

rendererサイズの参照として使用したことに注意してください。ただし、x、yが左上隅であれば、任意の長方形を使用できます。

これが本当にうまくいくと言うことから、3軸すべてで境界線オブジェクトを簡単に動かすことができるので(ゲームを回転させても、ラインレンダラーは常にカメラに面しているので変に見えません)、実装するのは難しくありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.