Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Izze · Dec 01, 2014 at 11:12 PM · databasescriptableobjectrpgcustom-editoreditor-classes

Making an RPG Maker VX esque database using ScriptableObject, with custom editor

Hello!

I've been prototyping an RPG in RPG Maker VX Ace for a few months, but I feel I need a more versatile engine, so I'm trying my hand at learning Unity. I was looking into ways to create a database containing stuff (characters, jobs, items etc) akin to the database in RMVX. Someone told me to try using ScriptableObject and then write a custom editor for it. My Database class looks like this:

 [System.Serializable]
 public class Database : ScriptableObject {
     public List<Character> characters;
     public List<Job> jobs;
     public List<Skill> skills;
 }

Character class looks like this, and the other database items look similar:

 [System.Serializable]
 public class Character {
     public string name = "Character";
     public int experience = 0;
     public Job job;
 }

My first question is: can I even have a reference to a Job object inside a Character object? What I want is basically to reference a Job stored in the list of jobs in the database. If this doesn't work, is using an ID, or maybe even just the index in the list, the best option?

My next question is about going about creating a custom editor and property drawers for my different database items. This is my custom database editor:

 [CanEditMultipleObjects]
 [CustomEditor(typeof(Database))]
 public class DatabaseEditor : Editor {
 
     public override void OnInspectorGUI() {
         serializedObject.Update();
         DrawGroup("characters");
         DrawGroup("jobs");
         DrawGroup("skills");
         serializedObject.ApplyModifiedProperties();
     }

     // Draw the full list of items of a category in the database
     private void DrawGroup(string groupName) {
         SerializedProperty list = serializedObject.FindProperty(groupName);
         EditorGUILayout.PropertyField(list);
 
         if (list.isExpanded) {
             // Draw array size field
             EditorGUILayout.PropertyField(list.FindPropertyRelative("Array.size"));
 
             EditorGUI.indentLevel++;
 
             // Draw all the list elements
             for (int i = 0; i < list.arraySize; i++) {
                 SerializedProperty element = list.GetArrayElementAtIndex(i);
                 EditorGUILayout.PropertyField(element);
             }
 
             EditorGUI.indentLevel--;
         }
     }
 }

I have also written a quick property drawer for Character objects:

 [CustomPropertyDrawer(typeof(Character))]
 public class CharacterDrawer : PropertyDrawer {
     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
         property.isExpanded = EditorGUILayout.Foldout(property.isExpanded, label);
 
         if (property.isExpanded) {
             EditorGUILayout.PropertyField(property.FindPropertyRelative("name"));
             EditorGUILayout.PropertyField(property.FindPropertyRelative("experience"));
 
             // Some way to reference a Job object in the database?
         }
     }
 }
 

OK, so first off, how do I reference a Job object? The Job objects are stored in the jobs field in the Database. Is there any way a Character object can get a straight reference to a Job object? What type of EditorGUI field do I use for that? I'm also getting line-high gaps in between every element in the list, why is that? Picture:

alt text

Thanks in advance for any help!

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dorpeleg · Dec 02, 2014 at 12:12 PM 0
Share

In your custom inspector code, use EditorGUI.Popup to have a drop down menu for choosing a job out of the jobs list in the data base.

Then, try to just reference that in your Character class.

If that doesn't work, I don't think there is a way to do that.

But, you might be able to do some workaround at game runtime.

Something like: In the database you save a string of job name. Then, at runtime, you look for the correct job instance in the data base an assign it.

Again, not sure if any of this will work, those are just ideas.

avatar image Mmmpies · Dec 02, 2014 at 08:47 PM 0
Share

Best I can do is point you in this direction:

link text

This has an attachment Unity package with a spell list that reference the components of each spell. Look in some of the scripts like CastSpell.cs It's a pretty good example and well commented throughout but it's not $$anonymous$$e, it should give you the idea of how to get what you're after.

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Izze · Dec 04, 2014 at 01:28 PM

@Mmmpies Thanks a bunch for the link! I ended up doing it like they did, having a separate ScriptableObject asset for each item in the database. It's a bit messier, but it's way easier to reference other database items from one item. Cheers!

Edit: I also managed to make proper custom property drawers, so now everything looks nice and clean in the inspector.

For future reference, if anyone stumbles across this having the same problems as I did, here are a few of my classes:

 [System.Serializable]
 public class Job : ScriptableObject {
     public new string name = "Job";
     public Sprite icon = null;
     public List<SkillIntPair> learnableSkills = new List<SkillIntPair>();
     public List<WeaponTypeIntPair> weaponMastery = new List<WeaponTypeIntPair>();
     public List<EquipmentTypeIntPair> equipmentMastery = new List<EquipmentTypeIntPair>();
     public Range strGrowth = new Range();
     public Range vitGrowth = new Range();
     public Range intGrowth = new Range();
     public Range wisGrowth = new Range();
     public Range dexGrowth = new Range();
     public Range agiGrowth = new Range();
     public List<Attribute> attributes = new List<Attribute>();
 }

You need to make Lists of custom pair classes, because Unity doesn't serialize generic types (e.g. KeyValuePair doesn't work). Here is my SkillIntPair class and its custom property drawer:

 [System.Serializable]
 public class SkillIntPair {
     public Skill skill = null;
     public int level = 0;
 }
 
 [CustomPropertyDrawer(typeof(SkillIntPair))]
 public class SkillIntPairPropertyDrawer : PropertyDrawer {
     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
         EditorGUI.BeginProperty(position, label, property);
         SerializedProperty key = property.FindPropertyRelative("skill");
         SerializedProperty value = property.FindPropertyRelative("level");
 
         // Get the name of the skill, and use that as the label for the property
         // (otherwise the label is simply "Element n" when stored in lists)
         Skill skillObject = (Skill)key.objectReferenceValue;
         string header = label.text;
 
         if (skillObject != null)
             header = skillObject.name;
 
         // Disable indention for this property
         position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(header));
         int indent = EditorGUI.indentLevel;
         EditorGUI.indentLevel = 0;
 
         // Decide where the property fields are to be drawn
         Rect keyRect = new Rect(position.x, position.y, position.width / 2, position.height);
         Rect valueRect = new Rect(position.x + position.width / 2, position.y, position.width / 2, position.height);
 
         // GUIContent.none removes the separate label from the field
         // If you want a label you have to use custom EditorGUI.LabelField I think,
         // because the inherent labels of these PropertyFields are buggy for some reason
         EditorGUI.PropertyField(keyRect, key, GUIContent.none);
         EditorGUI.PropertyField(valueRect, value, GUIContent.none);
 
         EditorGUI.indentLevel = indent;
 
         EditorGUI.EndProperty();
     }
     
     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
     {
         return 18;
     }
 }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Can’t serialize custom class variable in ScriptableObject.Or add instance of a class to a list with overridden method in custom editor. 1 Answer

Database-like arrays 1 Answer

RPG Quest structure in MySQL 0 Answers

Weapon Database wtih scriptable objects 1 Answer

How to persist design-time data (excluded from the final game)? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges