Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 craigiedon · Oct 15, 2015 at 01:11 AM · serializationtilemapcustom editor

Efficiently serializing large collision grid

I am currently making a Tile-Map class in Unity with a custom editor. This TileMap currently only contains a 2-D grid, with each tile being either collidable or non-collidable. At the moment, my TileMap class looks something like:

 public class TileMap : MonoBehaviour {
     public int cols = 100;
     public int rows = 100;
     public bool[] collisionGrid;
 }

The collisionGrid variable is a flattened 2D array of size cols * rows, and represents each grid space on the 2D grid. If collisionGrid[r * cols + c] = true, then that grid space is impassable.

My TileEditor script is a class that extends Editor. It gets the mouse position and, if the mouse is clicked, sets the corresponding tile to true.

 void OnSceneGUI(){
     //Get Mouse position and appropriate tile index
     if(e.type == EventType.MouseDown || e.type == EventType.MouseDrag){
         tMap.collisionGrid[tileIndex] = true;
     }
     EditorUtility.SetDirty(tMap);
 }

My problem is that, while this does what it is supposed to do, the editor slows to almost a halt. Clicking and dragging to add new collidable positions is next to impossible, and even attempting to pan the camera has noticeable delay.

There are several things I have tried already to resolve this issue:

  1. Changing the dimensions from 100 x 100 to, say, 20 x 20, then everything works smoothly. However, I specifically want to make larger tile maps, And I feel like 100 x 100 is hardly a demanding size to work with.

  2. Removing the "EditorUtility.SetDirty(tMap)". However, If I do this, Unity will not persist my collisionGrid properties between sessions. I need it to persist.

  3. Moving the "EditorUtility.SetDirty(tmap)" inside of the "if" condition. This resolves the problem of regular Unity functionality (like panning and zooming) being sluggish, but doesn't resolve the core problem, that editing the grid of collision values is so slow as to be unusable.

So my question is, what am I doing wrong? How can I edit a moderately sized grid in real-time and have it persist? Is it a case of calling EditorUtility.SetDirty() sometimes, but not every frame? Or something smarter than that?

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

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by esg-tim · Oct 15, 2015 at 04:41 PM

You have a few avenues to explore:

  • You could try targeting the SerializedProperty of the collision by using

     // when setting
    
     var tileProperty = serializedObject.FindProperty("collisionGrid").GetArrayElementAtIndex(tileIndex);
     tileProperty.boolValue = true;
     
     // to apply
    
     serializedObject.ApplyModifiedProperties();
    
    

    I'm not sure, but this may be faster, and only copy the changed properties of the object.

  • You could add a cached version of the array that the editor changes when working, and then try to make it call "SetDirty" only after the user has been idle for more than 3 (or whatever) seconds.

    You can ensure the cached field exists only in the editor using #if UNITY_EDITOR preprocessor blocks. You can make the TileMap choose to draw from the cached field first before the actual values when in the editor.

    Setting a timer in the Editor could be accomplished in a few ways. A simple way would be to add a listener to EditorApplication.update that looks for when Editor.timeSinceStartup - idleStartTime > 3.0d, then copies the cache and calls EditorUtility.SetDirty(targetObject) if it needs to. Update idleStartTime to EditorApplication.timeSinceStartup every time the mouse is down.

Comment
Add comment · Show 2 · 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 craigiedon · Oct 15, 2015 at 04:57 PM 0
Share

@esg-tim with regards to the second option, this would indeed take some of the burden off of the amount of serializations done. However, would this guarantee that the object is serialized when needed.

As an example, when unity is closed, or the user clicks "play" to run their game, any properties that have not been serialized are reset. So if my SetDirty interval was say, 5 seconds, and 2 seconds after editing, the user clicked "Play", wouldn't they lose the changes they had just made? Ideally, I think I need some way to say "If I am in a situation where I am about to throw away unsaved changes, serialize any changes".

Alternatively i could just make the interval so small as to guarantee the user cant get from the tile map editor to the play button in that amount of time, but at that point, the "SetDirty"s will be so frequent that the problem is back to square one!

avatar image esg-tim craigiedon · Oct 15, 2015 at 06:36 PM 0
Share

You might be able to detect when to serialize on the Tile$$anonymous$$ap by implementing the ISerializationCallbackReceiver, which would call OnBeforeSerialize every time the object needed to be serialized. In this method you could copy the cache into the actual object data. In fact, maybe you wouldn't need the timer at all if you went this route?

avatar image
0

Answer by Bunny83 · Oct 15, 2015 at 03:19 AM

Well, when calling SetDirty you mark your array as "dirty" so it will be reserialized to the assetfile where its parent class is actually contained. 100 x 00 are actually 10000 bool values (or 10 kB).

Of course you should only call SetDirty when you actually changed something. So put the call inside that if statement.

Additionally you should implement some kind of enable / diable for your editor. Otherwise it will always execute the check while you have your object selected.

Comment
Add comment · Show 2 · 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 craigiedon · Oct 15, 2015 at 09:20 AM 0
Share

@Bunny83 The two things you have suggested (putting the "SetDirty" inside of the click/drag condition, and allowing the editor to be enabled disabled) solve one part of the problem: Namely that the editor would no longer stutter and slow when panning and zoo$$anonymous$$g etc.

However, it still doesn't really solve the core of the problem. If I move the SetDirty inside the conditional, then this will not prevent the editor from stuttering when I attempt to paint on various collision blocks by clicking and dragging.

I think what I really need is to know some way of having the Unity Editor re-serialize the large grid of values only when the data is required to be persisted rather than re serializing every single time a field in the grid is altered.

avatar image craigiedon · Oct 15, 2015 at 09:25 AM 0
Share

@Bunny83 I have now updated the question to take account of your suggestion

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How to save sprite color change on custom inspector ? 0 Answers

"Unbroken Reference" problem when using a custom Editor to Save/Load a ScriptableObject Asset 0 Answers

Variable modified with custom editor not saved when enter play mode, even with serialized attributes. 0 Answers

How to insert an element of specific type to a list as serializedProperty? 1 Answer

Finding property with serializedObject on script with a generic 0 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