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 Tryz · Jun 23, 2014 at 01:05 PM · databaseinheritancedata

How do you store non-GameObject data?

There's data I want to store outside of any GameObject. For example, I'd like to store inheritable data for character races in a database style structure.

In this way, I can say:

  • All character races have a 'Strength' attribute

  • Goblins have a range of strength attribute values (they can override)

  • Goblin warriors have a specific range of strength values (they can override)

  • Joe the Goblin Warrior has an even more specific value (he can override)

I really don't want to create empty prefabs for generic character template data. It feels clumsy for searching and updating. I also don't believe prefabs support nested data the way I'm thinking about it.

So, I have all of this working using my own game-save/storage system. However I now have 2 different 'save' buttons in the editor:

  1. Unity's normal 'save' to save the scene

  2. My 'save' to save data external to the scene (i.e. inheritable attributes)

This feels cumbersome.

So, how do you store data that isn't part of a GameObject?

Is there a way to trigger my data save when the developer (me) saves the scene?

Comment
Add comment
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

3 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by PAEvenson · Jun 23, 2014 at 01:07 PM

Sounds like you want ScriptableObject!

http://docs.unity3d.com/ScriptReference/ScriptableObject.html

Comment
Add comment · Show 6 · 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
avatar image Tryz · Jun 23, 2014 at 01:35 PM 0
Share

Thanks PA. I did do some research and testing on the ScriptableObject, but that seemed to fall short (or maybe I missed something).

The ScriptableObjects seemed to be part of the scene data. So I couldn't create a prefab or share the data across multiple scenes.

In my example above, I wanted the goblin attribute data to be accessible no matter what scene was loaded. The alternative was to save the data once for each scene, but the DBA in me cringed. :)

avatar image PAEvenson · Jun 23, 2014 at 02:01 PM 0
Share

ScriptableObjects do work across multiple scenes. They look just like any other asset inside the Project View. They are not scene specific. For example:

 public class GoblinBadGuy: $$anonymous$$onoBehavior
 {
      public BudGuyStats GoblinStats;
 }
 
 //In different file
 public class BudGuyStats : ScriptableObject
 {
      public int health = 100;
      public int power = 100;
      public int toughness = 100;
 }

Inside of the Project View you would create a new BadGuyStats. I would then rename it to something like GoblinStats. This is now a file sitting inside the project, which you can change the stats inside the inspector. You could then create new files for each of your different types(storing differnt values ie "PowerfulGoblin") but all are of the same class.

When I use ScriptableObjects I like to create editor scripts that allow me to create them easily:

 using UnityEngine;
 using UnityEditor;
 using System;
 public class BadGuy$$anonymous$$enuItems
 {
 
 [$$anonymous$$enuItem("Assets/BadGuys/BasicBadGuy")]
     public static void CreateBadGuyStats()
     { 
         CustomScriptableObjectUtility.CreateAsset<BadGuyStats>("NewBadGuyStats");
     }
 }


Here is the UtilityFile(Im sure i found this somewhere in the Unity community) it super useful.

 using System;
 using UnityEngine;
 using UnityEditor;
 using System.IO;
 
 public class CustomScriptableObjectUtility
 {
     public static void CreateAsset<T> () where T : ScriptableObject
     {
         CreateAsset<T>("New " + typeof(T).Name.ToString());
     }
 
     public static void CreateAsset<T>(string name) where T : ScriptableObject
     {
         T asset = ScriptableObject.CreateInstance<T>();
 
         string path = AssetDatabase.GetAssetPath(Selection.activeObject);
         if (path == "")
         {
             path = "Assets";
         }
         else if (Path.GetExtension(path) != "")
         {
             path = path.Replace(Path.GetFileName(AssetDatabase.GetAssetPath(Selection.activeObject)), "");
         }
 
         string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/" + name + ".asset");
 
         AssetDatabase.CreateAsset(asset, assetPathAndName);
 
         AssetDatabase.SaveAssets();
         UnityEditor.EditorUtility.FocusProjectWindow();
         Selection.activeObject = asset;
     }
 }
 

 
avatar image Tryz · Jun 23, 2014 at 02:50 PM 0
Share

Thanks PA for all the details!

So that means I'd need a separate class/file for each instance:

  • BadGuyStats

  • BadGuyGoblinStats

  • BadGuyGoblinWarriorStats

  • BadGuyGoblinWarriorArcherStats

Joe the Goblin Warrior Archer would have an instance of GoblinWarriorArcherStats.

The difference being only value changes. They all have 'Health' just a different value.

So far, so good. Potentially lots of files, but I can inherit the classes and only override the property values I need to.

However, if in mid-game, all Goblin Warrior Archerers power should increase by 10, I'd have to find all the instances and update them individually...

I wouldn't be able to update the GoblinWarriorArcherStats once and have it flow because that data lives as a resource and I can't save it at run-time.

Hopefully this makes sense.

Note: my initial reaction to creating all the classes is that since it's just values that are changing, it makes more sense to store them in a database vs. separate classes. But, maybe I'm stuck in my way of doing things.

Sorry for dragging this out...I'm really trying to make sure I (and maybe others) understand.

avatar image PAEvenson · Jun 23, 2014 at 04:09 PM 0
Share

You can certainly write an editor script that finds all of the objects of a specific type and adjust a value in them if you were to go the ScriptableObject route. You could also write another editor script to view all of the creatures in the project and display them in an editor window, and change stats right then and there.

As for the changing at runtime, I would personally add a modifier property. Something like this:

 public int BaseHealth 
 {
      get { return stats.Health}
 }
 
 public int $$anonymous$$odifiedHealth
 {
      get { return stats.Health + this.Health$$anonymous$$ods;}
 }
 
 public int Health$$anonymous$$ods
 {
      get
      {
           return 0;//Adds all the Health $$anonymous$$ods together here
      }
 }

It all depends how comfortable you feel with the technologies. If you are familiar with databases or want to learn more about them, then I would go the database route. If you want to learn more about ScriptableObjects and the Unity Editor, go that route. You could probably combine the database and UnityEditor, allow you to change stats inside of Unity rather than an outside application.

-Paul

avatar image PAEvenson · Jun 23, 2014 at 04:24 PM 0
Share

Actually, if you have more than 30 or so different variations, I would probably use a database. Things could start getting a little out of hand if you have 30+ different scriptableObjects sitting in your project. :P

Show more comments
avatar image
2

Answer by AyAMrau · Jun 23, 2014 at 01:17 PM

Have you considered using Scriptable Objects with a script like the one here. This will let you store data in objects that are saved in the Project. You can edit them just like prefabs and everything is saved automatically. You can also give them custom inspector if you need something fancy to happen.

Comment
Add comment · Show 5 · 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
avatar image Tryz · Jun 23, 2014 at 01:50 PM 0
Share

Thanks AyA$$anonymous$$rau, I haven't seen this and will have to try it. If it does let me reuse the data across all scenes, that may work.

I have X$$anonymous$$L serialization working, but if this is the 'right' way to use data I'd rather work with Unity than against it.

avatar image AyAMrau · Jun 23, 2014 at 02:10 PM 0
Share

Yes, this is saved in the Project (same as prefabs, scripts etc), therefore it's available in all scenes. You can either add references directly to game objects or you can place the scriptable object files in the Resources folder and use Resources.Load.

If you have quite a lot of scriptable objects that need loading, then you can also make an object that just stores a list of them, where it makes sense. For example one that stores all the enemies. Then you only need to load one thing and access the list as normal in code.

avatar image Tryz · Jun 23, 2014 at 02:29 PM 0
Share

Thanks.

I just did some digging and testing. Everything looked good until I realized you can't save the data back into the resource at runtime.

Not saving parent data at runtime might be ok, but not being able to update inherited instances is an issue.

avatar image AyAMrau · Jun 23, 2014 at 03:17 PM 0
Share

Quickly about your comment to the previous answer. If all your goblins have the same properties (i.e. health, strength), then you don't need a Scriptable Object derived class for every single one. You only need a separate copy of the actual Scriptable Object in your project, name them differently and set all the values to be what you want. You will probably have a hierarchy for your game objects when creating characters in game, but they can all refer to one type of Scriptable Object.

You shouldn't be modifying the scriptable object instances at runtime, because this is permanent (and shared for all in game characters). The way to do this, is to make a field on the game object to store the Scriptable Object with the data and then duplicate any fields that you will be modifying (like health). Treating the Scriptable Object as source of base values.

If the base values need to change during the game I can see two ways to do this.

  • If the new value is also a preset data: Store it in the Scriptable Object as a new field and then in the game object have some logic that let's the character know which value to use.

  • If the value is dynamic and decided at runtime: Have a stat modifier variable on the game object that will be applied after reading from the data object.

If the change is specific to one character then you will need to access it. But if you need all the enemies of given type to make change you can probably get away with using a static.

avatar image Tryz · Jun 24, 2014 at 02:22 PM 0
Share

Thanks AyA$$anonymous$$rau.

Part of what I was trying to figure out was if there was a pre-built solution in Unity that I just didn't know about. Given the responses, I think the answer is 'no' and going with my database style approach is probably the best answer for me.

Thanks again for helping me beat through this! :)

avatar image
0

Answer by Gizmoi · Jun 23, 2014 at 01:41 PM

I would suggest saving your data out to text and reading it in at run-time.

JSON is currently my format of choice.

SimpleJSON can be used with Unity.

Comment
Add comment · Show 1 · 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
avatar image Tryz · Jun 23, 2014 at 02:00 PM 0
Share

Thanks Gizmoi. I'm using a compact version of X$$anonymous$$L now and my run-time save/load game is working great.

However, when in the editor I have to remember to save data changes in addition to saving the scene. That feels error prone and a bit weird to me and why I'm thinking I should have serialized it a different way...maybe with ScritableObjects ins$$anonymous$$d of JSON or X$$anonymous$$L.

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

24 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Database-like arrays 1 Answer

How to upgrade from free to paid version and maintain established player prefrence data? 0 Answers

An OS design issue: File types associated with their appropriate programs 1 Answer

How to import data into Microsoft Excel? 1 Answer

Use a simple Database... 2 Answers


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