memomem

備忘録・メモ置き場

PropertyDrawer にハマった

古い情報が多くてハマってしまった。

var enableProperty = property.FindPropertyRelative("enable");
enableProperty.boolValue = EditorGUI.Toggle(drawRect, "enable", enableProperty.boolValue);

みたいな書き方があるが、これだとインスペクターを複数選択したときに、勝手に値が変更されてしまう。 これよりも

EditorGUI.PropertyField(drawRect, property.FindPropertyRelative("enable"), new GUIContent("enable"), false);

の方がシンプルでどのtypeでも共通で使える為簡単。

また、要素が重なったりするときは、

public override float GetPropertyHeight(SerializedProperty property, GUIContent label)

の中などで記載していく必要がある。

雛形

[CustomPropertyDrawer(typeof(TweenAnimChildren))]
public class TweenAnimChildrenDrawer : PropertyDrawer
{
    Color playingColor = Color.green;

    public override void OnGUI(Rect drawRect, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(drawRect, label, property);
        //
        var isPlayingChainsProperty = property.FindPropertyRelative("isPlayingChains");
        var isPlayingParallelsProperty = property.FindPropertyRelative("isPlayingParallels");

        GUI.contentColor = isPlayingChainsProperty.boolValue ? playingColor : Color.white;
        drawRect.y += EditorGUIUtility.singleLineHeight + 2f;
        EditorGUI.PropertyField(drawRect, property.FindPropertyRelative("chains"), new GUIContent("chains"), true);

        float childGroupH = EditorGUI.GetPropertyHeight(property.FindPropertyRelative("chains"), true);
        drawRect.y += childGroupH;

        GUI.contentColor = isPlayingParallelsProperty.boolValue ? playingColor : Color.white;
        drawRect.y += EditorGUIUtility.singleLineHeight + 2f;
        EditorGUI.PropertyField(drawRect, property.FindPropertyRelative("parallels"), new GUIContent("parallels"), true);
        //
        GUI.contentColor = Color.white;
        EditorGUI.EndProperty();
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        var padding = 5;
        var lineH = EditorGUIUtility.singleLineHeight + 4;
        var height = 0f;

        var chainsGroupProperty = property.FindPropertyRelative("chains");
        var parallelsGroupProperty = property.FindPropertyRelative("parallels");

        float childGroupH = EditorGUI.GetPropertyHeight(chainsGroupProperty, true);
        float parallelsGroupH = EditorGUI.GetPropertyHeight(parallelsGroupProperty, true);
        height += childGroupH + parallelsGroupH + padding;

        height += lineH * 1.5f;
        return height + padding;
    }
}

下記のUnity公式がわかりやすい。

using UnityEditor;
using UnityEngine;

// IngredientDrawer
[CustomPropertyDrawer(typeof(Ingredient))]
public class IngredientDrawer : PropertyDrawer
{
    // 指定された矩形内のプロパティーを描画
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // 親プロパティーで BeginProperty / EndProperty を使用することは、    
    // プレハブオーバーライドロジックがプロパティー全体で機能することを意味します。
        EditorGUI.BeginProperty(position, label, property);

        // ラベルを描画
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        // 子のフィールドをインデントしない 
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // 矩形を計算
        var amountRect = new Rect(position.x, position.y, 30, position.height);
        var unitRect = new Rect(position.x + 35, position.y, 50, position.height);
        var nameRect = new Rect(position.x + 90, position.y, position.width - 90, position.height);

        // フィールドを描画 - GUIContent.none をそれぞれに渡すと、ラベルなしに描画されます
        EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none);
        EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none);
        EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);

        // インデントを元通りに戻します
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

docs.unity3d.com

参考

light11.hatenadiary.com

qiita.com

www.tangledrealitystudios.com

Unity Prefab 関連

プレハブがインポートされた時に呼び出される関数

using UnityEditor;
using UnityEngine;

public class Example : AssetPostprocessor
{
    private void OnPostprocessPrefab( GameObject root )
    {
        root.AddComponent<BoxCollider>();
    }
}

unity.com

Prefabを生成/上書き

PrefabUtility.SaveAsPrefabAsset(gameObject, assetPath);

Prefabを生成し関連づけ

PrefabUtility.SaveAsPrefabAssetAndConnect(gameObject, localPath, InteractionMode.UserAction, out prefabSuccess);

参考

docs.unity3d.com

light11.hatenadiary.com

qiita.com

DLLに実装されている関数を調べる

UnityでNativePluginを実装するときに、dllに実装されている関数を確認したい。

kazupon.org

上記ページに方法記載されている。下記は概要。

Visual Studio Installer で[C++ によるデスクトップ開発]がインストールされているかチェック。未インストールであればインストールを行う。

Visual Studio を起動し、[ツール] > [コマンドライン] > [開発者用 Power Shell]を選択。

Windows Power Shell が起動し

cd でdllのあるパスへ移動

dumpbin /exports XXXX.dll

を実行

Microsoft (R) COFF/PE Dumper Version 14.24.28314.0
Copyright (C) Microsoft Corporation.  All rights reserved.
Dump of file C:\Windows\System32\amsiproxy.dll
File Type: DLL
  Section contains the following exports for amsiproxy.dll
    00000000 characteristics
    918B159C time date stamp
        0.00 version
           1 ordinal base
           4 number of functions
           4 number of names
    ordinal hint RVA      name
          1    0 00001080 DllCanUnloadNow
          2    1 00001040 DllGetClassObject
          3    2 000010E0 DllRegisterServer
          4    3 00001110 DllUnregisterServer
  Summary
        1000 .data
        1000 .pdata
        2000 .rdata
        1000 .reloc
        1000 .rsrc
        1000 .text

のようにに実装されている関数が表示される。

DllCanUnloadNow, DllGetClassObject, DllRegisterServer, DllUnregisterServer が実装されている関数名ということがわかる。

その他参考

xoxopigs.com

RaceGameでのTelemetry

概要

大まかに分けるとSharedMemoryを使用する方法とUDPでの送信する方法がある。

家庭用ゲーム機はUDPでゲームから送信する方式が多い。

PCゲームではSharedMemoryでテレメトリーの内容をみて、そこからアプリでUDPで送信したりとか、アクチュエーター制御を行ったりすることが多い。 Sim Racing Telemetry もこのタイプ

Assetto Corsa

UDP [DOC] AC UDP Remote Telemetry | Assetto Corsa Mods

www.assettocorsa.net

Assetto corsa competizione

SharedMemory docs.google.com

D-BOXとの連動

Assetto corsa competizione には標準であり

support.d-box.com

support.d-box.com

github上でのC#での実装

UDPでの実装もありそう

github.com

github.com

github.com

github.com

その他

MotionSimのコミュニティ www.xsimulator.net

綺麗にできているモーションシミュレーター www.motionsimulation.com

Unity CinemachinePathBase.PositionUnits.PathUnits について

CinemachinePathBase.PositionUnits.PathUnits がイマイチわかりにくくて忘れるのでメモ

パス上の座標取得

パス上のポイント座標を取得する方法として

cinemachinePath.EvaluatePositionAtUnit(float pos, PositionUnits units);

がある

// posはパス上の距離を指定する
cinemachinePath.EvaluatePositionAtUnit(pos, PositionUnits.Distance);

// posはパス上のNormalizedされた値を指定する。0であれば始点、1であれば終点、0.5であれば中間点
cinemachinePath.EvaluatePositionAtUnit(pos, PositionUnits.Normalized);

// posはパス上のPathUnitsを指定する。
cinemachinePath.EvaluatePositionAtUnit(pos, PositionUnits.PathUnits);

PositionUnits.PathUnits

PositionUnits.PathUnitsは、パスを設定したWaypointsと関係する。

Waypointsが3つの時、

  • 0番目と1番目の位置の中間は0.5
  • 1番目と2番目の位置の中間は1.5
  • 終点は3.0

となる。

任意の座標に最も近いパス上の位置取得

ワールド座標から最も近いパス上の位置を取得する方法として

float v = cinemachinePath.FindClosestPoint(Vector3 p, int startSegment, int searchRadius, int stepsPerSegment);

がある。(searchRadius: -1 でパス全体から捜査)

この関数は PositionUnits.PathUnits を返す。

これを利用し

// pos に最も近いパス上の座標取得
public Vector3 CalcClosestPointFrom(Vector3 pos)
{
    float v = cinemachinePath.FindClosestPoint(pos, 0, -1, 20);
    return cinemachinePath.EvaluatePositionAtUnit(v, CinemachinePathBase.PositionUnits.PathUnits);
}
// pos に最も近いパス上のNormalizeされた値(パス全体の進捗)取得
public float CalcClosestProgressFrom(Vector3 pos)
{
    float v = cinemachinePath.FindClosestPoint(pos, 0, -1, 20);
    return cinemachinePath.FromPathNativeUnits(v, CinemachinePathBase.PositionUnits.Normalized);
}

ができる。

参考

docs.unity3d.com

UE5 で nanite が有効にならないとき

UE5で nanite を設定しているのに nanite ビジュアリゼーション でnaniteが表示されずに、フォールバックのメッシュのみ表示されるとき。

下記の設定を確認。

NaniteはDX12およびShaderModel6でのみ対応と。

次は、サポートされない Nanite マテリアル機能の一例です。

以下のレンダリング機能は現在サポートされていません。

以下を使用するビュー関連のオブジェクトのフィルタリング:

レイトレーシング機能はサポートされますが、光線は完全に詳細な Nanite メッシュではなく、粗い表現 (フォールバック メッシュ) と交差します。

docs.unrealengine.com