Upgrade to Pro — share decks privately, control downloads, hide ads and more …

こわくないエディター拡張入門

 こわくないエディター拡張入門

unity1week online共有会 #13にて発表させていただいたスライドです。
動画等は配信をご確認ください。
https://youtu.be/COFWY3BrDEw?t=2786

ゲムシャリコ

October 14, 2023
Tweet

Other Decks in Technology

Transcript

  1. こわくない
    エディター拡張入門
    ゲムシャリコ
    2023/10/14 unity1week 共有会 #13 (お題: 1ボタン)

    View full-size slide

  2. 自己紹介
    • 情報系大学 2年生
    • ゲームプログラマー志望
    • unity1week参加 3回目
    @gameshalico
    ゲムシャリコ

    View full-size slide

  3. Orbit
    重力2Dアクション
    自転に沿って動いたり 公転に沿って動いたり
    総合10位(発表時)

    View full-size slide

  4. エディター拡張?
    Unityエディターをカスタマイズするもの
    ヒエラルキーの見た目を整えたり
    インスペクタにボタンを追加したり

    View full-size slide

  5. エディター拡張で時短
    ちま……ちま……
    インスペクターから値を調整
    ドラッグ移動で爆速調整

    View full-size slide

  6. Orbitでの実装
    書いたコードはこれだけ!

    View full-size slide

  7. なんだか難しそう?
    見慣れない構文や見たことない関数だらけで
    尻込みしてしまいがち?
    一回やってみると意外と単純
    作業効率UPで作品のクオリティもUP

    View full-size slide

  8. 作ってみよう : 2点間を移動するギミック
    本題ではないのでゲーム側の実装は割愛(配布あり)

    View full-size slide

  9. 今回作るもの
    ハンドルを使って目標点を移動できるようにする

    View full-size slide

  10. 実装
    using UnityEditor;
    using UnityEngine;
    [CustomEditor(typeof(MoveBetween))]
    public class MoveBetweenEditor : Editor
    {
    private void OnSceneGUI()
    {
    MoveBetween moveBetween = (MoveBetween)target;
    EditorGUI.BeginChangeCheck();
    Vector3 position =
    Handles.PositionHandle(moveBetween.destination, Quaternion.identity);
    if(EditorGUI.EndChangeCheck())
    {
    Undo.RecordObject(moveBetween, "Change Destination");
    moveBetween.destination = position;
    }
    }
    }

    View full-size slide

  11. Editorフォルダの作成
    「Editor」という名前のフォルダを作成する
    エディター拡張のScriptはここに入れる
    Editorフォルダ以下はビルドに含まれない
    Scripts
    Editor
    別のフォルダとして用意
    通常のスクリプト
    エディター拡張の
    スクリプト
    ※ 階層は自由
    参考: https://docs.unity3d.com/ja/2023.2/Manual/SpecialFolders.html

    View full-size slide

  12. using UnityEditor;
    エディター拡張に関するクラスは
    UnityEditor名前空間にある。
    using UnityEditorを忘れない。
    大体のIDEで補完してくれるので
    こんなのあったな、ぐらいでOK。
    ビルドに含まれない
    コードでのみ利用できる
    using UnityEditor;
    using UnityEngine;
    クラス等をグループ化して
    まとめるもの。
    各クラスはUnityEditor.Editor
    のような形で表現できるが、
    using で省略できる。
    名前空間
    参考: https://docs.unity3d.com/ScriptReference/UnityEditor.html

    View full-size slide

  13. [CustomEditor(typeof(XXX))]
    このクラスはXXX型のエディター拡張だよ、という宣言
    Unity側に教えてあげるイメージ
    指定した型の情報を取得する。
    型を変数に入れられる形に変換する。
    []で囲まれてるやつをAttributeといい、
    クラスやメンバーに情報を付加できる。
    typeof演算子 Attribute
    [CustomEditor(typeof(MoveBetween))]
    public class MoveBetweenEditor : Editor
    参考: https://docs.unity3d.com/ScriptReference/CustomEditor.html

    View full-size slide

  14. class XXX : Editor
    MonoBehaviourみたいなもの。
    MonoBehaviour(スクリプト)用の
    エディター拡張のクラスは、
    Editorクラスを継承 させる。
    [CustomEditor(typeof(MoveBetween))]
    public class MoveBetweenEditor : Editor
    {
    ……
    }
    ScriptableObjectの
    エディターを拡張するときも
    Editorクラスを継承して使う。
    ScriptableObject
    Editor
    MoveBetweenEditor
    継承


    参考: https://docs.unity3d.com/ScriptReference/Editor.html

    View full-size slide

  15. private void OnSceneGUI()
    {
    ……
    }
    OnSceneGUI()
    Unityから呼ばれるイベント関数。
    Updateみたいなイメージ。
    ヒエラルキー上で
    選択されているときに呼ばれる。
    シーンビューの表示を拡張する。
    インスペクターが表示されるときに呼ばれる
    インスペクターの機能を拡張できる。
    UIToolkitではCreateInspectorGUIを使う。
    OnInspectorGUI()
    2
    1
    「2」を選択中
    「2」のOnSceneGUIが呼ばれている
    参考: https://docs.unity3d.com/ScriptReference/Editor.html

    View full-size slide

  16. this.target
    選択している拡張対象のオブジェクト。
    Editorクラスのpublic変数。
    UnityEngine.Object型で入っているので
    キャスト(型変換)して使う必要がある。
    MoveBetween
    moveBetween =
    (MoveBetween)target;
    万物の祖。Unity関係のオブジェクトはだ
    いたいこいつを継承している。
    UnityEngine.Object
    「1」を選択中
    参考: https://docs.unity3d.com/ja/current/ScriptReference/Editor-target.html

    View full-size slide

  17. EditorGUI.BeginChangeCheck()
    EditorGUI.EndChangeCheck() : bool
    これに囲まれたGUI要素(後述)が
    変更されたかを検知する。
    EditorGUI.BeginChangeCheck();
    ……
    if(EditorGUI.EndChangeCheck())
    {
    ……
    }
    BeginChangeCheck
    EndChangeCheck
    PositionHandle 変更されてる?👀👀
    あったよ!(true)
    or
    なかったよ!(false)
    変更見てるよ!
    参考: https://docs.unity3d.com/ja/current/ScriptReference/EditorGUI.BeginChangeCheck.html

    View full-size slide

  18. Handles.PositionHandle
    (Vector3 position, Quaternion rotation) : Vector3
    移動できるハンドルを制御するGUI要素。
    EditorGUI.Begin/EndChangeCheck
    で囲み、変更を検知する。
    Vector3 position =
    Handles.PositionHandle(
    moveBetween.destination,
    Quaternion.identity
    );
    真ん中の半透明の面を
    ドラッグすると平面で移動
    できるって知ってました?
    私は知りませんでした。
    参考: https://docs.unity3d.com/ja/current/ScriptReference/Editor-target.html

    View full-size slide

  19. Undo.RecordObject
    (Object objectToUndo, string name)
    アンドゥ(Ctrl+Z)に対応させる。
    オブジェクトを変更する直前に呼び出す。
    Undo.RecordObject(
    moveBetween,
    "Change Destination“
    );
    moveBetween.destination = position;
    Edit>Undo History
    で確認できる
    参考: https://docs.unity3d.com/ja/current/ScriptReference/Undo.RecordObject.html

    View full-size slide

  20. ね?簡単でしょ?
    using UnityEditor;
    using UnityEngine;
    [CustomEditor(typeof(MoveBetween))]
    public class MoveBetweenEditor : Editor
    {
    private void OnSceneGUI()
    {
    MoveBetween moveBetween = (MoveBetween)target;
    EditorGUI.BeginChangeCheck();
    Vector3 position =
    Handles.PositionHandle(moveBetween.destination, Quaternion.identity);
    if(EditorGUI.EndChangeCheck())
    {
    Undo.RecordObject(moveBetween, "Change Destination");
    moveBetween.destination = position;
    }
    }
    }

    View full-size slide

  21. プロジェクト配布
    GitHubにて今回の
    プロジェクトを配布中
    今回紹介できなかった
    MoveBetweenの実装も
    コメント追記済み
    https://github.com/gameshalico/unity-custom-editor-sample-move-between

    View full-size slide

  22. 次のステップ
    • エディター拡張の記事を探して
    自分でも実装してみる
    • 公式のマニュアルを読んでみる
    • UIToolkitはいいぞ(情報少なめ)

    View full-size slide

  23. ご清聴ありがとうございました

    View full-size slide