Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

PropertyDrawer and SerializedProperty aren't working correctly

Discussion in 'Scripting' started by tariasvillares, Jul 31, 2018.

  1. tariasvillares

    tariasvillares

    Joined:
    Jul 11, 2018
    Posts:
    13
    Hi guys! I need some help here.

    I'm trying to make this work, but for some reason my PropertyDrawer isn't working the way it should with my SerializedProperty. The custom PropertyDrawer is inside the Assets\Editor. Can you point what's wrong here? The PropertyDrawer.OnGUI() is not being executed...

    Many thanks =)

    Ps: the CustomEditor is a bit messy, because I was trying to figure out what was wrong, so please do not burn me, ok?

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class DisableablePropertyAttribute : PropertyAttribute {}
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. [CustomPropertyDrawer(typeof(DisableablePropertyAttribute))]
    7. public class DisableablePropertyDrawer : PropertyDrawer {
    8.  
    9.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    10.     {
    11.         Debug.Log(">>> Executing DisebleablePropertyDrawer.OnGUI()");
    12.         if (TargetSpawnerCustomEditor._spwnChanceSum > TargetSpawnerCustomEditor._maximumSpawnChanceSummation)
    13.         {
    14.             GUI.enabled = false;
    15.         }
    16.         else {
    17.             GUI.enabled = true;
    18.         }
    19.         EditorGUI.PropertyField(position, property, label);
    20.     }
    21.  
    22.     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    23.     {
    24.         Debug.Log(">>> Executing DisebleablePropertyDrawer.GetPropertyHeight()");
    25.         return EditorGUI.GetPropertyHeight(property, label);
    26.     }
    27. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. [CustomEditor(typeof(TargetSpawner))][CanEditMultipleObjects]
    7. public class TargetSpawnerCustomEditor : Editor {
    8.     private static float _spawnChanceSum = 0f;
    9.     public static float _maximumSpawnChanceSummation { get; } = 1f;
    10.     public float _minSpawnChance;      
    11.    
    12.     public static float _spwnChanceSum {
    13.         get {
    14.             return _spawnChanceSum;
    15.         }
    16.     }  
    17.  
    18.     public override void OnInspectorGUI()
    19.     {
    20.         TargetSpawner _tSpawner = (TargetSpawner)target;      
    21.         _minSpawnChance = EditorGUILayout.FloatField("Min spawn chance", _minSpawnChance);
    22.         ///*
    23.         if (_spawnChanceSum > 1f) {
    24.             _spawnChanceSum = 1f;
    25.         }
    26.         //*/
    27.         EditorGUILayout.LabelField("Maximum = " + _maximumSpawnChanceSummation);
    28.         EditorGUILayout.LabelField("Current value = " + _spawnChanceSum);
    29.         /*
    30.         _spawnChanceSum = 0f;
    31.         for (int i = 0; i < _tSpawner._spawnDataList.Count; i++) {
    32.             _spawnChanceSum += _tSpawner._spawnDataList[i]._spawnChance;
    33.             if (_spawnChanceSum > 1f)
    34.                 EditorGUI.BeginDisabledGroup(true);
    35.            
    36.             _tSpawner._spawnDataList[i]._spawnChance = EditorGUILayout.Slider(_tSpawner._spawnDataList[i]._tag, _tSpawner._spawnDataList[i]._spawnChance, 0.000f, _maximumSpawnChanceSummation);
    37.  
    38.             if (_spawnChanceSum <= 1f)
    39.                 EditorGUI.EndDisabledGroup();                      
    40.             EditorGUILayout.Space();
    41.             //_maxCumulativeChance -= _tSpawner._spawnDataList[i]._spawnChance;          
    42.         }
    43.         */
    44.  
    45.         //EditorGUI.BeginChangeCheck();
    46.         //if (EditorGUI.EndChangeCheck()) {
    47.  
    48.         //}
    49.         //*/
    50.  
    51.         //EditorGUILayout.LabelField("Sum = " + SpawnData._spawnChanceSum);
    52.         /*
    53.         for (int i = 0; i < _tSpawner._spawnDataList.Count; i++) {
    54.             if ((_maxTest + _tSpawner._spawnDataList[i]._spawnChance) == 1) {
    55.                 foreach (SpawnData _s in _tSpawner._spawnDataList) {
    56.  
    57.                 }
    58.             }      
    59.         }
    60.         //*/
    61.  
    62.         ///*
    63.         for (int i = 0; i < _tSpawner._spawnDataList.Count; i++)
    64.         {
    65.             _spawnChanceSum += _tSpawner._spawnDataList[i]._spawnChance;
    66.             _tSpawner._spawnDataList[i]._spawnChance = EditorGUILayout.Slider(_tSpawner._spawnDataList[i]._tag, _tSpawner._spawnDataList[i]._spawnChance, 0.000f, _maximumSpawnChanceSummation);          
    67.             EditorGUILayout.Space();        
    68.         }
    69.         //*/
    70.     }  
    71. }
    72.  
     
  2. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    How is your DisableablePropertyAttribute being implemented. Can we see an example code of it's use case?
     
  3. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Also remember to enable GUI after using the property field. Here's how I use it:

    Code (CSharp):
    1. public class ReadOnlyAttribute : PropertyAttribute
    2.     {
    3.  
    4.     }
    Code (CSharp):
    1.     [CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
    2.     public class ReadOnlyDrawer : PropertyDrawer
    3.     {
    4.         public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    5.         {
    6.             return EditorGUI.GetPropertyHeight(property, label, true);
    7.         }
    8.  
    9.         public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    10.         {
    11.             GUI.enabled = false;
    12.             EditorGUI.PropertyField(position, property, label, true);
    13.             GUI.enabled = true;
    14.         }
    15.     }
    Code (CSharp):
    1.  
    2.         [SerializeField, ReadOnly] private bool m_Transitioning = false;
    3.         [SerializeField, ReadOnly] private bool m_DoorOpen = false;
    4.  
     
  4. tariasvillares

    tariasvillares

    Joined:
    Jul 11, 2018
    Posts:
    13
    The DisableablePropertyAttribute is empty as I posted it earlier. And I add the GUI.enabled = true; after the EditorGUI.PropertyField(), but no luck at all =\

    I dunno why the ONGUI() is not being called...
     
  5. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Ooh I meant it's usage? Like where are you using the Property? Like you can see my use is here as an example:

    Code (CSharp):
    1. [SerializeField, ReadOnly] private bool m_Transitioning = false;
    2.         [SerializeField, ReadOnly] private bool m_DoorOpen = false;
    The only gotcha I know of with [CustomPropertyDrawer(typeof(DisableablePropertyAttribute))] is you need to set true on it's second parameter to allow children to also use this property drawer, but I don't think you'd have that issue. So I'm wondering whether you have other affectors on the property overriding your custom view.
     
  6. tariasvillares

    tariasvillares

    Joined:
    Jul 11, 2018
    Posts:
    13
    Well, I have the script modified by the custom Editor and the property being serialized right here:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [System.Serializable]
    4. public class SpawnData
    5. {
    6.     public string _tag;
    7.     [Range(0f, 1f), DisableableProperty]
    8.     public float _spawnChance;
    9. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Linq;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System.IO;
    6.  
    7. public class TargetSpawner : MonoBehaviour {
    8.     private static TargetSpawner _instance;
    9.  
    10.     [SerializeField, Range(0, 5)]
    11.     private float _timeBetweenTargetSpawn;
    12.  
    13.     [SerializeField, Range(0.5f, 10)]
    14.     private float _activeTime;
    15.  
    16.     [SerializeField]
    17.     private float _timer = 0f;
    18.  
    19.     private bool[] _occupiedSlot = new bool[9] {false, false, false, false, false, false, false, false, false};
    20.     private float[] _timeInsideSlot = new float[9] { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f};
    21.     private List<Sprite> _spriteList;
    22.     private Dictionary<int, AdventureBaseClass> _targetList = new Dictionary<int, AdventureBaseClass>();
    23.     private int _worldPositionIndex;
    24.     public GameObject _objPooler;
    25.     public List<SpawnData> _spawnDataList;
    26.      
    27.     void Awake()
    28.     {
    29.         if (_instance == null)
    30.         {
    31.             _instance = this;
    32.             //DontDestroyOnLoad(gameObject);
    33.         }
    34.         else {
    35.             Destroy(gameObject);
    36.         }
    37.     }
    38.  
    39.     public static TargetSpawner Instance {
    40.         get {
    41.             return _instance;
    42.         }
    43.     }
    44.  
    45.     void Start()
    46.     {
    47.         _spriteList = Storage.GetResourcesListFromPath<Sprite>("Sprites/Aventura_5/");    
    48.     }
    49.  
    50.     void Update()
    51.     {
    52.         _timer += Time.deltaTime;
    53.         if (_timer >= _timeBetweenTargetSpawn && _occupiedSlot.Contains(false)) {
    54.             do
    55.             {
    56.                 _worldPositionIndex = Random.Range(1, 10);            
    57.             } while (_occupiedSlot[_worldPositionIndex - 1] == true);
    58.             _occupiedSlot[_worldPositionIndex - 1] = true;
    59.             NeoHuntTarget _target = (NeoHuntTarget)_objPooler.GetComponent<ObjectPoolerScript>().spawnObjectFrom("NeoHuntTarget",              
    60.                     GameObject.Find("TargetNode_" + (_worldPositionIndex)).transform.position, GameObject.Find("TargetNode_" + (_worldPositionIndex)).transform.rotation);
    61.             float _cumulativeChance = 0.0f;
    62.             float _randomNumber = Random.Range(0f, 1f);
    63.             int _spriteIndex = 0;
    64.             for (int i = 0; i < _spawnDataList.Count; i++) {
    65.                 _cumulativeChance += _spawnDataList[i]._spawnChance/* / _spawnDataList.Count*/;
    66.                 Debug.Log("*** _randomNumber = " + _randomNumber + "\t_cumulativeChance = " + _cumulativeChance);
    67.                 if (_randomNumber < _cumulativeChance) {
    68.                     _spriteIndex = i;                
    69.                     break;
    70.                 }
    71.             }
    72.             Debug.Log(">>> _randomNumber = " + _randomNumber + "\t_spriteIndex = " + _spriteIndex + "\t_cumulativeChance = " + _cumulativeChance);        
    73.             _target._gameObj.GetComponent<SpriteRenderer>().sprite = _spriteList[_spriteIndex];
    74.             _target._gameObj.GetComponent<BoxCollider2D>().size = _target._gameObj.GetComponent<SpriteRenderer>().sprite.bounds.size;
    75.             _target._gameObj.GetComponent<BoxCollider2D>().offset = _target._gameObj.GetComponent<SpriteRenderer>().sprite.bounds.center;
    76.             _timer = 0f;                    
    77.             if (!_targetList.ContainsKey(_worldPositionIndex - 1))
    78.             {
    79.                 _targetList.Add(_worldPositionIndex - 1, _target);
    80.             }
    81.             else {
    82.                 _targetList[_worldPositionIndex - 1] = _target;
    83.             }
    84.         }    
    85.         for (int i = 0; i < 9; i++) {
    86.             if (_occupiedSlot[i]) {
    87.                 _timeInsideSlot[i] += Time.deltaTime;
    88.                 if (_timeInsideSlot[i] >= _activeTime) {
    89.                     _targetList[i]._gameObj.SetActive(false);                
    90.                     _occupiedSlot[i] = false;
    91.                     _timeInsideSlot[i] = 0f;
    92.                 }
    93.             }
    94.         }
    95.     }
    96. }
     
    Last edited: Jul 31, 2018
  7. tariasvillares

    tariasvillares

    Joined:
    Jul 11, 2018
    Posts:
    13
    A little bump here
     
  8. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Have you tried removing all the 'TargetSpawnerCustomEditor' parts of the code from the attribute and drawer. So there is only the amount like my example ReadOnly scripts to confirm that that aspect works first? From that point you could probably incrementally add bits until you find the gotcha.
     
  9. tariasvillares

    tariasvillares

    Joined:
    Jul 11, 2018
    Posts:
    13
    I'll try this approach right now. In fact, I'm thinking about create a new test project just to follow your advice and to figure out what is wrong here, I'll say something later thanks =)
     
    Last edited: Aug 1, 2018
    Nigey likes this.