Programming」カテゴリーアーカイブ

プログラミング全般に関するカテゴリーです。

C#でgotoの使い方

forステートメント

C#でforの2重ループから抜けたい時、gotoステートメントを使って次のような書き方ができるみたいです。

サンプルコード

using System;

public class Example
{
  static public void Main ()
  {
    for (int i = 0; i < 5; ++i)
    {
      for (int j = 0; j < 5; ++j)
      {
        Console.WriteLine($"i={i}, j={j}");
        if (i + j > 5) goto Finish;
      }
    }

    Finish:
      Console.WriteLine("Finish");
  }
}

実行結果

i=0, j=0
i=0, j=1
i=0, j=2
i=0, j=3
i=0, j=4
i=1, j=0
i=1, j=1
i=1, j=2
i=1, j=3
i=1, j=4
i=2, j=0
i=2, j=1
i=2, j=2
i=2, j=3
i=2, j=4
Finish

switchステートメント

他にも、switchステートメントで

switch (n)
{
  case 1:
    // 実行したい内容1
    break;
  case 2:
    // 実行したい内容2
    goto case 1;
  default
    break;
}

のような書き方もできるみたいです。

慣れないと戸惑いそうですが、覚えておくと便利そうな気がします。

リンク

goto statement – C# Reference | Microsoft Docs
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto

UnityのInspectorで配列の順番を変更したい場合はReorderableList

Unityで配列を使いたい場合、

using UnityEngine;

public class Example : MonoBehaviour
{
  public string[] Array;
}

のような感じで実装すると、Inspectorには次のように表示されます。

これだけでもInspectorから配列のサイズと値を設定することができて便利ですが、要素の並び替えがしたいと思って実装方法を調べてみました。

ReorderableList

ということで、ReorderableListを使うとInspectorで並び替えができるようになるみたいです。

最低限の実装で並び替えだけしたい場合

とりあえず並び替えだけできれば良いという場合は、次のように実装できるみたいです。

using UnityEditor;
using UnityEditorInternal;

[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
  ReorderableList _reorderableList;

  void OnEnable()
  {
    var property = serializedObject.FindProperty("Array");
    _reorderableList = new ReorderableList(serializedObject, property, true, true, false, false);
  }

  public override void OnInspectorGUI()
  {
    base.OnInspectorGUI();

    serializedObject.Update();
    _reorderableList.DoLayoutList();
    serializedObject.ApplyModifiedProperties();
  }
}

Inspectorの表示は次のような感じになります。

Serialized Propertyに表示されているElementをドラッグで移動できるようになります。(移動した場合は上のArrayの値も変更されます。)

値も表示したい

値も表示したいという場合は、次のような感じでdrawElementCallbackを実装します。

void OnEnable()
{
  var property = serializedObject.FindProperty("Array");
  _reorderableList = new ReorderableList(serializedObject, property, true, true, false, false);

  _reorderableList.drawElementCallback = (rect, index, isActive, isFocused) =>
  {
    var element = property.GetArrayElementAtIndex(index);
    EditorGUI.PropertyField(rect, element);
  };
}

Inspectorの表示は次のような感じになります。

構造体を表示したい

構造体を表示したい場合は、Serializable属性を設定した上で、次のような感じで修正します。

using UnityEngine;

public class Example : MonoBehaviour
{ 
  [System.Serializable]
  public struct Struct
  { 
    public string text;
    public int value;
  }

  public Struct[] Array;
}
using UnityEditor;
using UnityEditorInternal;

[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
  ReorderableList _reorderableList;

  void OnEnable()
  {
    var property = serializedObject.FindProperty("Array");
    _reorderableList = new ReorderableList(serializedObject, property, true, true, false, false);

    _reorderableList.elementHeightCallback = (index) =>
    {
      var element = property.GetArrayElementAtIndex(index);
      return EditorGUI.GetPropertyHeight(element.FindPropertyRelative("text")) + EditorGUI.GetPropertyHeight(element.FindPropertyRelative("value"));
    };

    _reorderableList.drawElementCallback = (rect, index, isActive, isFocused) =>
    {
      var element = property.GetArrayElementAtIndex(index);

      rect.height = EditorGUI.GetPropertyHeight(element.FindPropertyRelative("text"));
      EditorGUI.PropertyField(rect, element.FindPropertyRelative("text"));

      rect.y += rect.height;
      rect.height = EditorGUI.GetPropertyHeight(element.FindPropertyRelative("value"));
      EditorGUI.PropertyField(rect, element.FindPropertyRelative("value"));
    };
  }

  public override void OnInspectorGUI()
  {
    base.OnInspectorGUI();

    serializedObject.Update();
    _reorderableList.DoLayoutList();
    serializedObject.ApplyModifiedProperties();
  }
}

Inspectorの表示は次のような感じになります。

もう少し真面目に実装したい場合

同じ設定が二重に表示されないようにしたい場合はHideInInspector属性を設定します。

[HideInInspector] public Struct[] Array;

ただ、このままではInspectorから配列のサイズが変更できなくなってしまうので、

_reorderableList = new ReorderableList(serializedObject, property);

とした上で、_reorderableListonAddCallbackonRemoveCallbackを実装すると良いみたいです。

UnityでビルドしたWebGLゲームのURLが知りたい場合

UnityでビルドしたWebGLのゲームで、実行時にURLが知りたい場合はApplication.absoluteURLを使って確認できるみたいです。

使い方

Debug.Log(Application.absoluteURL);

ちなみに、Android/iOS/UWPでビルドした場合、absoluteURLはdeep link URLになっているそうです。WebGL以外でabsoluteURLを参照する場合は注意してください。

リンク

Unity – Scripting API: Application.absoluteURL
https://docs.unity3d.com/ScriptReference/Application-absoluteURL.html

Unity – Scripting API: Application.deepLinkActivated
https://docs.unity3d.com/ScriptReference/Application-deepLinkActivated.html