1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Unity(C#)】ProjectWindowを更新する

Last updated at Posted at 2019-03-02

  
  
  
この記事は

『プログラミング完全未経験からUnityでの開発現場に迎え入れてもらえた世界一の幸せ者』

の記事です。そのつもりでお読みください。

ProjectWindowを更新

Inspectorの更新をまとめた記事はたくさんあったんですが、
ProjectWindowを更新する方法があまり見受けられなかったので詳しく調べました。

何のためにProjectWindowを更新したいの?

以前、編集ソフトとか使わずにUnityEditor上でGIF画像をサクッと作りたくて
プレイ中にキー入力で録画できるようなものを作りました。(人が作ったものを改造した)
記事→こちら
ダウンロード→こちら

その際に、
作成されたGIF画像がProjectWindowに反映されない
というめんどくさい現象が起きてました。(一度EditorWindowをたたまないと反映されない)

しかも、保存処理の終了するタイミングはPlayMode中とは限らないため、
メインスレッド(Updateとか)で終了するまで監視するということはできません。

その結果、
ProjectWindow上に何かが保存されたタイミングでエディタ拡張を利用してProjectWindowを更新
↑これをすれば解決するのでは?という仮説にたどり着きました。

結論から言うとできました。(もっと楽勝な方法があれば教えてください喜びます)

コード

public class Refresh : Editor
{
    //コンストラクタ
    static Refresh()
    {
        EditorApplication.update += ProjectWindowUpdate;
    }

    [RuntimeInitializeOnLoadMethod]
    static void ProjectWindowUpdate()
    {
        if (/*処理終了のフラグ*/)
        {
            AssetDatabase.Refresh();
        }

        if (EditorApplication.isPlaying ==false && /*処理終了のフラグ*/)
        {
            EditorApplication.update -= ProjectWindowUpdate;
        }
    }
}

AssetDatabase.Refresh

AssetDatabase.Refreshは かなりぼんやり説明するとProjectWindowを更新してくれます。
正直なところこれを更新したいタイミングで呼び出せばいいだけなんですが、
コードが上級者向け過ぎて私には理解できず、求めている処理の箇所にたどり着きませんでした。
なのでこんなめんどくさいこと調べて気付いたら朝の五時です。

誰か見つけたら教えてください。

本来はAssetDatabase.Refresh();この一行と名前空間書いて終わりです。
ただのあほやん

追記(翌日)
よくよく考えたら、今回の場合、PlayMode中に保存処理が終了するとは限らないので
更新したいタイミングでAssetDatabase.Refreshを呼び出すには
UnityEditorを更新する方法で合ってました。


AssetDatabase.RefreshのUnityのすくりぷとりふぁれんす↓

何かしら変更があったアセットをすべてインポートします。
コンテンツ内容が何かしら変更されたアセットや、
プロジェクトフォルダーに追加/削除されたアセットをインポートします。


[RuntimeInitializeOnLoadMethod]

[RuntimeInitializeOnLoadMethod]をメソッドの上に書くと
PlayModeになった瞬間に一回呼び出されます。

ちなみにコンストラクタはRefreshクラスの初期化処理を行っており、
最初にやっておいてほしい処理(初期設定みたいなもの)を書いてます。
上記コードの場合のコンストラクタはPlayModeになった瞬間に一度だけ呼び出されます。


[InitializeOnLoadMethod]

[InitializeOnLoadMethod]というのも存在しており、
[InitializeOnLoadMethod]をメソッドの上に書くと、
Editor画面を開いた瞬間(起動時)とPlayModeになった瞬間に一回呼び出されます。


[InitializeOnLoad]

[InitializeOnLoad]はクラスの上に書きます。
こんな感じです。

[InitializeOnLoad]
public class Refresh : Editor
{
    //コンストラクタ
    static Refresh()
    {
        EditorApplication.update += ProjectWindowUpdate;
    }

    static void ProjectWindowUpdate()
    {
        if (/*処理終了のフラグ*/)
        {
            AssetDatabase.Refresh();
        }

        if (EditorApplication.isPlaying ==false && /*処理終了のフラグ*/)
        {
            EditorApplication.update -= ProjectWindowUpdate;
        }
    }
}

[InitializeOnLoad]を上に書いたクラスは
Editor画面を開いた瞬間(起動時)とPlayModeになった瞬間に一回呼び出されます。

クラスごと呼び出されるのでコンストラクタも一緒に行われます。
つまり、上記コードの場合、コンストラクタは
Editor画面を開いた瞬間(起動時)とPlayModeになった瞬間に一度だけ呼び出されます。


2019/04/22 追記

静的コンストラクタ

どうやら、 この記事でまとめたInitializeOnLoad 属性
任意のstaticデータの初期化ついでに、1度だけ実行する必要がある処理に対して使うのが目的のようです。

ですので、文字通り、静的なコンストラクタを作らないとうまく動いてくれませんでした。
要するにInitializeOnLoad 属性を利用する際はコンストラクタにはstaticをつける必要があるということです。

unityのスクリプトリファレンスには

スタティックコンストラクターは、どのようなスタティック関数やクラスのインスタンスが使用されるよりも先に呼び出されることが保証されていますが、InitializeOnLoad 属性によりエディター起動時に呼び出されることを保証します。

とあります。


EditorApplication.update

EditorApplication.updateはUnityEditorで更新処理を行うためのデリゲートです。
登録したメソッドがUnityEditor上で秒間100回呼び出されるようになります。

ただ、それだと重くなったりするのかな~と思って
更新後、メソッドの登録を解除してます。

あまり重くなったように感じませんがどうなんでしょうか。
呼び出し回数も調整できたりするのかな?
誰か教えてください~

ProjectWindow変更時のデリゲート

実はProjectWindowの変更時のデリゲートは用意されています。
EditorApplication.projectChangedです。
なので、下記でいけるかと思いましたが無理でした。

[InitializeOnLoad]
public class Refresh : EditorWindow
{
    static Refresh()
    {
        EditorApplication.projectChanged += OnProjectChange;
    }

    static void OnProjectChange()
    {
        AssetDatabase.Refresh();
    }
}

EditorApplication.projectChangedに関する
Unityのすくりぷとりふぁれんすにcreatingとあったのでこれでいける!と確信しましたが、
これはどうやらEditor上でポチポチ操作したときの話のようです。

実際にEditorApplication.projectChangedを利用した上記のコードに変更し、
ProjectWindow上でCreateとかRenameとかしてみたところEditorが更新されました。

結論

EditorApplication.projectChangedに関するUnityのすくりぷとりふぁれんす↓

Actions that trigger this event include creating, renaming, or reparenting assets, as well as moving or renaming folders in the project. Note that the event is not raised immediately in response to these actions, but rather during the next update of the editor application.

EditorApplication.projectChangedがイベントを渡すのは次にEditorが更新されている最中だよ
って書いてます。

推測ですが、Editorが更新されるタイミング
ProjectWindow上のフォルダがProjectWindow上で何かしら変更されたタイミングです。

なので、UnityEditor上でスクリプトによって変更が加えられたProjectWindowに対して
スクリプトでProjectWindowを更新したいなら、
EditorApplication.projectChangedは使わずに
Editorの更新処理のデリゲートである
EditorApplication.updateにメソッドを渡す
しかないってことなんじゃないでしょーか。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?