Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在inspector中显示不可变(只读)结构的只读字段_C#_Unity3d - Fatal编程技术网

C# 在inspector中显示不可变(只读)结构的只读字段

C# 在inspector中显示不可变(只读)结构的只读字段,c#,unity3d,C#,Unity3d,我有以下不可变结构 [Serializable] public readonly struct Wind { /// <param name="windSpeed">The speed of the wind</param> /// <param name="rho">The density of the air, if not provided 15 degrees assumed aka 1.225f

我有以下不可变结构

[Serializable]
public readonly struct Wind
{
    /// <param name="windSpeed">The speed of the wind</param>
    /// <param name="rho">The density of the air, if not provided 15 degrees assumed aka 1.225f</param>
    public Wind(Vector3 windSpeed, float rho = 1.225f)
    {
        Speed = windSpeed;
        Rho = rho;
    }

    /// <summary>
    /// The speed of the wind [m/s]
    /// </summary>
    [DisplayReadOnly]
    public readonly Vector3 Speed;

    /// <summary>
    /// Density of the air [kg/m^3]
    /// </summary>
    [DisplayReadOnly]
    public readonly float Rho;
}
[可序列化]
公共只读结构风
{
///风速
///空气密度,如果未提供15度,则假定为1.225f
公共风(矢量3风速,浮标rho=1.225f)
{
速度=风速;
Rho=Rho;
}
/// 
///风速[m/s]
/// 
[显示只读]
公共只读矢量3速度;
/// 
///空气密度[kg/m^3]
/// 
[显示只读]
公共只读浮点Rho;
}
问题是Unity无法序列化只读字段,因此我遵循Anton Semchenko关于如何在inspector中将属性设置为仅显示这些字段的内容,以便于调试

以下是我制作的脚本:

自定义属性抽屉

[CustomPropertyDrawer(typeof(DisplayReadOnlyAttribute))]
public class DisplayReadOnlyAttributeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        DisplayReadOnlyAttribute att = (DisplayReadOnlyAttribute)attribute;
        object obj = property.serializedObject.targetObject;
        Type type = obj.GetType();
        FieldInfo field = type.GetField(property.propertyPath, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
        object val = field?.GetValue(obj);

        if (att.warningIfNull && (val == null || val.ToString().Equals("null")))
            val += " <-This value should NOT be NULL!";

        EditorGUI.LabelField(position, string.Format("{0}: {1}", label.text, val));
    }
}
[CustomPropertyDrawer(typeof(DisplayReadOnlyAttribute))]
公共类DisplayReadOnlyAttributeDrawer:PropertyDrawer
{
public override void OnGUI(Rect位置、SerializedProperty属性、GUIContent标签)
{
DisplayReadOnlyAttribute att=(DisplayReadOnlyAttribute)属性;
object obj=property.serializedObject.targetObject;
Type Type=obj.GetType();
FieldInfo field=type.GetField(property.propertyPath,BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
对象值=字段?.GetValue(obj);
if(att.warningIfNull&(val==null | | val.ToString().Equals(“null”))

val+=“因此,最后我使用了一个定制的inspector GUI,因为Unity由于限制无法将
PropertyAttribute
s挂钩到只读字段

[Serializable]
public readonly struct Wind
{
    /// <param name="windSpeed">The speed of the wind</param>
    /// <param name="rho">The density of the air, if not provided 15 degrees assumed aka 1.225f</param>
    public Wind(Vector3 windSpeed, float rho = 1.225f)
    {
        Speed = windSpeed;
        Rho = rho;
    }

    /// <summary>
    /// The speed of the wind [m/s]
    /// </summary>
    public readonly Vector3 Speed;

    /// <summary>
    /// Density of the air [kg/m^3]
    /// </summary>
    public readonly float Rho;

#if UNITY_EDITOR
    [CustomPropertyDrawer(typeof(Wind))]
    public class WindDrawer : PropertyDrawer
    {
        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            return EditorGUIUtility.singleLineHeight * 4 + 6;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            // Readonly fields are initialized at construction time so we need to wait for them
            bool readonlyInitialized = GameManager.LevelController;
            // Getting the readonly fields values
            var rho = typeof(Wind).GetField(nameof(Rho));
            var speed = typeof(Wind).GetField(nameof(Speed));

            var windRect = new Rect(position.x, position.y + 18, position.width, 16);
            var rhoRect = new Rect(position.x, position.y + 42, position.width, 16);
            var speedRect = new Rect(position.x, position.y + 66, position.width, 16);

            EditorGUI.BeginProperty(position, label, property);
            {
                EditorGUI.LabelField(windRect, label);
                EditorGUI.indentLevel++;

                EditorGUI.BeginDisabledGroup(true);
                {
                    EditorGUI.Vector3Field(rhoRect, nameof(Speed),
                    // Default value is Vector3.zero when the readonly field cannot be defined
                        readonlyInitialized ? (Vector3)speed.GetValue(GameManager.LevelController.WeatherController.Wind) : Vector3.zero);
                }
                EditorGUI.EndDisabledGroup();
            }
            EditorGUI.EndProperty();

            EditorGUI.BeginProperty(position, label, property);
            {
                EditorGUI.BeginDisabledGroup(true);
                {
                    EditorGUI.FloatField(speedRect, nameof(Rho),
                       // Default value is zero when the readonly field cannot be defined
                       readonlyInitialized ? (float)rho.GetValue(GameManager.LevelController.WeatherController.Wind) : 0.0f);
                }
                EditorGUI.EndDisabledGroup();
            }
            EditorGUI.indentLevel--;
            EditorGUI.EndProperty();
        }
    }
#endif
}
[可序列化]
公共只读结构风
{
///风速
///空气密度,如果未提供15度,则假定为1.225f
公共风(矢量3风速,浮标rho=1.225f)
{
速度=风速;
Rho=Rho;
}
/// 
///风速[m/s]
/// 
公共只读矢量3速度;
/// 
///空气密度[kg/m^3]
/// 
公共只读浮点Rho;
#如果统一编辑器
[CustomPropertyDrawer(类型(风))]
公共类WindDrawer:PropertyDrawer
{
公共覆盖浮点GetPropertyHeight(SerializedProperty属性,GUIContent标签)
{
返回EditorGUIUtility.singleLineHeight*4+6;
}
public override void OnGUI(Rect位置、SerializedProperty属性、GUIContent标签)
{
//只读字段在构造时初始化,所以我们需要等待它们
bool readonlyInitialized=GameManager.LevelController;
//获取只读字段值
var rho=类型(风).GetField(名称(rho));
var speed=类型(风)。GetField(名称(速度));
var windRect=新矩形(位置x,位置y+18,位置宽度,16);
var rhorrect=新的Rect(位置.x,位置.y+42,位置.width,16);
var speedRect=新矩形(位置x,位置y+66,位置宽度16);
EditorGUI.BeginProperty(位置、标签、属性);
{
EditorGUI.LabelField(windRect,label);
EditorGUI.indentLevel++;
EditorGUI.BeginDisabledGroup(true);
{
EditorGUI.Vector3字段(rhoRect,名称(速度),
//无法定义只读字段时,默认值为Vector3.0
readonlyInitialized?(Vector3)speed.GetValue(GameManager.LevelController.WeatherController.Wind):Vector3.zero);
}
EditorGUI.EndDisabledGroup();
}
EditorGUI.EndProperty();
EditorGUI.BeginProperty(位置、标签、属性);
{
EditorGUI.BeginDisabledGroup(true);
{
EditorGUI.FloatField(speedRect,nameof(Rho),
//无法定义只读字段时,默认值为零
readonlyInitialized?(float)rho.GetValue(GameManager.LevelController.WeatherController.Wind):0.0f;
}
EditorGUI.EndDisabledGroup();
}
EditorGUI.indentLevel--;
EditorGUI.EndProperty();
}
}
#恩迪夫
}
这将生成以下编辑器GUI:

瞧:编辑器窗口中显示了只读结构

我认为这不值得付出努力,如果你真的需要性能,那么就使用它,并在backingfield中附加一个readonly属性

[Serializable]
public struct Wind
{
    /// <param name="windSpeed">The speed of the wind</param>
    /// <param name="rho">The density of the air, if not provided 15 degrees assumed aka 1.225f</param>
    public Wind(Vector3 windSpeed, float rho = 1.225f)
    {
        Speed = windSpeed;
        Rho = rho;
    }

    /// <summary>
    /// The speed of the wind [m/s]
    /// </summary>
    public Vector3 Speed { get; }

    /// <summary>
    /// Density of the air [kg/m^3]
    /// </summary>
    public float Rho { get; }
}
[可序列化]
公共结构风
{
///风速
///空气密度,如果未提供15度,则假定为1.225f
公共风(矢量3风速,浮标rho=1.225f)
{
速度=风速;
Rho=Rho;
}
/// 
///风速[m/s]
/// 
公共向量3速度{get;}
/// 
///空气密度[kg/m^3]
/// 
公共浮点数Rho{get;}
}
[Serializable]
public struct Wind
{
    /// <param name="windSpeed">The speed of the wind</param>
    /// <param name="rho">The density of the air, if not provided 15 degrees assumed aka 1.225f</param>
    public Wind(Vector3 windSpeed, float rho = 1.225f)
    {
        Speed = windSpeed;
        Rho = rho;
    }

    /// <summary>
    /// The speed of the wind [m/s]
    /// </summary>
    public Vector3 Speed { get; }

    /// <summary>
    /// Density of the air [kg/m^3]
    /// </summary>
    public float Rho { get; }
}