So, I have been playing around with ScriptableObjects for a while Now, and I have created a Blanket Object to use as an Item Database, The thing I would like to know is if it is possible to Hide certain DataTypes if the Item does not use it.
So say for instance I create my Item Database, I create Two Items, One a Weapon and the other a Piece of Armour, Is there a way for me to have a Damage Float only Appear on the Weapon.
Hello,
there is two ways to achieve this.
The first way is making your custom editor for scriptable Objects. Customizing components and scriptable editors is weirdly addictive and allows you to achieve A LOT, included showing / hiding some serialized properties or attributes. I’m not sure if you’ll need a PropertyDrawer or a CustomEditor for scriptables, for components both work.
The second is using a [ConditionalHide] attribute above said variables. This one comes from a tutorial from Sebastian Lague. This is why I’ve kept the credits in the code I’m sharing you here :
Conditional Hide Attribute:
using System;
using UnityEngine;
//Original version of the ConditionalHideAttribute created by Brecht Lecluyse (www.brechtos.com)
//Modified by: Sebastian Lague
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property |
AttributeTargets.Class | AttributeTargets.Struct, Inherited = true)]
public class ConditionalHideAttribute : PropertyAttribute
{
public string conditionalSourceField;
public bool showIfTrue;
public int enumIndex;
public ConditionalHideAttribute(string boolVariableName, bool showIfTrue)
{
conditionalSourceField = boolVariableName;
this.showIfTrue = showIfTrue;
}
public ConditionalHideAttribute(string enumVariableName, int enumIndex)
{
conditionalSourceField = enumVariableName;
this.enumIndex = enumIndex;
}
}
Conditional Hide Property Drawer:
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//Original version of the ConditionalHideAttribute created by Brecht Lecluyse (www.brechtos.com)
//Modified by: Sebastian Lague
[CustomPropertyDrawer(typeof(ConditionalHideAttribute))]
public class ConditionalHidePropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute;
bool enabled = GetConditionalHideAttributeResult(condHAtt, property) == condHAtt.showIfTrue;
if (enabled)
{
EditorGUI.PropertyField(position, property, label, true);
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute;
bool enabled = GetConditionalHideAttributeResult(condHAtt, property) == condHAtt.showIfTrue;
if (enabled)
{
return EditorGUI.GetPropertyHeight(property, label);
}
//We want to undo the spacing added before and after the property
return -EditorGUIUtility.standardVerticalSpacing;
}
bool GetConditionalHideAttributeResult(ConditionalHideAttribute condHAtt, SerializedProperty property)
{
SerializedProperty sourcePropertyValue = null;
//Get the full relative property path of the sourcefield so we can have nested hiding.Use old method when dealing with arrays
if (!property.isArray)
{
string propertyPath = property.propertyPath; //returns the property path of the property we want to apply the attribute to
string conditionPath = propertyPath.Replace(property.name, condHAtt.conditionalSourceField); //changes the path to the conditionalsource property path
sourcePropertyValue = property.serializedObject.FindProperty(conditionPath);
//if the find failed->fall back to the old system
if (sourcePropertyValue == null)
{
//original implementation (doens't work with nested serializedObjects)
sourcePropertyValue = property.serializedObject.FindProperty(condHAtt.conditionalSourceField);
}
}
else
{
//original implementation (doens't work with nested serializedObjects)
sourcePropertyValue = property.serializedObject.FindProperty(condHAtt.conditionalSourceField);
}
if (sourcePropertyValue != null)
{
return CheckPropertyType(condHAtt,sourcePropertyValue);
}
return true;
}
bool CheckPropertyType(ConditionalHideAttribute condHAtt, SerializedProperty sourcePropertyValue)
{
//Note: add others for custom handling if desired
switch (sourcePropertyValue.propertyType)
{
case SerializedPropertyType.Boolean:
return sourcePropertyValue.boolValue;
case SerializedPropertyType.Enum:
return sourcePropertyValue.enumValueIndex == condHAtt.enumIndex;
default:
Debug.LogError("Data type of the property used for conditional hiding [" + sourcePropertyValue.propertyType + "] is currently not supported");
return true;
}
}
}