渋谷ほととぎす通信

新しいこと、枯れたこと問わず大庭が興味を持ったものを調査、生活の効率を求める完全趣味の技術ブログ。基礎を大事にしています。

UIElementsのStyleSheetインスタンスは保持してはいけない


開発環境をUnity2019にアップグレードしたし、新機能のUIElementsを始めました。

公式のブログを読みながら進めています。

本記事はUIElementsに関する落とし穴共有です。

StyleSheetのフィールド保持

何も気にせず、StyleSheetインスタンスをフィールドに保持してしまいました。
以下のような感じで。

StyleSheet _stylesheet;

void OnEnable()
{
    _stylesheet = AssetDatabase.LoadAssetPath<StyleSheet>("Assets/Editor/Hoge/Hoge.uss");

    var label = new Label("test");
    label.styleSheets.Add(stylesheet);
}

ussファイル更新ができなくなる

ussファイルを変更するとこの通りエラーが起きてしまう。

MissingReferenceException: The object of type 'StyleSheet' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
UnityEngine.Object.get_name () (at /Users/builduser/buildslave/unity/build/Runtime/Export/Scripting/UnityEngineObject.bindings.cs:189)
UnityEngine.UIElements.StyleSheets.StyleSheetCache.GetPropertyID (UnityEngine.UIElements.StyleSheet sheet, UnityEngine.UIElements.StyleRule rule, System.Int32 index) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/StyleSheets/StyleSheetCache.cs:333)
UnityEngine.UIElements.StyleSheets.StyleSheetCache.GetPropertyIDs (UnityEngine.UIElements.StyleSheet sheet, System.Int32 ruleIndex) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/StyleSheets/StyleSheetCache.cs:253)
UnityEngine.UIElements.VisualTreeStyleUpdaterTraversal.ProcessMatchedRules (UnityEngine.UIElements.VisualElement element, System.Collections.Generic.List`1[T] matchingSelectors) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/VisualTreeStyleUpdater.cs:313)
UnityEngine.UIElements.VisualTreeStyleUpdaterTraversal.TraverseRecursive (UnityEngine.UIElements.VisualElement element, System.Int32 depth) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/VisualTreeStyleUpdater.cs:248)
UnityEngine.UIElements.StyleSheets.HierarchyTraversal.Recurse (UnityEngine.UIElements.VisualElement element, System.Int32 depth) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/HierarchyTraversal.cs:24)
UnityEngine.UIElements.VisualTreeStyleUpdaterTraversal.TraverseRecursive (UnityEngine.UIElements.VisualElement element, System.Int32 depth) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/VisualTreeStyleUpdater.cs:271)
UnityEngine.UIElements.StyleSheets.HierarchyTraversal.Recurse (UnityEngine.UIElements.VisualElement element, System.Int32 depth) (at 

StyleSheetはローカル変数で使用

このようにローカル変数に保持しておけば問題は起きません。
ussファイルを変更するとシームレスに見た目の更新が入ります。

void OnEnable()
{
    var stylesheet = AssetDatabase.LoadAssetPath<StyleSheet>("Assets/Editor/Hoge/Hoge.uss");
    var label = new Label("test");
    label.styleSheets.Add(stylesheet);
}

最後に

まだ始めたばかりでよくわからないUIElementsですが、uxml、ussで構造と見た目を作っていく感じは、今までのIMGUIとは全く違うアプローチです。

またHTML/CSSのような馴染みもあるため、自分の武器にすべく完全理解しようと思います。

以上