Sceneビューにちょっと便利なGUIを表示させよう

# はじめに
Unityを使っていると同じ作業を何度も行うことがあり、なかなか面倒なことが多々あります。

そんなときはSceneビューにボタンを出しておいて、ボタンを押したときにコードを実行されるようにしておくと便利です。

今回の記事では、実際に使ってみて便利 (or 微妙) だと思ったGUIをいくつかご紹介しようと思います。

#Sceneビューにボタンを出す基本コード
以下のスクリプトをUnityプロジェクトに配置すると、Sceneビューにボタンが出てきます。

```NewBehaviourScript.cs
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Diagnostics;

[InitializeOnLoad]
public class NewBehaviourScript
{
    // ボタンの大きさ
    const float ButtonWidth = 120f;

    static NewBehaviourScript()
    {
        SceneView.onSceneGUIDelegate += (sceneView) =>
        {
            Handles.BeginGUI();
            if (GUILayout.Button("ボタンです", GUILayout.Width(ButtonWidth)))
            {
                //<--- ボタンが押されるとここが実行されます。--->//
                UnityEngine.Debug.Log("ボタンが押されました。");
            }
            Handles.EndGUI();
        };
    }
}
```
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/f5e1d703-d013-55ca-1be9-0ea9d34b87e8.png)

上記のスクリプトのここの部分を書き換えることでボタンが押されたときの挙動を変えることができます。

```NewBehaviourScript.cs
if (GUILayout.Button("ボタンです", GUILayout.Width(ButtonWidth)))
{
    //<--- ボタンが押されるとここが実行されます。--->//
    Debug.Log("ボタンが押されました。");
}
```

<br>
本記事では、上記のスクリプトをベースにして話を進めていきます。


# 特定のシーンを開くボタン
便利度 ★★★
ボタンが押されたら指定したシーンを開くというもの。　
Projectビュー上でシーンを選ぶのは結構めんどくさいですが、
Sceneビュー上にボタンを出しておけばシーンがワンクリックで開けるのでなかなか便利です。

```NewBehaviourScript.cs
if (GUILayout.Button("シーンを開く", GUILayout.Width(ButtonWidth)))
{
    EditorSceneManager.OpenScene("Assets/Test.unity");
}
```

# 選択オブジェクトのスケール値を2倍にするボタン
便利度 ★★☆
Sceneビュー上で選択しているオブジェクトのスケール値を2倍にするというもの。
手っ取り早くオブジェクトを拡大したいときなんかにとても便利です。

```NewBehaviourScript.cs
if (GUILayout.Button("Scale x2", GUILayout.Width(ButtonWidth)))
{
  if (Selection.activeGameObject != null)
  {
    Selection.activeGameObject.transform.localScale *= 2f;
    Undo.RegisterFullObjectHierarchyUndo(Selection.activeGameObject, "'" + Selection.activeGameObject.name + "'" + " Scale x2");
  }
}
```

# Sceneカメラの移動速度を変更するスライダー
便利度 ★★☆
AWSDからのSceneカメラ移動速度がスライダーから変更できるようになります。
Sceneカメラの移動速度が速すぎるときなど便利です。

![image](https://qiita-image-store.s3.amazonaws.com/0/44288/d3f6b39d-94fd-9cd5-6745-3beab135b394.png)


```NewBehaviourScript.cs
// スライダー用のメンバ変数
private const float MinCameraSpeed = 0.1f;
private const float MaxCameraSpeed = 9f;
private static float _cameraSpeed = 9f;

(中略)

/// <summary>
/// Sceneカメラの移動速度を変更するスライダー(Unity5.5.0b7)
/// </summary>
private static void CameraSpeedSlider()
{
    float width = 180f;
    float height = 42f;
    var windowRect = new Rect(Screen.width - width - 12f, Screen.height - height - 32f, width, height);

    GUI.Window(1, windowRect, (id) =>
    {
        _cameraSpeed = EditorGUILayout.Slider(_cameraSpeed, MinCameraSpeed, MaxCameraSpeed);
    }
    , "CameraSpeed");

    var asm = Assembly.Load("UnityEditor.dll");
    var typeSceneViewMotion = asm.GetType("UnityEditor.SceneViewMotion");

    Event e = null;
    SceneView.onSceneGUIDelegate += (sceneView) =>
    {
        e = Event.current;
    };
    
    var s_FlySpeed = (FieldInfo)typeSceneViewMotion.GetMember("s_FlySpeed", BindingFlags.Static | BindingFlags.NonPublic)[0];
    EditorApplication.update += () =>
    {
        if (e != null && e.shift)
        {
            // Shiftキーが押されていたら5倍速
            s_FlySpeed.SetValue(null, _cameraSpeed * 5f);
        }
        else
        {
            s_FlySpeed.SetValue(null, _cameraSpeed);
        }
    };
}
```
なお、Unityのバージョンが上がると使えなくなる可能性があります。

# SceneカメラをGameカメラに合わせるボタン
便利度 ★★☆
Gameビューのカメラの位置にSceneカメラを持っていきたいときとかに便利です。

```NewBehaviourScript.cs
if (GUILayout.Button("Sync Game to Scene", GUILayout.Width(ButtonWidth)))
{
    var sceneCamera = SceneView.GetAllSceneCameras()[0];
    var gameCamera = Camera.main;
    gameCamera.transform.position = sceneCamera.transform.position;
    gameCamera.transform.rotation = sceneCamera.transform.rotation;
}
```

# GameカメラをSceneカメラに合わせるボタン
便利度 ★★☆
こちらはGameカメラをSceneカメラに合わせるボタン

```NewBehaviourScript.cs
if (GUILayout.Button("Sync Scene to Game", GUILayout.Width(ButtonWidth)))
{
    var sceneView = SceneView.lastActiveSceneView;
    var gameCamera = Camera.main;
    sceneView.pivot = gameCamera.transform.position;
    sceneView.rotation = gameCamera.transform.rotation;
}
```


# 選択オブジェクトをSceneビューの中央に表示するボタン
便利度 ★☆☆
選択オブジェクトをSceneビューの中央に表示させるというもの。便利かも。

```NewBehaviourScript.cs
if (GUILayout.Button("選択オブジェクトを中央に表示", GUILayout.Width(ButtonWidth)))
{
    if (Selection.activeGameObject == null) { return; }
    SceneView.lastActiveSceneView.LookAt(Selection.activeGameObject.transform.position);
}
```

#立方体を生成するボタン
便利度 ★☆☆
仮素材として立方体を置きたいときに手っ取り早く立方体が作れます。　便利かも。

```NewBehaviourScript.cs
if (GUILayout.Button("Create Cube", GUILayout.Width(ButtonWidth)))
{
    EditorApplication.ExecuteMenuItem("GameObject/3D Object/Cube");
}
```

#特定のフォルダを開くボタン(Windows10)
便利度 ★☆☆
ボタンが押されたら指定したフォルダを開くというもの。
よく開くフォルダはここに登録しておくとちょっと便利です

```NewBehaviourScript.cs
if (GUILayout.Button("フォルダを開く", GUILayout.Width(ButtonWidth)))
{
  Process.Start(フォルダのパスをここに入れます);
}
```