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. Dismiss Notice

Custom Class Editor Questions

Discussion in 'Scripting' started by lo-94, Feb 9, 2015.

  1. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    Hello all,

    So I made a custom Ability class that contains all of the information needed for abilities in a pickup item. I then made a custom editor in the inspector which begins with:

    Code (csharp):
    1.  
    2. Ability settings = (Ability)target;
    3.  
    My question is, because this editor targets the Ability class, I have to drag the Ability class script onto the abilityPickup object, which then gives me access to all of the custom gui settings I put in. My question is, how do I get the settings object I declared into the script on the option that will contain the functions for when it collides? Essentially, on collide, I want to be able to send a message to the player that will pass a type Ability of the settings that I set within the inspector

    I hope that was clear

    Thanks for the help
     
  2. tango209

    tango209

    Joined:
    Feb 23, 2011
    Posts:
    379
    A custom inspector just changes the view into your class.

    You handle collisions like always, with OnTriggerXXX or OnCollisionXXX methods.
     
  3. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    So are you setting the constructor settings when new is called on that class for that GameObject when you call something like:

    Code (csharp):
    1.  
    2. settings.castTime = EditorGUILayout.IntField("Experience", settings.castTime);
    3.  
     
  4. tango209

    tango209

    Joined:
    Feb 23, 2011
    Posts:
    379
    Since it's a MonoBehaviour, I set initial values in Start() or Awake().
     
  5. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    So I'm confused....
    Anyone else have any input?
     
  6. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    I can provide more information regarding the issue if needed
     
  7. tango209

    tango209

    Joined:
    Feb 23, 2011
    Posts:
    379
    Is Ability a plain old class or does it derive from MonoBehaviour? Can you post your classes? It's not clear how you've got this setup.
     
  8. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    Indeed I can
    Thanks for the help btw
    Always appreciated

    Ability class:
    Code (csharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class Ability : MonoBehaviour{
    7.     public enum dmgType{
    8.         physical,
    9.         poison,
    10.         frost,
    11.         fire,
    12.         water,
    13.         electric,
    14.         darkmatter
    15.     }
    16.     public enum atkType{
    17.         melee,
    18.         ranged,
    19.         aura
    20.     }
    21.  
    22.     public enum AuraType{
    23.         effectSelf,
    24.         effectTeamRadius,
    25.         effectEnemiesRadius,
    26.         effectAllEnemies,
    27.         effectAllTeam
    28.     }
    29.  
    30.     public enum AuraDetails{
    31.         healing,
    32.         damage,
    33.         buff,
    34.         healingAndDamage,
    35.         healingAndBuff,
    36.         buffAndDamage,
    37.         all
    38.     }
    39.  
    40.     public enum trajectoryType{
    41.         travelUntilHit,
    42.         travelUntilRange,
    43.         travelUntilEvent,
    44.     }
    45.  
    46.     public enum TypeEvent{
    47.         buttonPress,
    48.         time
    49.     }
    50.  
    51.     public enum RicochetType{
    52.         goUntilTime,
    53.         goUntilNumHits,
    54.         goUntilRange
    55.     }
    56.  
    57.     public int id;
    58.     public atkType attackType;
    59.     public AuraType auraType;
    60.     public dmgType damageType;
    61.     public int dmgAmount;
    62.     public int abilityLevel;
    63.     public int healAmount;
    64.     public int abilityXP = 0;
    65.     public bool overTime;
    66.     public float duration;
    67.     public float increment;
    68.     public int percentChanceDOT;
    69.  
    70.     //melee information
    71.     public float abilityWidth;
    72.     public float abilityHeight;
    73.  
    74.  
    75.     //ranged information
    76.     public float abilityInitialSpeed;
    77.     public float abilityAcceleration;
    78.     public float abilityMaxSpeed;
    79.     public float maxRange;
    80.     public int projectileLimit;
    81.     public GameObject attackSprite;
    82.     public trajectoryType travelUntil;
    83.     public TypeEvent typeEvent;
    84.     public bool ricochet;
    85.     public RicochetType ricochetType;
    86.     public float projectileTimeLimit;
    87.     public int projectileHitLimit;
    88.  
    89.  
    90.  
    91.  
    92.     //aura information
    93.     public float radius;
    94.     public AuraDetails auraDetails;
    95.  
    96.  
    97.     public float atkCooldown;
    98.     public bool onCooldown;
    99.  
    100.     public Animation atkAnimation;
    101.     public AudioClip atkSound;
    102.  
    103.     public void resetCooldown(){
    104.         onCooldown = false;
    105.     }
    106.  
    107. }
    108.  
    Ability Editor
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEditor;
    5. [System.Serializable]
    6. [CustomEditor(typeof(Ability))]
    7.  
    8. public class abilityEditor : Editor {
    9.         public override void OnInspectorGUI ()
    10.     {
    11.         Ability settings = (Ability)target;
    12.  
    13.         settings.attackType = (Ability.atkType)EditorGUILayout.EnumPopup("Attack Type", settings.attackType);
    14.  
    15.         if(settings.attackType == Ability.atkType.ranged){
    16.  
    17.             settings.damageType = (Ability.dmgType)EditorGUILayout.EnumPopup("Damage Type", settings.damageType);
    18.  
    19.             settings.abilityLevel = EditorGUILayout.IntField("Level", settings.abilityLevel);
    20.  
    21.             settings.abilityInitialSpeed = EditorGUILayout.FloatField("Initial Speed", settings.abilityInitialSpeed);
    22.            
    23.             settings.abilityMaxSpeed = EditorGUILayout.FloatField("Max Speed", settings.abilityMaxSpeed);
    24.            
    25.             settings.abilityAcceleration = EditorGUILayout.FloatField("Ability Acceleration", settings.abilityAcceleration);
    26.  
    27.             settings.travelUntil = (Ability.trajectoryType)EditorGUILayout.EnumPopup ("Travel Type", settings.travelUntil);
    28.  
    29.             if(settings.travelUntil == Ability.trajectoryType.travelUntilEvent){
    30.  
    31.                 settings.typeEvent = (Ability.TypeEvent) EditorGUILayout.EnumPopup ("Event Type", settings.typeEvent);
    32.  
    33.                 if(settings.typeEvent == Ability.TypeEvent.time){
    34.  
    35.                     settings.projectileTimeLimit = EditorGUILayout.FloatField("Time", settings.projectileTimeLimit);
    36.        
    37.                     settings.ricochet = true;
    38.  
    39.                 }
    40.  
    41.             }
    42.  
    43.             if(settings.travelUntil == Ability.trajectoryType.travelUntilHit){
    44.                
    45.                 settings.projectileLimit = EditorGUILayout.IntField ("Projectile Limit", settings.projectileLimit);
    46.  
    47.                 settings.ricochet = EditorGUILayout.Toggle("Ricochet?", settings.ricochet);
    48.  
    49.                 if(settings.ricochet){
    50.  
    51.                     settings.ricochetType = Ability.RicochetType.goUntilNumHits;
    52.  
    53.                     settings.projectileHitLimit = EditorGUILayout.IntField("Num Hits", settings.projectileHitLimit);
    54.  
    55.                 }
    56.                
    57.             }
    58.            
    59.             else if(settings.travelUntil == Ability.trajectoryType.travelUntilRange){
    60.                
    61.                 settings.maxRange = EditorGUILayout.FloatField("Range", settings.maxRange);
    62.                 settings.ricochet = EditorGUILayout.Toggle("Ricochet?", settings.ricochet);
    63.                
    64.                 if(settings.ricochet){
    65.                    
    66.                     settings.ricochetType = Ability.RicochetType.goUntilRange;
    67.                    
    68.                 }
    69.                
    70.             }
    71.  
    72.             settings.overTime = EditorGUILayout.BeginToggleGroup("Damage Over Time", settings.overTime);
    73.  
    74.             settings.dmgAmount = EditorGUILayout.IntField("   -Damage", settings.dmgAmount);
    75.  
    76.             settings.duration = EditorGUILayout.FloatField ("   -Duration", settings.duration);
    77.  
    78.             settings.duration = EditorGUILayout.FloatField ("   -Increment", settings.increment);
    79.  
    80.             settings.percentChanceDOT = EditorGUILayout.IntField("   -% Chance", settings.percentChanceDOT);
    81.  
    82.             EditorGUILayout.EndToggleGroup();
    83.  
    84.  
    85.         }
    86.  
    87.         else if(settings.attackType == Ability.atkType.melee){
    88.  
    89.             settings.damageType = (Ability.dmgType)EditorGUILayout.EnumPopup("Damage Type", settings.damageType);
    90.  
    91.             settings.dmgAmount = EditorGUILayout.IntField("Damage", settings.dmgAmount);
    92.  
    93.             settings.abilityLevel = EditorGUILayout.IntField("Level", settings.abilityLevel);
    94.  
    95.         }
    96.  
    97.         else if(settings.attackType == Ability.atkType.aura){
    98.  
    99.             settings.auraType = (Ability.AuraType)EditorGUILayout.EnumPopup ("Aura Type", settings.auraType);
    100.  
    101.             settings.auraDetails = (Ability.AuraDetails)EditorGUILayout.EnumPopup ("Aura Details", settings.auraDetails);
    102.  
    103.             //conditional to open damage options
    104.             if(settings.auraDetails == Ability.AuraDetails.damage || settings.auraDetails == Ability.AuraDetails.buffAndDamage || settings.auraDetails == Ability.AuraDetails.healingAndDamage || settings.auraDetails == Ability.AuraDetails.all){
    105.  
    106.                 settings.damageType = (Ability.dmgType)EditorGUILayout.EnumPopup("Damage Type", settings.damageType);
    107.  
    108.                 settings.dmgAmount = EditorGUILayout.IntField("Damage", settings.dmgAmount);
    109.  
    110.             }
    111.  
    112.  
    113.  
    114.         }
    115.  
    116.  
    117.     }
    118.  
    119.  
    120. }
    121.  
     
  9. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    Also, I should mention this editor's initial use is intended for pickup items. So I essentially want to be able to assign the pickup object to hold this information, so on collide I can send a message to the players function setAbility(Ability newAbility) to set the new ability.
     
  10. tango209

    tango209

    Joined:
    Feb 23, 2011
    Posts:
    379
    1) Create a plain old C# class to hold the actual data you are interested in and only have a variable in your monobehaviour for it (Data in the example below).
    2) Update the editor class to use the settings.Data instead of settings.
    3) Add a method to do a shallow copy of the AbilityData, otherwise if the pickup's data changes so will your players data since it is a reference. (ShallowCopy in AbilityData below).
    4) Add OnCollisionEnter to the pickup object that hosts the Ability monobehaviour, check to see if it was the player that collided and if so, shallow copy the data to its Ability monobehaviours' Data object.

    The code below works in this manner.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEditor;
    4.  
    5. [System.Serializable]
    6. [CustomEditor(typeof(Ability))]
    7. public class abilityEditor : Editor
    8. {
    9.   public override void OnInspectorGUI()
    10.   {
    11.     Ability settings = (Ability)target;
    12.     settings.Data.attackType = (AbilityData.atkType)EditorGUILayout.EnumPopup("Attack Type", settings.Data.attackType);
    13.     if (settings.Data.attackType == AbilityData.atkType.ranged)
    14.     {
    15.       settings.Data.damageType = (AbilityData.dmgType)EditorGUILayout.EnumPopup("Damage Type", settings.Data.damageType);
    16.       settings.Data.abilityLevel = EditorGUILayout.IntField("Level", settings.Data.abilityLevel);
    17.       settings.Data.abilityInitialSpeed = EditorGUILayout.FloatField("Initial Speed", settings.Data.abilityInitialSpeed);
    18.       settings.Data.abilityMaxSpeed = EditorGUILayout.FloatField("Max Speed", settings.Data.abilityMaxSpeed);
    19.       settings.Data.abilityAcceleration = EditorGUILayout.FloatField("AbilityData Acceleration", settings.Data.abilityAcceleration);
    20.       settings.Data.travelUntil = (AbilityData.trajectoryType)EditorGUILayout.EnumPopup("Travel Type", settings.Data.travelUntil);
    21.       if (settings.Data.travelUntil == AbilityData.trajectoryType.travelUntilEvent)
    22.       {
    23.         settings.Data.typeEvent = (AbilityData.TypeEvent)EditorGUILayout.EnumPopup("Event Type", settings.Data.typeEvent);
    24.         if (settings.Data.typeEvent == AbilityData.TypeEvent.time)
    25.         {
    26.           settings.Data.projectileTimeLimit = EditorGUILayout.FloatField("Time", settings.Data.projectileTimeLimit);
    27.           settings.Data.ricochet = true;
    28.         }
    29.       }
    30.       if (settings.Data.travelUntil == AbilityData.trajectoryType.travelUntilHit)
    31.       {
    32.         settings.Data.projectileLimit = EditorGUILayout.IntField("Projectile Limit", settings.Data.projectileLimit);
    33.         settings.Data.ricochet = EditorGUILayout.Toggle("Ricochet?", settings.Data.ricochet);
    34.         if (settings.Data.ricochet)
    35.         {
    36.           settings.Data.ricochetType = AbilityData.RicochetType.goUntilNumHits;
    37.           settings.Data.projectileHitLimit = EditorGUILayout.IntField("Num Hits", settings.Data.projectileHitLimit);
    38.         }
    39.       }
    40.       else if (settings.Data.travelUntil == AbilityData.trajectoryType.travelUntilRange)
    41.       {
    42.         settings.Data.maxRange = EditorGUILayout.FloatField("Range", settings.Data.maxRange);
    43.         settings.Data.ricochet = EditorGUILayout.Toggle("Ricochet?", settings.Data.ricochet);
    44.         if (settings.Data.ricochet)
    45.         {
    46.           settings.Data.ricochetType = AbilityData.RicochetType.goUntilRange;
    47.         }
    48.       }
    49.       settings.Data.overTime = EditorGUILayout.BeginToggleGroup("Damage Over Time", settings.Data.overTime);
    50.       settings.Data.dmgAmount = EditorGUILayout.IntField("   -Damage", settings.Data.dmgAmount);
    51.       settings.Data.duration = EditorGUILayout.FloatField("   -Duration", settings.Data.duration);
    52.       settings.Data.duration = EditorGUILayout.FloatField("   -Increment", settings.Data.increment);
    53.       settings.Data.percentChanceDOT = EditorGUILayout.IntField("   -% Chance", settings.Data.percentChanceDOT);
    54.       EditorGUILayout.EndToggleGroup();
    55.     }
    56.     else if (settings.Data.attackType == AbilityData.atkType.melee)
    57.     {
    58.       settings.Data.damageType = (AbilityData.dmgType)EditorGUILayout.EnumPopup("Damage Type", settings.Data.damageType);
    59.       settings.Data.dmgAmount = EditorGUILayout.IntField("Damage", settings.Data.dmgAmount);
    60.       settings.Data.abilityLevel = EditorGUILayout.IntField("Level", settings.Data.abilityLevel);
    61.     }
    62.     else if (settings.Data.attackType == AbilityData.atkType.aura)
    63.     {
    64.       settings.Data.auraType = (AbilityData.AuraType)EditorGUILayout.EnumPopup("Aura Type", settings.Data.auraType);
    65.       settings.Data.auraDetails = (AbilityData.AuraDetails)EditorGUILayout.EnumPopup("Aura Details", settings.Data.auraDetails);
    66.       //conditional to open damage options
    67.       if (settings.Data.auraDetails == AbilityData.AuraDetails.damage || settings.Data.auraDetails == AbilityData.AuraDetails.buffAndDamage || settings.Data.auraDetails == AbilityData.AuraDetails.healingAndDamage || settings.Data.auraDetails == AbilityData.AuraDetails.all)
    68.       {
    69.         settings.Data.damageType = (AbilityData.dmgType)EditorGUILayout.EnumPopup("Damage Type", settings.Data.damageType);
    70.         settings.Data.dmgAmount = EditorGUILayout.IntField("Damage", settings.Data.dmgAmount);
    71.       }
    72.     }
    73.   }
    74. }
    75.  
    Code (CSharp):
    1. public class Ability : MonoBehaviour
    2. {
    3.   public AbilityData Data = new AbilityData();
    4.  
    5.   public void resetCooldown()
    6.   {
    7.     this.Data.onCooldown = false;
    8.   }
    9.  
    10.   public void OnCollisionEnter(Collision collision)
    11.   {
    12.     // See if we have collided with the player
    13.     if (collision.collider.gameObject.layer == 12)
    14.     {
    15.       Player player = collision.collider.gameObject.GetComponent<Player>();
    16.       player.Ability.Data = this.Data.ShallowCopy();
    17.     }
    18.   }
    19. }
    Code (CSharp):
    1. public class AbilityData
    2. {
    3.   public enum dmgType
    4.   {
    5.     physical,
    6.     poison,
    7.     frost,
    8.     fire,
    9.     water,
    10.     electric,
    11.     darkmatter
    12.   }
    13.   public enum atkType
    14.   {
    15.     melee,
    16.     ranged,
    17.     aura
    18.   }
    19.   public enum AuraType
    20.   {
    21.     effectSelf,
    22.     effectTeamRadius,
    23.     effectEnemiesRadius,
    24.     effectAllEnemies,
    25.     effectAllTeam
    26.   }
    27.   public enum AuraDetails
    28.   {
    29.     healing,
    30.     damage,
    31.     buff,
    32.     healingAndDamage,
    33.     healingAndBuff,
    34.     buffAndDamage,
    35.     all
    36.   }
    37.   public enum trajectoryType
    38.   {
    39.     travelUntilHit,
    40.     travelUntilRange,
    41.     travelUntilEvent,
    42.   }
    43.   public enum TypeEvent
    44.   {
    45.     buttonPress,
    46.     time
    47.   }
    48.   public enum RicochetType
    49.   {
    50.     goUntilTime,
    51.     goUntilNumHits,
    52.     goUntilRange
    53.   }
    54.  
    55.   public int id;
    56.   public atkType attackType;
    57.   public AuraType auraType;
    58.   public dmgType damageType;
    59.   public int dmgAmount;
    60.   public int abilityLevel;
    61.   public int healAmount;
    62.   public int abilityXP = 0;
    63.   public bool overTime;
    64.   public float duration;
    65.   public float increment;
    66.   public int percentChanceDOT;
    67.   //melee information
    68.   public float abilityWidth;
    69.   public float abilityHeight;
    70.   //ranged information
    71.   public float abilityInitialSpeed;
    72.   public float abilityAcceleration;
    73.   public float abilityMaxSpeed;
    74.   public float maxRange;
    75.   public int projectileLimit;
    76.   public GameObject attackSprite;
    77.   public trajectoryType travelUntil;
    78.   public TypeEvent typeEvent;
    79.   public bool ricochet;
    80.   public RicochetType ricochetType;
    81.   public float projectileTimeLimit;
    82.   public int projectileHitLimit;
    83.   //aura information
    84.   public float radius;
    85.   public AuraDetails auraDetails;
    86.   public float atkCooldown;
    87.   public bool onCooldown;
    88.   public Animation atkAnimation;
    89.   public AudioClip atkSound;
    90.  
    91.   public AbilityData ShallowCopy()
    92.   {
    93.     return (AbilityData)this.MemberwiseClone();
    94.   }
    95. }
     
  11. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    So I got it working with your suggestion. The issue I'm running into now is that the variables I set in the inspector on the pickup item are reset everytime I run the game
     
  12. tango209

    tango209

    Joined:
    Feb 23, 2011
    Posts:
    379
    Take a look at the answer here.
     
  13. lo-94

    lo-94

    Joined:
    Nov 1, 2013
    Posts:
    282
    I ended up figuring it out. Basically it was working, but it was resetting every time I would start the game. Inserting

    Code (csharp):
    1.  
    2. if(GUI.changed){
    3.             EditorUtility.SetDirty ((pickupObject)target);
    4.         }
    5.  
    seemed to fix it. I was unaware of this function. Now I just have to ensure that this works for multiple pickups