城崎温泉の名物外湯

城崎温泉に行く機会があり、名物の外湯巡りをしました。 天候は雨でしたが、傘をさしながら巡りました。

kinosaki-spa.gr.jp

まんだらの湯

6つの外湯の中で一番小さかったです。 露天風呂を体に2つの瓶型のお風呂があるのが特徴でした。

まんだらの湯

御所の湯

外流れる滝を見ることができる露天風呂です。 立ち湯があるのが個人的にとても良かったです。建物自体も新しいのかとても綺麗でした。

御所の湯

地蔵湯

宿のあるエリアから一番遠い(駅からは一番近い) 大きさは6つの中では中位。

地蔵湯

柳の湯

杉(もしくはひのき)で作られたお風呂で、サイズは小さいですが、木の香りが心地よいです。

柳の湯

一の湯

洞窟の中に露天風呂がある。 ここだけではないですが、露天風呂はぬるいので長く入ることができる。

一の湯

鴻の湯

こちらも露天風呂があります。 シンプルなお風呂。

鴻の湯

最後に

城崎温泉のお湯は基本的に熱めですので、長時間浸かるのが難しいです。ただし、露天風呂は水温が若干低めで、長く楽しむことができます。水の色は透明に近いです。熱いため、一度に多くの湯を巡るのではなく、1~2箇所ずつゆっくりと楽しむのがおすすめです。また、定休日があるため、事前に休みの日を確認することも大切です。

LinqのTakeとSkipについて

Linqで出会った、初見では理解が難しかった関数について、メモ代わりにブログに記載します。

Take

Takeはシーケンスの先頭から指定した数の要素を返します。

int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// Takeメソッドを使用して、最初の3つの要素を取得します。
var firstThreeNumbers = numbers.Take(3);

// 出力結果
0
1
2

Skip

Skipはシーケンスの先頭から指定した数の要素をスキップし、その後の要素を返します。

 // Skipメソッドを使用して、最初の3つの要素をスキップします。
var numbersAfterFirstThree = numbers.Skip(3);


// 出力結果
3
4
5
6
7
8
9

TakeやSkipメソッドは一般的に非常に効率的です。これらは遅延評価を活用しており、必要な要素だけを処理するため、大きなコレクションに対してもパフォーマンスが良好です。

【Unity】Settingに項目を追加する

独自のSettingを追加したい場合のやり方を調べてみました。

サンプルコード

次のコードはProjectSettingに項目を追加する最小限のコードになります。 SettingProviderを継承したクラスを作成し、コンストラクタなどを追加します。

public class AnotherSettingProvider : SettingsProvider
{ 
    public AnotherSettingProvider(string path, SettingsScope scopes, IEnumerable<string> keywords = null) : base(path,
        scopes, keywords)
    {
    }
    
    [SettingsProvider]
    public static SettingsProvider CreateAnotherSettingsProvider()
    {
        var provider = new AnotherSettingProvider("Preferences/Another Setting", SettingsScope.User);
        return provider;
    }
}

項目を追加する

SettingsScope

SettingsScopeはSettingsWindowかPreferencesWindowに項目するかどうかで設定が変わります。 SettingsScope.Userにして、今回はPreferencesWindowに項目を追加しています。

項目の中身を書く

OnGUIに項目の中身を記載します。

public override void OnGUI(string searchContext)
{
    EditorGUILayout.LabelField("This is another setting provider");
}

テキスト表示

保存する用のScriptableObjectを用意する

settingの内容を保存するScriptableObjectを用意します。

public class NewProjectSetting : ScriptableObject
{
    public bool hoge = false;
}

こちらのScritableObjectを表示するようAnotherSettingProviderを調整します。

 private static NewProjectSetting _settings;
 private SerializedObject _setting;

 private const string path = "Assets/AnotherSetting.asset";

public override void OnActivate(string searchContext, VisualElement rootElement)
{
    _settings = AssetDatabase.LoadAssetAtPath<NewProjectSetting>(path);
    if (_settings == null)
    {
        var setting = ScriptableObject.CreateInstance<NewProjectSetting>();
        AssetDatabase.CreateAsset(setting, path);
    }
    
    _setting = new SerializedObject(_settings);
}

public override void OnGUI(string searchContext)
{
    if (_settings == null) return;
    _setting.Update();
    EditorGUILayout.PropertyField(_setting.FindProperty("hoge"));
    _setting.ApplyModifiedProperties();
}

次のように表示されます。

項目追加

このScripatbleObjectを使って必要な処理を実装できます。

OnActivate

OnActivateメソッドは設定プロバイダがアクティブになる時(つまりユーザが設定ウィンドウを開いた時)に呼び出されます。 そのため、設定ウィンドウが開かれた際に必要なセットアップ、例えば設定のロードやUIの更新などのコードは、OnActivateメソッド内に配置するのが一般的です。

最後に

後は、設定した項目を必要な箇所で利用します。

Unity2023のAwaitableについて調べてみた

Awaitable型は非同期コードを公開するために使用され、Unityに特化した非同期の戻り値型も提供します。

docs.unity3d.com

Awaitableについて

UnityのAwaitableは、非同期コードの戻り値として特にUnity環境に適した型を提供します。これにより、非同期操作の完了まで待機するプロセスを表現でき、非同期メソッドの戻り値として利用されます。 例えば、Awaitable.NextFrameAsync(ct)メソッドは次のフレームまでの待機を非同期で実行し、UniTaskを返します。このUniTaskをawaitにより処理することで、非同期的に次のフレームまでの待機が可能です。

private async Awaitable HogeAsync(CancellationToken ct)
{
    Debug.Log(Time.frameCount);
    await Awaitable.NextFrameAsync(ct);
    Debug.Log("待機:" + Time.frameCount);
}

// 出力結果
1 // Start()が呼び出されたときのフレームカウント
待機:2 // 次のフレームでのフレームカウント

同じことをUniTaskでする場合は次のようなコードになります。

await UniTask.Yield();

その他

WaitForSecondsAsyncは指定秒待機します。

 private async Awaitable HogeAsync(CancellationToken ct)
{
    Debug.Log(Time.time);
    await Awaitable.WaitForSecondsAsync(seconds: 1f, cancellationToken: ct);
    Debug.Log("待機:" + Time.time);
}

キャンセル

CancellationTokenがキャンセルされた場合、OperationCanceledExceptionがスローされます。

private async Awaitable HogeAsync(CancellationToken ct)
{
    try
    {
        await Awaitable.WaitForSecondsAsync(seconds: 30f, cancellationToken: ct);

    }
    catch (OperationCanceledException)
    {
        Debug.Log("キャンセルされました");
    }
}

GWに京都競馬場へ行ってきました 【画像多め】

今年もGWに京都競馬場へ行ってきました。 正月開催に行って以来の京都競馬場です。 天気は最高によく、京都市内は30度を超えていたということで、淀もかなりの暑さになっていました。 日陰にいれば涼しいのですが、日中日向にいるのは結構つらい時期になってきました。

続きを読む

C#のLazy<T>について調べてみたメモ

Lazyクラスは、NET Frameworkで提供されているクラスで、そのインスタンスが最初にアクセスされるまで値の生成を遅延させることができます。 これは、値の生成に時間がかかる場合や、必ずしもすぐに値が必要とされない場合に有用です。 learn.microsoft.com

実装例

簡単な実装例は次のようになります。

private Lazy<string> lazyValue = new Lazy<string>(() =>
{
    Debug.Log("Lazy value is being calculated");
    return "Hello, World!";
});

void Start()
{
    Debug.Log("first");
    Debug.Log(lazyValue.Value);
    Debug.Log("second");
    Debug.Log(lazyValue.Value);
    Debug.Log("third");
    Debug.Log(lazyValue.Value);
}

// 出力結果
first
Lazy value is being calculated
Hello, World!
second
Hello, World!
third
Hello, World!

このコードは、lazyValueというLazy型のインスタンスの値に3回アクセスしています。 Lazy型の特性により、lazyValue.Valueに初めてアクセスされたときに値が計算され、その後のアクセスでは既に計算された値が返されます。

注意点

先ほどの例のように、Lazyは遅延初期化を提供しますが、一度計算された値は変更されません。 したがって、プロパティの値が都度変わる可能性がある場合、Lazyは適切な選択ではないかもしれないので注意が必要です。

【Unity】Hierarchy Windowで表示される特定のGameObjectの見た目を変更する

特定のComponentを持つGameObjectを視覚的にわかりやすくしたいという要望があり、少しやり方を調べてみました。

例コード

UnityエディタのHierarchyウィンドウで表示されるゲームオブジェクトの色を変更するクラスです。 特定のコンポーネントが存在する場合、そのゲームオブジェクトの色を変更します。 例として、Imageコンポーネントが存在する場合には色を変える場合のコードが次になります。

#if UNITY_EDITOR

using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

[InitializeOnLoad]
public class HierarchyColor
{
    static HierarchyColor()
    {
        EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
    }

    private static void HierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
    {
        var gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
        if (gameObject != null && gameObject.GetComponent<Image>() != null)
        {
            EditorGUI.DrawRect(selectionRect, Color.red);
            GUI.color = Color.black;
            EditorGUI.LabelField(selectionRect, gameObject.name,new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });
            GUI.color = Color.white;
        }
    }
}
#endif

InitializeOnLoad

エディタがロードされたときに一度だけ呼び出されます docs.unity3d.com

EditorApplication.hierarchyWindowItemOnGUI

Hierarchyウィンドウで各ゲームオブジェクトが描画されるたびに、特定のイベントが発生します。 このイベントのハンドラは、ゲームオブジェクトのインスタンスIDと描画領域のRectを引数として受け取ります。これらの情報を利用してハンドラ内でゲームオブジェクトの描画方法をカスタマイズすることが可能です。

docs.unity3d.com

EditorUtility.InstanceIDToObject

引数として与えられたインスタンスIDを使用して、そのIDに関連付けられたオブジェクトを取得します。

設定画像