26
7

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 1 year has passed since last update.

QualiArtsAdvent Calendar 2022

Day 3

「え!UnityYAML読めないんですか?」

Last updated at Posted at 2022-12-02

なんて同僚たちにマウント取られる前にUnityYAMLの勉強をしておこうと思った記事です。
一応調べましたが、やっぱりよくわかりません。

QualiArtsアドカレ 3日目の記事になります。

UnityYAMLとは

UnityYAMLとは、Unityのアセットのシリアライズ形式の一つで、yaml記法のサブセットです。
Asset SerializationにForce Textを指定するとこの形式でprefabなどのアセットが保存されるようになります。

force text.png

とりあえずForce Textを選択しているものの、特にprefabは巨大なyamlになりがちで、読み方もよくわからないしで、ほとんど向き合ってきませんでした。
ところがしばらく前に、Unity公式から
Unity のシリアライズ言語 YAML を理解する
という記事が公開されました。ありがたいことに日本語翻訳されているのでまだ読んでない方は是非読んでみてください。

Unity のシリアライズ言語 YAML を理解する を読んでみて

上記記事の内容が素晴らしいので、一通り目を通してUnityYAMLを完全に理解した気持ちになれたので、手元のprefabを読んでみました。

CardBoxScreen.prefab(sample)
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1865014687417162
GameObject:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  serializedVersion: 6
  m_Component:
  - component: {fileID: 224475894893193696}
  - component: {fileID: 222259688764093502}
  - component: {fileID: 114916577866252144}
  m_Layer: 5
  m_Name: Text
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!224 &224475894893193696
RectTransform:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 1865014687417162}
  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 2527234515757153141}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
  m_AnchorMin: {x: 0.5, y: 0.5}
  m_AnchorMax: {x: 0.5, y: 0.5}
  m_AnchoredPosition: {x: 0, y: 215.39001}
  m_SizeDelta: {x: 366.41266, y: 203.70001}
  m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &222259688764093502
CanvasRenderer:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 1865014687417162}
  m_CullTransparentMesh: 0
--- !u!114 &114916577866252144
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 1865014687417162}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 
  m_Material: {fileID: 0}
  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
  m_RaycastTarget: 1
  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
  m_Maskable: 1
  m_OnCullStateChanged:
    m_PersistentCalls:
      m_Calls: []
  m_FontData:
    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
    m_FontSize: 50
    m_FontStyle: 0
    m_BestFit: 0
    m_MinSize: 0
    m_MaxSize: 69
    m_Alignment: 4
    m_AlignByGeometry: 0
    m_RichText: 1
    m_HorizontalOverflow: 1
    m_VerticalOverflow: 1
    m_LineSpacing: 1
  m_Text: "\x04\u30AB\u30FC\u30C9\u4E00\u89A70"
--- !u!114 &2281633851196779435
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 1794220058932668345}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 54274acba9bd3450992ce3a66d0e7af2, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 
  _root: {fileID: 3368266533159312908}
--- !u!114 &5223233202539212553
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 1794220058932668345}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: c3ddc448688d94df2b8f9019109edfc6, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 
  _view: {fileID: 2281633851196779435}
  _screenCommonRoot: {fileID: 6423277813639145140}
  _cardListPresenter: {fileID: 4475072414863852767}
--- !u!1001 &1793172451492897065
PrefabInstance:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications:
    - target: {fileID: 1400207620163216, guid: 094164b28ecc049328ef3063313e741b, type: 3}
      propertyPath: m_Name
      value: CardBoxScreen
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_RootOrder
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalPosition.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalPosition.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalPosition.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalRotation.w
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalRotation.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalRotation.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalRotation.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalEulerAnglesHint.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalEulerAnglesHint.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 2148239045628858729, guid: 094164b28ecc049328ef3063313e741b,
        type: 3}
      propertyPath: m_LocalEulerAnglesHint.z
      value: 0
      objectReference: {fileID: 0}
    m_RemovedComponents: []
  m_SourcePrefab: {fileID: 100100000, guid: 094164b28ecc049328ef3063313e741b, type: 3}
--- !u!1 &1794220058932668345 stripped
GameObject:
  m_CorrespondingSourceObject: {fileID: 1400207620163216, guid: 094164b28ecc049328ef3063313e741b,
    type: 3}
  m_PrefabInstance: {fileID: 1793172451492897065}
  m_PrefabAsset: {fileID: 0}
--- !u!114 &6423277813639145140 stripped
MonoBehaviour:
  m_CorrespondingSourceObject: {fileID: 4739671352265131933, guid: 094164b28ecc049328ef3063313e741b,
    type: 3}
  m_PrefabInstance: {fileID: 1793172451492897065}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 1794220058932668345}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: add964d6de6884f75a1f30247ae54694, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 
--- !u!224 &2527234515757153141 stripped
RectTransform:
  m_CorrespondingSourceObject: {fileID: 4318999042065406556, guid: 094164b28ecc049328ef3063313e741b,
    type: 3}
  m_PrefabInstance: {fileID: 1793172451492897065}
  m_PrefabAsset: {fileID: 0}
--- !u!225 &3368266533159312908 stripped
CanvasGroup:
  m_CorrespondingSourceObject: {fileID: 3917247981887962917, guid: 094164b28ecc049328ef3063313e741b,
    type: 3}
  m_PrefabInstance: {fileID: 1793172451492897065}
  m_PrefabAsset: {fileID: 0}
--- !u!1001 &2728508175332412409
PrefabInstance:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 2527234515757153141}
    m_Modifications:
    - target: {fileID: 3127823570204878437, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMax.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 3127823570204878437, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMax.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 3127823570204878437, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMin.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_Pivot.x
      value: 0.5
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_Pivot.y
      value: 0.5
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_RootOrder
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMax.x
      value: 0.5
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMax.y
      value: 0.5
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMin.x
      value: 0.5
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchorMin.y
      value: 0.5
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_SizeDelta.x
      value: 100
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_SizeDelta.y
      value: 100
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalScale.x
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalScale.y
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalScale.z
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalPosition.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalPosition.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalPosition.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalRotation.w
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalRotation.x
      value: -0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalRotation.y
      value: -0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalRotation.z
      value: -0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchoredPosition.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchoredPosition.y
      value: -120
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalEulerAnglesHint.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalEulerAnglesHint.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4720499058283198052, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_LocalEulerAnglesHint.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4732023361674043342, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_Size
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4821767156134577128, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_AnchoredPosition.x
      value: -0.0000038146973
      objectReference: {fileID: 0}
    - target: {fileID: 7042572429314006190, guid: 631e66137c7824aa79f18da746121ef2,
        type: 3}
      propertyPath: m_Name
      value: CardList
      objectReference: {fileID: 0}
    m_RemovedComponents: []
  m_SourcePrefab: {fileID: 100100000, guid: 631e66137c7824aa79f18da746121ef2, type: 3}
--- !u!114 &4475072414863852767 stripped
MonoBehaviour:
  m_CorrespondingSourceObject: {fileID: 2001635751693651750, guid: 631e66137c7824aa79f18da746121ef2,
    type: 3}
  m_PrefabInstance: {fileID: 2728508175332412409}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 0}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 7cd2f7b60e5044a60b6a926eefc18d83, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 

MonoBehaviourがいくつか付いている、ということ以外、僕の読解力では何もわかりませんでした・・・

UnityYAML読解補助ツールを作ってみる

わからなすぎたので次のような可視化ツールを作ってみました。

  • UnityYAMLの要素をTreeViewとして表示
  • !u!1のような記述を GameObject などのようなクラス名に置き換える
  • 参照やスクリプトに応じたIconを表示
  • GUIDをファイルパスに置き換える

movie3.gif

これなら完全にUnityYAMLを理解したような気がしてきます。
・・・本当はヒエラルキー構造も表したいところですが。

以下、細かい実装やハマりどころを紹介して行きますが、もし、とりあえず試しに動かしてみたいよっていう方は、以下のrepoからインストールしてみてください。
https://github.com/satanabe1/asset-yaml-tree-view
注意点として、yamlのパーサにYamlDotNetを採用しているので、README.mdに書いてある通り、 yamldotnet かYamlDotNetを取り込んでいる com.unity.visualscripting(1.6.0以上)を一緒にインストールする必要があります。

UnityYAML読解補助ツールを作るまで

UnityYAMLの読み込み

yamlパーサの選定

UnityYAMLの読み込みにはYamlDotNetを採用しました。これはYamlDotNetが.Net界隈で最もポピュラーなyamlパーサの一つであり、また、 com.unity.visualscripting にも取り込まれていて、Unity公式のUnity Registry内で完結することもできるためです。
ただし、com.unity.visualscriptingを使いたくないよってこともあり得るので、本家のyamldotnetにも対応してみました。
Assembly DefinitionのVersion Definesを使えば両対応は難しくありません。
define.png

Version Definesで定義したDefineでusingを切り分けます。

#if AYTV_YAMLDOTNET_11_2_OR_NEWER
using YamlDotNet.RepresentationModel;
#elif AYTV_VISUALSCRIPTING_1_6_0_OR_NEWER
using Unity.VisualScripting.YamlDotNet.RepresentationModel;
#else
#error require '"yamldotnet": "11.2.1"' or '"com.unity.visualscripting": "1.6.0"'
#endif

読み込み方

UnityYAMLを標準的なyamlパーサに流し込むと、ファイル先頭のヘッダーライン(%TAG !u! ...など)や、オブジェクトのヘッダー(--- !u!1 &1865014687417162など)の存在により、うまく読み込めません。
そこでアセットファイルを --- !u! の文字列で分割し、それぞれを独立したyamlとしてパーサに流し込むことで乗り越えます。 参考実装
--- !u! の行にも重要な情報があるので、捨てずにYamlDocumentとセットで取得しておくのがよさそうです。

TreeView表示

IMGUIのTreeViewを利用してみました。(今風にするのであればUIToolKitを使うべきだったかもしれません・・・。)
基本的にはこの辺の処理で、YamlDocumentのNodeの要素と、ほぼ1体1でAssetYamlTreeElementからなる木構造に変換しました。guidなどに関しては若干のオリジナリティを加えましたが、ほとんど意味はありません。
安直にTreeViewでyamlを表示すると以下のようになります。
スクリーンショット 2022-11-28 19.13.44.png
何もわかりやすくなってないですね。

ClassIdの解決

UnityYAMLのよくわからなさを助長している!u!XXXXの部分をまともなクラス名に変えてみます。
!u!XXXXの数字の部分XXXXは解説ではクラスIDと呼ばれています。クラスIDとクラス名の関係は こちらのドキュメント で紹介されています。
スクリーンショット 2022-11-29 9.57.34.png
とは言え、これを一つ一つハードコードしていくのも微妙なので、Unityの内部から拾ってきます。
Unity内では UnityType.FindTypeByPersistentTypeID(int id) というメソッドを通してクラスIDから型情報を取得できるようになっています。ただしUnityTypeはpublicクラスではないのでリフレクションが必要になります。
こんな感じでクラスIDからクラス名を取得するメソッドを実装しました。

private static string GetTypeNameByPersistentTypeID(int id) {
    const BindingFlags flags = BindingFlags.Public
                               | BindingFlags.Static
                               | BindingFlags.Instance
                               | BindingFlags.InvokeMethod
                               | BindingFlags.GetProperty;
    var assembly = Assembly.GetAssembly(typeof(MonoScript));
    var unityType = assembly.GetType("UnityEditor.UnityType");
    var findTypeByPersistentTypeID = unityType.GetMethod("FindTypeByPersistentTypeID", flags);
    var nameProperty = unityType.GetProperty("name", flags);
    var typeInstance = findTypeByPersistentTypeID?.Invoke(null, new object[] { id });
    return typeInstance != null ? nameProperty?.GetValue(typeInstance) as string : null;
}

あとは取得したクラス名と!u!XXXXの部分を置換してやれば、以下のように、人間にも優しい表示になります。
スクリーンショット 2022-11-29 10.08.31.png

Iconの適用

文字列だけではやっぱり直感的ではないのでIconも表示してみます。イイカンジのIconの取得というのも結構厄介で、いろんなメソッドを組み合わせることになります。(もっとシンプルに一発で取得する方法、募集中です)

使用したAPIは以下の通りです。

どれも微妙にできることとできないことが違うので、UnityYAML中のクラスIDやGUIDに応じたIconをサポートしようとすると、こんなことに・・・
https://github.com/satanabe1/asset-yaml-tree-view/blob/c124aee327882202b7c93c87b98acf7b8b48962e/Editor/AssetYamlTreeUtil.cs#L117-L146

アドカレネタに突貫で書いたので不要なところもありそうですが、これで取得できたIconを表示してみると以下のようになります。

スクリーンショット 2022-11-29 10.50.47.png

結構悪くない感じになってきました。

GUIDの解決

スクリーンショット 2022-11-29 10.56.28.png
guidのところの情報が重要な割に、人間にはナニモワカラナイ所なので、可能な限りファイルパスに置き換えてみます。
これは何も難しい話はなくて、guidというYamlNodeの配下にあるYamlScalerNodeの値を取得して、AssetDatabaseに問い合わせるだけです。
スクリーンショット 2022-11-29 13.19.16.png

ついでで、ダブルクリックでPrefabやScriptを開けるようにしてあげるとより親切でしょう。

// override TreeView.DoubleClickedItem
protected override void DoubleClickedItem(int id)
{
    base.DoubleClickedItem(id);
    var first = FindRows(new List<int> { id }).FirstOrDefault() as AssetYamlTreeViewItem;
    if (first?.Data?.AssetPath == null) return;
    AssetDatabase.OpenAsset(AssetDatabase.LoadMainAssetAtPath(first.Data.AssetPath));
}

FileIDの解決(未実装)

FileIDを使って、親子関係やComponentのアタッチ対象なども解決してあげると実用的なツールに近づきそう、という展望はありますが、今回は実装しませんでした。いつかモチベーションが上がったら・・・
スクリーンショット 2022-11-29 13.25.36.png

終わりに

ツールを使えば僕でもUnityYAMLの雰囲気を感じ取ることができるようになりました。
ただ、Unity上でしか表示できないっていうのは、本来僕が求めているところじゃなかったりします。
Chrome Extension化してGithub PullRequestのところで同様の可視化ができたらいいのにな、とか夢は広がりますが、それは今後の課題ということで・・・

以上です。

26
7
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
26
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?