![](https://habrastorage.org/files/f98/8f1/8e7/f988f18e79b84b38b24fca363e204f35.png)
この記事では、開発に役立ったいくつかの便利な機能と実装について説明します。 Unityにはすでに「デバッグログ」だけでなく、エディターウィンドウで必要なデータを展開して終了するための多くの方法があります。 Unityを初めて使用する場合、または知識を更新したい場合-「それをとる必要があります!」。
借方ログ。
Debugクラスを使用すると、テキスト、エラーの表示、線の描画、エディターの一時停止などができます。
例を考えてみましょう。
このメソッドは、敵が銃の射程内にいるときに呼び出されます。 その中で、武器メッシュは彼の方向に回転し、それに線を引きます。 これが発生するとすぐに、エディターは一時停止します。
コードスニペットを表示
// void LookOnEnemy() { meshPoint.LookAt(_currentEnemy.myTransform.position); // Debug.Log("Look on" + _currentEnemy.name, gameObject); // Debug.DrawLine(myTransform.position, _currentEnemy.myTransform.position); // Debug.Break(); // }
![](https://habrastorage.org/files/32a/7eb/4c5/32a7eb4c5a5241afa40dcdae9223c28f.png)
ギズモ
ギズモは視覚的なデバッグに使用されます。
例を考えてみましょう。
敵にとって無難なブロックは、通過不可能な青の立方体でペイントされます-赤(障害物に占有されている)または灰色(パスなし)、仕上げは青です。 エディターでマウスを使用して地球要素を選択すると、その隣接要素が緑色で強調表示されます(この場合、対角セルは隣接要素とは見なされず、隣接システムがパスの検索に使用されます)。
コードスニペットを表示
void OnDrawGizmos() { Gizmos.color = (walkable)? Color.blue: Color.red; if (rcost == 0) // Gizmos.color = Color.cyan; if (walkable && rcost < 0) // , Gizmos.color = Color.gray; for (int i = 0; i < Selection.gameObjects.Length; i++) { if (Selection.gameObjects[i] == gameObject) // { Gizmos.color = Color.green; drawLinks = true; } else drawLinks = false; } Gizmos.DrawCube(transform.position, Vector3.one * 0.5f); // if (drawLinks && Neighbors != null && Neighbors.Count > 0) // for (int i = 0; i < Neighbors.Count; ++i) if (Neighbors[i] != null) { Gizmos.DrawLine(transform.position, Neighbors[i].transform.position); Gizmos.DrawCube(Neighbors[i].transform.position, Vector3.one * 0.6f); } }
![](https://habrastorage.org/files/940/af2/b3c/940af2b3c7c3411cad2a8bb23951cf8a.png)
ギズモは、シーンウィンドウ(右上)のコンポーネントの種類ごとに個別にオン/オフできることに注意してください-最初の図では拡大表示されています。
ハンドル
ハンドルは、シーンウィンドウでオブジェクトを表示および操作するために使用されます。
以下は、小さなカーブエディタの段階的な例です。http : //catlikecoding.com/unity/tutorials/curves-and-splines/
BezierSplineInspectorクラスでOnSceneGUIが機能しない場合は、SceneView.onSceneGUIDelegateを介して実装を使用します。
コードスニペットを表示
void OnEnable() { SceneView.onSceneGUIDelegate += SceneUpdate; } void OnDisable() { SceneView.onSceneGUIDelegate -= SceneUpdate; } void SceneUpdate(SceneView sceneView) { ... Handles.color = Color.white; Handles.DrawBezier(p0, p1, c0, c1, Color.white, null, 2f); ... }
この拡張のおかげで、ウサギは円形の曲線を描きます。 そして、これらはすべてエディターで美しく設定されています。
![](https://habrastorage.org/files/f8c/532/cc3/f8c532cc31844238841d61c2d7b2850b.png)
属性
属性は、インスペクタの装飾、メニューの整理、ランタイムでの作業、コンポーネントの処理など、まったく異なる状況で役立ちます。 Unityの新しいバージョンごとに、それらはますます増えています。 属性は独立して記述できます。興味深い例を次に示します。https : //github.com/Thundernerd
メッシュの頂点を移動し、波の簡単なシミュレーションを作成するスクリプトの例を挙げましょう。 以下は、いくつかの変数(範囲)の値を制限し、ツールチップを表示する視覚的なヘルパーです。 プロパティ(ContextMenuItem)のコンテキストメニューを構成することもできます。
コードスニペットを表示
using UnityEngine; using System.Collections; public class SinWater : MonoBehaviour { [Header(" ")] public Vector2 range = new Vector2(0.1f, 1); [Tooltip(" ")] [ContextMenuItem("Reset", "resetTheValue")] public float speed = 1f; [Tooltip(" ")] public float maxY = 0.5f; [Range(0.1f, 1f)] public float offXMax = 0.1f; [Range(0.1f, 1f)] public float offYMax = 0.1f; [Range(0.1f, 1f)] public float offXSpeed = 0.1f; [Range(0.1f, 1f)] public float offYSpeed = 0.1f; private Mesh mesh; private Material mat; void Start() { mesh = GetComponent<MeshFilter>().mesh; mat = GetComponent<Renderer>().material; } void Update() { Vector3[] vertices = mesh.vertices; int i = 0; while (i < vertices.Length) { vertices[i].y = Mathf.Sin(Time.time * speed) * maxY; if (i % 2 == 0) vertices[i].y *= -1; i++; } mesh.vertices = vertices; Vector2 off = mat.GetTextureOffset("_MainTex"); off.x = Mathf.Sin(Time.time * offXSpeed)* offXMax; off.y = Mathf.Sin(Time.time * offYSpeed)* offYMax; mat.SetTextureOffset("_MainTex", off); } void resetTheValue() { speed = 1f; } }
![](https://habrastorage.org/files/3a8/5d8/889/3a85d888945048c7a9f445ab69aa3b7b.png)
私がよく使用する別の手法は、ContextMenuと遅延に関連しています。 30の実績を持つUIを構築したと仮定すると、それらは表示され、意図したとおりにスクロールします。 クラスへのリンクをリストに記入する必要があります。 名前を30回ドラッグし、説明を30回ドラッグする必要があります。 このプロセスは自動化できます。
コードスニペットを表示
[ContextMenu("AutoFill")] public void Fiil() { for (int i = 0; i < 30; ++i) { GameObject go = GameObject.Find("a" + i.ToString("#00")); achivs[i].image = go.transform.FindChild("aImage").GetComponent<Image>(); achivs[i].name = go.transform.FindChild("aName").GetComponent<Text>(); achivs[i].desription = go.transform.FindChild("aDescription").GetComponent<Text>(); } }
![](https://habrastorage.org/files/f1a/946/9ae/f1a9469ae93642c582b2410a060d7abb.gif)
独自のレベルエディター
ゲームに多数の類似した構造化されたレベルが含まれる場合(私の例では、これはTower Defenseです)。 膨大な時間をかけて、独自のレベルエディターを節約できます。
彼の主な仕事は、必要な情報だけを表示すること、インスペクターの単一のボタンを押すことで複数のアクションを表示すること、プロンプト、追加ファイルの読み取り/ダウンロードを行うことだと思います。
エディターファイル全体を提供するのではなく、理解のために一般的な構造のみを提供します。 本質は簡単です-キーストロークをキャッチする必要がある場合は、インスペクター、スライダー、ボタンで描画します。SceneView.onSceneGUIDelegateを使用します。 そして、ビデオは、特に私の場合のために、完全な機能を示します。
コードスニペットを表示
[CustomEditor(typeof(LevelEditor))] public class LevelEditorEditor : Editor { LevelEditor my; void OnEnable() { SceneView.onSceneGUIDelegate = WhenUpdate; } void WhenUpdate(SceneView sceneview) { Event e = Event.current; if (e.isKey && e.character == 'a') // – ChangeLand(e.mousePosition); … } public override void OnInspectorGUI() { DrawDefaultInspector(); my = (LevelEditor)target; if (my == null) return; … DrawMoney(); … } void DrawMoney() { GUILayout.Space(10); GUILayout.BeginVertical("box"); my.btMoney = EditorGUILayout.Foldout(my.btMoney, "Money"); if (my.btMoney) { my.level.gold = EditorGUILayout.IntSlider("Start Money Bank:", my.level.gold, 0, 1000); my.level.goldStart = EditorGUILayout.IntSlider("Coins Start:", my.level.goldStart, 0, 1000); my.level.goldMax = EditorGUILayout.IntSlider("Coins Max:", my.level.goldMax, 0, 40); my.level.goldMinTime = EditorGUILayout.Slider("Coins Min Time:", my.level.goldMinTime, 0, 100f); my.level.goldMaxTime = EditorGUILayout.Slider("Coins Max Time:", my.level.goldMaxTime, 0, 100f); } GUILayout.EndVertical(); } }