Search Unity

Tidy Tile Mapper: Paint tile-maps from the Editor [Released]

Discussion in 'Assets and Asset Store' started by JFFM, Jan 21, 2012.

  1. Scott Southworth

    Scott Southworth

    Joined:
    Feb 29, 2012
    Posts:
    1
    Hi JFFM! I'm relatively new to Unity (so please excuse questions this might show my ignorance) -- and I bought the Tile Mapper and have mostly figured out the painting portion. I'm planning to use it for an old-skool Dungeon Crawl, e.g. Bard's Tale. While it looks like it will work nicely to lay things out, my interface will be moving via code through the scene one step at a time -- and I'll need a way (at the least) to interrogate the map (square occupied, etc.) I could raycast, but I was hoping for an API to pull info (block at coords 1,2 or such). Also, a nice way to attach metadata (there's this monster hidden at tile 5,6) without requiring/breaking prefabs would rock. Any suggestions (or upcoming features) would be great to hear about.

    Thanks,
    Scott S
     
  2. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Jrricky,

    I certainly did miss that post. Could you clarify what you mean by Edge Barriers?

    Do you mean generation of colliders between a set of points? I could do that.

    -JFFM
     
  3. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Jrricky,

    Oh that's a big question. Give me a little, I'll put something together - a set of pictures or such.

    -JFFM
     
  4. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Scott,

    You should send me an email! (at the support email address in the readme.txt of Tidy TileMapper) - I'd love to pick your brain about your requirements and tool desires and such - this is exactly the use-case I was envisioning when I developed TTM.

    Coincidentally, I'm just putting the finishing touches on what has been dubbed "The Runtime API" - which will allow you to add,remove,and query your maps at runtime - so that should tick one of your boxes.

    Your metadata requirement is also a good one, I've been working on this slowly, as a fun thing for myself, but I'll put it at the front of the queue as an upcoming addon now that I know there's a good demand for it.

    Expect the runtime API in the next few days (maybe even tomorrow, if I can clear my list) - and send me an email, we'll talk about your metadata and tagging requirements.

    Exciting!

    -JFFM
     
  5. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    YES! YES! I want to create invisible barriers (just like creating a rectangular primitive with a collider then turn of the mesh renderer) so player cannot walk pass that certain spot. And I would like an intuitive way, like using a waypoint system that creates this barrier along the waypoint lines.

    Also, I emailed you about some other glitch I found in my preview problem.
     
  6. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    So publishing a map doesn't work at all. It's like it created a prefab of the map I was creating and didn't strip a single thing, chunks are still there :-/ Plus, I get some whacky glitch where the tiles are not looking right. Is there a reason if I deactivate the Map I am creating the blocks go glitchy/whacky and console throws an error?

    EDIT: I actually see what happens when I deactivate the Map game object. When I reactivate it, all the variants show up in one place looking weird.

    Console throws this error:

    Also here is before after pic:
    http://dl.dropbox.com/u/4585058/CM%20Capture%2010.png
    http://dl.dropbox.com/u/4585058/CM%20Capture%2011.png
     
    Last edited: Mar 15, 2012
  7. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Jrricky,

    Yes, this is related to how Unity enabled/disables hierarchies of objects. If you disable and then re-enabled a map, it doesn't preserve the working series of activations (so you lose your orientations).

    -JFFM
     
  8. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    I don't know what to do for the map not publishing correctly. It's still has the chunks plus the visual glitch comes up when I drag the published map into the scene.
     
  9. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Jrricky,

    Oh sorry I misunderstood - I read the enable/disable and publishing issue as the same issue in your sentence.

    Give me a little, I'll recreate the issue and release an update later today.

    -JFFM
     
  10. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hello Everybody,

    Before I finish up for the evening, I thought I'd put together a little video for you to give you a demonstration of the "Runtime API" for Tidy TileMapper (releasing tomorrow).



    I thought that... before I went ahead and published the release, I should make a demo to put the API through its paces - so I made this Deer Digging Demo (alliteration!)

    This was originally a mobile video - as this demo is built out to the Android and runs just beautifully... but it's so so hard to film a phone and have it look nice.

    Enjoy!

    -JFFM
     
  11. Lars-Steenhoff

    Lars-Steenhoff

    Joined:
    Aug 7, 2007
    Posts:
    3,526
    Cool!! you can release the runtime api demo for a few dollars as an add-on in the app store and everyone is happy
     
  12. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Everybody!

    I've just submitted an update to TTM to the Asset Store - including the new BlockUtilities class which contains all of the Runtime functions, and a demo scene that shows the basics of how it works.

    I'll be putting an API page up on our website once I can figure out how to export documentation from MonoDevelop).

    I've got a few other smaller things to look at (@Jrricky's Publish bug and some small things to do with level stripping) and then:

    I'll be releasing the long-overdue "Tidy [Something]" addon: Containing the demo you saw in the video a few posts ago (Character controller, advanced runtime use), as well as some character controllers for both player and AI characters (using pathfinding and map query). [You'll note I blatantly stole @Lars Steenhoff's idea here and made it my own. Thanks Lars!]

    All of these scripts will be open so that you can modify them, learn from them and extend them to reach the pinnacles of development ecstasy.

    That's all from my side of the screen! It's been a surprisingly complex task, putting together the Runtime API. As with everything else, I'll expand and improve on this API as I get your feedback, and hopefully soon we'll have a beautiful and robust library.

    -JFFM
     
  13. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    Great stuff - I love how frequent the updates are :)
    (Wish I could consistently manage that!)

    Programming: Making the easy things hard and the impossible possible.
     
  14. AlexEvangelou

    AlexEvangelou

    Joined:
    Sep 15, 2011
    Posts:
    11
    So I'm still having problems with the "Act Empty" blocks. They aren't seeming to register as empty to other "Act Empty" blocks, including ones of the same type.





    In the first image my mouse was hovering over the block with the red dot. It's an act empty block, the same block type as the block with the blue dot. It should be coming up as having an empty block to its left, an "act empty" block below and to its right, and a solid block above it. This should register as bottom_alone but instead it's registering as left_surrounded because the only block it is counting as being empty is the empty block. The block with the blue dot is being counted as solid.

    You can see in the second Image that the block marked with the green dot, which is a solid block, is correctly registering as Centre_Horizontal_Surrounded. The two blocks to it's sides are solid, the block above it is empty and the block below it is "act empty". The same block as in image 1 with the blue dot is now registering as empty.

    Let me know if I'm assuming something works differently than how it does but I think the blue dotted block registering as empty/solid under different conditions is a bug.

    I can't wait to get this fixed because as soon as I do I'm going to dive into the runtime API. I looked at the demo and it looks great.
     
  15. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Alex,

    Oh man I'm sorry, I got distracted and completely forgot about the "Act Empty" tiling issue. I'll take a look at it post-haste.

    -JFFM
     
  16. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Everybody,

    Just a note to say that I've updated the tool description at the head of this thread, and I'll replicate right here:

    I've started some rudimentary API documentation on the blog: Runtime API

    As time goes by, I'll update and add examples and such.

    Enjoy!

    -JFFM
     
  17. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hello Everybody,

    While putting together the next release of Tidy TileMapper, I made this video, demonstrating some map-streaming capability for the creation of enormous maps. I thought you might find it entertaining:



    The thing I love about the Unity forums is that is contains that beautiful mix of... game design/programmer/artist. I swear I'd be hard pressed to find anybody else who cared about this sort of functionality :D

    I'm not sure what I intend to do with the function, but I thought it might get everybody's juices flowing on the procedural-generation front.

    -JFFM
     
  18. wesllg

    wesllg

    Joined:
    Jan 8, 2011
    Posts:
    18
    Quick question: Does TTM batch its tile layers into single GameObjects with a single mesh per layer? This would be important for memory consumption on mobile devices. i.e you don't want a single gameobject per tile.

    Thanks.
     
  19. AlexEvangelou

    AlexEvangelou

    Joined:
    Sep 15, 2011
    Posts:
    11
    You keep making things just before I go to make them myself and that's excellent. This is exactly what I was talking about by a pooling system (I did notice the comment about that functionality in the example). This type of system is necessary for a mobile game with a big dynamic map. Any chance you'll put this in as example code? I'm a big fan of not reinventing the wheel.

    PS. It's 11:56AM on Wed here, so this video is from the future!

    I don't believe it does, there is the clean map function but I'm under the understanding that it removes all the extra unused orientations from blocks, but each block is still it's own game object, I haven't tried it yet myself. If you're just using TTM for level creation you could do what you said baking the level into a single mesh. However if you want to keep your blocks editable via the runtime API and deploy on a mobile device then the video JFFM just posted is what you want. Just picture the screen being in the center of the radius of blocks drawn. This lets you pool and reuse game objects, so the number of game objects you use is determined by how many fit on screen, not how many are in the level.
     
  20. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I and others would like meshes to be combined in some cases. Perhaps there could be a new option for publish "Strip All + Combine Meshes".

    Here is an editor tool that I have created for my project that must be use on an instance of the prefab generated by "Strip All". I release the code with a disclaimer which allows Joshua to include parts or all of the code within his product should he wish.

    Perhaps this will be of help to people...

    Here is what the tool does:
    • Combines all block meshes into a single mesh and adds a mesh filter and renderer to root map object
    • Removes redundant blocks from map (blocks with only a transform and no children)
    • Removes empty chunks from map
    • Removes trigger colliders from blocks (those that are not stripped despite having retaincollider set to off) Should not effect any triggers that are contained within blocks and will not remove solid colliders from blocks.
    • Replaces prefab with updated version

    How to use:
    • Publish map using "Strip All" setting (important)
    • Drag generated prefab into a scene and select any object within its hierarchy
    • Use my tool menu: Tools > Map> Cleanup and Merge Prefab

    Warning, this code has not been fully tested so please use with caution.

    Disclaimer:
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    Place in YourProject/Assets/Editor/CleanupTTM.cs
    Code (csharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. namespace CustomStuff.Editor {
    7.  
    8.     public static class CleanupTTM {
    9.    
    10.         private static void CleanupMergePrefab_Single(Transform parent, Object prefab) {
    11.             string filePath = EditorUtility.SaveFilePanelInProject("Save Mesh in Assets", parent.name + "_mesh.asset", "asset", "Please select destination file name");
    12.             if (filePath == "")
    13.                 return;
    14.            
    15.             MergeMeshContext context = new MergeMeshContext(parent.gameObject, filePath);
    16.            
    17.             for (int i = 0; i < parent.childCount; ++i) {
    18.                 Transform chunk = parent.GetChild(i);
    19.                
    20.                 for (int j = 0; j < chunk.childCount; ++j) {
    21.                     Transform block = chunk.GetChild(j);
    22.                    
    23.                     // Remove redundant collider from child?
    24.                     if (block.collider != null  block.collider.isTrigger)
    25.                         GameObject.DestroyImmediate(block.collider);
    26.                    
    27.                     // Add sub meshes to combiner
    28.                     // Note: Only do this to static blocks!
    29.                     if (block.gameObject.isStatic)
    30.                         context.AddChildrenToCombiner(block);
    31.                    
    32.                     // Remove empty block
    33.                     if (block.childCount == 0  block.GetComponents<Component>().Length == 1) {
    34.                         GameObject.DestroyImmediate(block.gameObject);
    35.                         --j;
    36.                     }
    37.                 }
    38.                
    39.                 // Remove empty chunk
    40.                 if (chunk.childCount == 0) {
    41.                     GameObject.DestroyImmediate(chunk.gameObject);
    42.                     --i;
    43.                 }
    44.             }
    45.                
    46.             // Add mesh filter and renderer to object
    47.             context.Combine();
    48.            
    49.             // Apply changes to prefab
    50.             PrefabUtility.ReplacePrefab(parent.gameObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
    51.         }
    52.        
    53.         [MenuItem("Tools/Map/Cleanup and Merge Prefab")]
    54.         public static void CleanupAndMergeMapPrefab() {
    55.             // Process each object in selection
    56.             foreach (GameObject go in Selection.gameObjects) {
    57.                 Object prefab = PrefabUtility.GetPrefabParent(go);
    58.                 if (prefab == null)
    59.                     continue;
    60.                
    61.                 GameObject rootGameObject = PrefabUtility.FindRootGameObjectWithSameParentPrefab(go);
    62.                 CleanupMergePrefab_Single(rootGameObject.transform, prefab);
    63.             }
    64.         }
    65.        
    66.     }
    67.    
    68. }
    Place in YourProject/Assets/Editor/MergeMeshContext.cs
    Code (csharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using System.Collections.Generic;
    4.  
    5. namespace CustomStuff.Editor {
    6.  
    7.     public class MergeMeshContext {
    8.        
    9.         public List< List<CombineInstance> > combiners;
    10.         public List<Material> materials;
    11.        
    12.         private GameObject gameObject;
    13.         private string filePath;
    14.         private Matrix4x4 correctionMatrix;
    15.        
    16.         public MergeMeshContext(GameObject parent, string targetFilePath) {
    17.             gameObject = parent;
    18.             filePath = targetFilePath;
    19.             correctionMatrix = parent.transform.localToWorldMatrix.inverse;
    20.            
    21.             combiners = new List< List<CombineInstance> >();
    22.             materials = new List<Material>();
    23.         }
    24.        
    25.         public List<CombineInstance> FindCombiner(MeshFilter filter, MeshRenderer renderer) {
    26.             int materialIndex = materials.IndexOf(renderer.sharedMaterials[0]);
    27.             if (materialIndex == -1) {
    28.                 List<CombineInstance> combiner = new List<CombineInstance>();
    29.                 combiners.Add(combiner);
    30.                 materials.Add(renderer.sharedMaterials[0]);
    31.                 return combiner;
    32.             }
    33.            
    34.             return combiners[materialIndex];
    35.         }
    36.        
    37.         public void AddToCombiner(Transform obj) {
    38.             MeshFilter filter = obj.GetComponent<MeshFilter>();
    39.             MeshRenderer renderer = obj.GetComponent<MeshRenderer>();
    40.            
    41.             if (filter == null || renderer == null)
    42.                 return;
    43.            
    44.             if (renderer.sharedMaterials.Length == 0) {
    45.                 Debug.LogWarning("No material assigned to '" + obj.name + "'");
    46.                 return;
    47.             }
    48.            
    49.             List<CombineInstance> combiner = FindCombiner(filter, renderer);
    50.            
    51.             // Create new combine instance
    52.             CombineInstance combine = new CombineInstance();
    53.             combine.mesh = filter.sharedMesh;
    54.             combine.transform = correctionMatrix * filter.transform.localToWorldMatrix;
    55.             combine.subMeshIndex = combiners.IndexOf(combiner);
    56.             combiner.Add(combine);
    57.            
    58.             // Remove filter and renderer from object
    59.             GameObject.DestroyImmediate(filter);
    60.             GameObject.DestroyImmediate(renderer);
    61.            
    62.             // Is this now an empty object?
    63.             // Note: Empty object only has transform component
    64.             if (obj.childCount == 0  obj.GetComponents<Component>().Length == 1)
    65.                 GameObject.DestroyImmediate(obj.gameObject);
    66.         }
    67.        
    68.         public void AddChildrenToCombiner(Transform parent) {
    69.             for (int i = 0; i < parent.childCount; ++i) {
    70.                 Transform child = parent.GetChild(i);
    71.                 AddChildrenToCombiner(child);
    72.                 AddToCombiner(child);
    73.             }
    74.         }
    75.        
    76.         public void Combine() {
    77.             List<CombineInstance> finalCombiner = new List<CombineInstance>();
    78.            
    79.             // IMPORTANT: Not compatible with meshes that use multiple materials
    80.             //            Not compatible with meshes that do not use a material
    81.            
    82.             // Combine per-material
    83.             int j = 0;
    84.             foreach (List<CombineInstance> combiner in combiners) {
    85.                 CombineInstance perMaterial = new CombineInstance();
    86.                 perMaterial.mesh = new Mesh();
    87.                 perMaterial.mesh.CombineMeshes(combiner.ToArray(), true, true);
    88.                 perMaterial.transform = gameObject.transform.localToWorldMatrix * correctionMatrix;
    89.                 perMaterial.subMeshIndex = j;
    90.                 finalCombiner.Add(perMaterial);
    91.                
    92.                 ++j;
    93.             }
    94.            
    95.             // Combine final mesh!
    96.             Mesh mesh = new Mesh();
    97.             mesh.CombineMeshes(finalCombiner.ToArray(), false, false);
    98.            
    99.             // Prompt user to save mesh
    100.             AssetDatabase.CreateAsset(mesh, filePath);
    101.             AssetDatabase.SaveAssets();
    102.            
    103.             // Assign mesh to object
    104.             MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
    105.             filter.sharedMesh = mesh;
    106.            
    107.             MeshRenderer renderer = gameObject.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    108.             renderer.materials = materials.ToArray();
    109.         }
    110.        
    111.     }
    112.    
    113. }
     
    Last edited: Mar 22, 2012
  21. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    @numberkruncher Awesome, nice work! I'll take a look at this today.

    Man, I get such a good feeling to see people developing against the tool - thanks so much :D

    -JFFM
     
  22. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    @AlexEvangelou Definitely, I'll put out example code and some updates to the Runtime API blog-post.

    And your answer to our friend @wesllg is spot-on. :)

    -JFFM
     
  23. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I updated the source in the post above. Block prefabs must be marked as "static" in order to be combined. The reason for this is my bouncers stopped working when combined :eek:

    Given this change, it would be handy if the block editor had an "Is Static" check box.

    @Joshua: The problem with the `NullReferenceException` it doesn't occur when designing blocks in a blank scene. It pretty much always occurs when there is a tile map system in the scene though. I also noticed that the phantom block (the one that is being edited) contains twice as many pieces after the `NullReferenceException` which I believe explains why there are too many visible pieces in the same square thereafter. The exception is preventing important block processing which totally breaks the block.
     
  24. wesllg

    wesllg

    Joined:
    Jan 8, 2011
    Posts:
    18
    Thanks guys. That's what I wanted to know. It is entirely feasible to write a combiner as numberkruncher has shown. The other option - as AlexEvangelou said - is to reuse block instances based on the current view. Depends on the game and it's requirements. Thanks.
     
  25. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    Since I still am not able to publish map correctly I might be under the impression publishing doesn't do what I thought it would? After reading numberkruncher's script I'm guessing publishing a map doesn't do this currently...
     
  26. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi Everybody,

    I've just submitted an update for TTM to the Asset Store.

    It adds a "Refresh" button to your map panel (to refresh maps that you have selected) and hopefully, hopefully corrects the error on creating new blocks in existing map scenes.

    This should also correct the tiling act-empty blocks (if you use "Refresh" map on your existing scenes they should be corrected).

    The biggest changes of all, however, are internal - all to support the Runtime API. So please please, backup your projects before updating. I've tried my darnedest not to make any changes that will break any links or destroy any projects, but you can never be too careful.

    The changes I've made internally were all to support more intense use of the Runtime API (like you see in the video a few posts ago), so hopefully the API is nice and semi-robust now. :D

    Enjoy!

    -JFFM
     
  27. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    Hey JFFM,

    The Refresh button addition helps to restore the map, but I still can't publish the map. It doesn't remove the map blocks that aren't enabled, they all are enabled still (it is acting just like the problem I have when I disabled the map then enabled it; same visual errors). It's been a while now since I am trying to figure this out, help. Thanks.

    EDIT: I just figured out that my problem is specific to the block set I am using. The default blockset publishes just fine when I use it to build. I'm gonna test this by deleting my blockset and readding the files, something must've happened when I updated TTM few updates ago?

    EDIT2: Ignore the previous Edit, back to square one....OMG!!
     
    Last edited: Mar 24, 2012
  28. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    So yea, JFFM...

    This is completely driving me crazy!!! Can I get some real help right now with this situation? It doesn't have anything to do with my specific mesh blocks (cause frankly, the same problem happens with the default TTM blocks you provided), it has nothing to do with my project (since I am testing the same thing in a BRAND NEW specific TTM Testing project, with only TTM in the project). Also, when I go to block editor and delete EVERY single block from each orientation, why does the block set still keeps old ones under it's prefab hierarchy?

    The problem just comes about when creating your own custom block set, I continue to add the blocks and as soon as I add a block to any orientation besides center surrounded and center alone, there is a problem with publishing the map. As I said, I tried creating a custom some with the TTM blocks provided and the same problem happens; see pic:

    http://dl.dropbox.com/u/4585058/CM%20Capture%2012.png

    As you can see, the published prefab map on the right is completely different from the raw one on the left. In the hierarchy, you can see in the published map, there are three enabled blocks in the chunk still when publish is supposed to remove the ones that were disabled it the raw map, what the heck (seems to be the same enable/disable problem again but in publish form)? I need some help ASAP because this problem has been haunting for more than a week now; and makes TTM redundant at the moment JFFM. It's also boggling that noone has these problems, or are posting about them which make things more annoying...
     
  29. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    And I am sorry about constant posting, I should just email you JFFM.
     
  30. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    :D Definitely. Just remember I'm on Sydney time here, so my 'awake and able to help' hours begin around now, and end in about 12 hours.

    I'll have a look at your issues and put up an update today.

    -JFFM
     
  31. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    @Jrricky: Cool, standby for a new update - I've found the issue and put together a solution - that should be live within the day.

    For everybody who is curious about how these things go (and as a result, how difficult they are to debug):

    1) When Editing blocks, we create a "Ghost Block" (you've likely seen it) that we add and remove data from (it's a much easier way to handle Undo / Save than using the Undo function in Unity, I found).

    2) When we want to save this, we just replace the parent prefab with the "Ghost Block", which contains all of the new data.

    3) Pre-3.5, this was fine - as replacing the prefab parent of an object in the scene would pull the scene object into line with the new prefab.

    4) Post-3.5, this doesn't work - as the scene object is now a mixture of itself and the prefab parent.

    5) As a result, what we're getting (and what @Jrricky is seeing) is his blocks holding a mixture of the parent blocks and the Ghost Blocks - which turns out to just be... doubling-up of the same blocks, disconnected from any block logic - which is why they aren't being stripped on publishing.

    The solution?

    Upon save, we now disconnect the Ghost Block from its parent prefab, so it's not modified by changes to the parent prefab.

    And then, because I'm still drinking my coffee and in general "Breakfast mode", I'm going to go ahead and socially chat with you for a little about how I debugged this:

    1) I recreated the steps @Jrricky highlighted and saw that the publishing of custom blocks was indeed broken.
    2) I checked the Map Cleaning / Stripping methods and put a billion Debug.Log() in there - but it was working fine.
    3) I created a custom editor script that would go through a block and delete all objects that are linked to BlockSets.

    AH HA!

    3.5) We're left with blocks that are disconnected from anything - which means something is going amiss in the Block Creation logic.
    4) I opened the Block Editor and repeatedly made Block Sets in different Editor states (painting, not painting etc)
    5) This was going nowhere.
    6) I opened the Block Editor and watched the Ghost Block state as I modified the Block.

    AH HA!

    We've found our problem.

    And now you know... the rest of the story.

    -JFFM
     
  32. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hello Everybody,

    Furthermore - since this was an issue within Block Creation, that means custom blocksets you've made may be suffering (structure-wise) from this issue.

    To save you re-creating them, take this script and put it in your project.

    Drag the Block prefab onto the scene that is suffering the issue.

    Click "Clean Block" (all the way at the bottom on the Oriented Block script).

    Replace the parent prefab with this cleaned block.

    Please read and understand the script before applying it - in case you have a custom scenario that this may break.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEditor;
    5. using System.Collections.Generic;
    6.  
    7. [CustomEditor(typeof(OrientedBlock))]
    8. public class OrientedBlockTestScript : Editor {
    9.  
    10.     public override void OnInspectorGUI ()
    11.     {
    12.         base.OnInspectorGUI ();
    13.                
    14.         if(GUILayout.Button("Clean Block")){
    15.            
    16.             OrientedBlock b = target as OrientedBlock;
    17.            
    18.             //This is a function in OrientedBlock
    19.             //It manually populates an array with all of the BlockSets contained within
    20.             //It's handy for things like this
    21.             //But a hassle to maintain
    22.             BlockSet[] bs = b.GetBlockSetsAsArray();
    23.                    
    24.             //We're going to go through our blocksets and mark all blocks
    25.             //That are linked to something as 'protected'
    26.             List<GameObject> protectedObjects = new List<GameObject>();
    27.            
    28.             for(int i = 0; i < bs.Length; i++){
    29.                
    30.                 if(bs == null){
    31.                     continue;
    32.                 }
    33.                
    34.                 GameObject[] o = bs[i].blockSet;
    35.                
    36.                 for(int j = 0; j < o.Length; j++){
    37.                    
    38.                     if(o[j] == null){
    39.                         continue;
    40.                     }
    41.                    
    42.                     protectedObjects.Add(o[j].gameObject);
    43.                    
    44.                 }
    45.                
    46.             }
    47.            
    48.             //Now that we have our protected blocks, we're going to go through the
    49.             //transform hierarchy and joyously murder all blocks that aren't protected
    50.             //It's kind of like the mark on the door
    51.            
    52.             for(int i = 0; i < b.transform.childCount; i++){
    53.                
    54.                 GameObject o = b.transform.GetChild(i).gameObject;
    55.                
    56.                 //If it's not protected....
    57.                 if(protectedObjects.Contains(o)){
    58.                    
    59.                     //Murder it
    60.                     Editor.DestroyImmediate(o);
    61.                    
    62.                 }
    63.                
    64.             }
    65.         }
    66.        
    67.     }
    68. }
    69.  
    70.  
    Hope that helps!

    -JFFM
     
  33. p6r

    p6r

    Joined:
    Nov 6, 2010
    Posts:
    1,158
    I have made this video to show how to make blocks very easily for TTM using Hexagon 2.5 (free until end of march 2012) and Triplanar Texturing (march madness sale !). It's the Part 1 of block's creation !!!



    6R
     
  34. p6r

    p6r

    Joined:
    Nov 6, 2010
    Posts:
    1,158
    This second video is showing how to use Anime Studio to create textures for your blocks. I use my own seamless textures to fill the 2D shapes. Then I simply import my textures and I replace the standard ones for example !!!



    6R
     
  35. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Awesome work as always @p6r!

    :D
     
  36. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hello Everybody,

    The latest update is now online and rearing to go.

    Aside from a fix for the bug that @jrricky was experiencing, I went ahead and fully accidentally left in some other features (that weren't intended for release yet) - so consider that a special feature!

    You'll notice in the Block Editor, in the Block Options (in the foldout at the top) there is now a set of fields for x,y,z offset and x,y,z rotation.

    This will apply offsets or rotations universally across all objects within a Block.

    It was added so that... if you have assets that are all rooted at the bottom (say - a character with a pivot at its feet) - you wouldn't have to nest your objects within another gameobject in order to get a centre pivot - you could instead set your y offset to be -0.5f or such.

    I was actually adding these in order to test using RagePixel with Tidy TileMapper (as RagePixel tiles require a 180 degree y rotation).

    So offset / rotation is a very new, not-intended-to-be-released feature - treat it kindly and report any issues you experience to your humble narrator.

    Enjoy!

    -JFFM
     
  37. AntFitch

    AntFitch

    Joined:
    Jan 31, 2012
    Posts:
    243
    JFFM, your tool looks awesome! I have one quick question. Is it possible to paint shapes like this for the player to walk on? i'm specifically curious about the ramps at the bottom.
     
    Last edited: Mar 25, 2012
  38. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    Yes amaranth, you can use any mesh you want, also with the new offset feature, i think you can have them that close too...
     
    Last edited: Mar 26, 2012
  39. AntFitch

    AntFitch

    Joined:
    Jan 31, 2012
    Posts:
    243
    Woot!!! I'm sold! :D
     
  40. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    Having serious issues with scaling at the moment. I'm creating blocks in modo at 1 standard "Game Unit". I then bring them into Unity and TTM without messing with the scaling and they are HUGE. I'm finding I have to adjust the scaling for the model import to some seemingly random value like 0.00125 to get things to tile properly.

    Anyone know if there's any science to this (i.e. a particular scaling method I should be using) or is it just a guessing game when importing from an external modelling package?
     
  41. mgrenier

    mgrenier

    Joined:
    Apr 26, 2011
    Posts:
    57
    From the chapter "Creating Game Objects Using modo" of "Creating 3D Game Art for the iPhone with Unity" (2011)

    Hope it does help you.
     
  42. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    The scaling varies depending upon which 3D modelling software that you are using.

    When using Blender, for example, I use 1 Blender unit for each Unity unit for simplicity. But when imported into Unity the mesh is exactly twice the required size. So I simply set all my mesh importer scales to 0.5 to correct the issue. When using other software like 3dsmax, Cinema4D there are different scale differences.

    When using Blender with 1 unit cubes and using the 0.5 scale correction in the mesh importer, setting the TTM scale to 1 seems to provide perfect tessellation. What modelling software are you using?
     
  43. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    I have that book :) Normally importing from modo and using the standard 0.01 scaling works fine. But for use with TTM, I've had to change the scaling to 0.00125 to make the modo cubes sit properly in the TTM grid. That's what I was questioning - seems odd, and "random" - was trying to figure out WHY I'm needing to do that.

    It would actually be kind of nice if TTM scaled the tiles automatically - as in, regardless of the size of the GameObject being tiled, it gets scaled to the equivalent of a standard Unity unit (like a standard Unity cube primitive).

    Anyway... I shall keep on playing around.
     
  44. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    This is exactly what I hoped/thought TTM did when I first bought it, instead your actually scaling TTM to your models size which I think JFFM should consider looking into.
     
  45. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    Just to follow up as far as modo goes, Wes actually posted this video recently:

    http://the3dninja.com/blog/?p=1766

    Following that, your imported modo cube is exactly the same size as a standard Unity cube, and this then works perfectly as a tile in TTM.
     
  46. AntFitch

    AntFitch

    Joined:
    Jan 31, 2012
    Posts:
    243
    When I create a grid that is 100x100 and flood fill it with a block, Unity freezes. This happens each time I attempt to build a grid for a large map. Is there a fix for this? I can use TTM to build small games, but definitely not a top-down RPG, for which it would be perfect.

    My request is for there to be a focus on optimization. AND to look at the RPG Maker XP editor to see how to build an easy-to-use map editor and tile collision system for 3D.

    *UPDATE*
    Okay, I think I see the problem... Every block is a game object? If that's true, no wonder performance goes through the roof if you try to create a relatively large level. Have you thought about finding a way to "fake" game objects? There must be some sort of clever way to do this...
     
    Last edited: Mar 27, 2012
  47. Damaniel

    Damaniel

    Joined:
    Mar 27, 2012
    Posts:
    1
    Yep - this is nailing me, too. I want to use the runtime API to generate a world -- nothing huge (yet), but probably in the 128x128 range. However, attempting to do this (eventually) causes the Mono GC to go nuts and Unity to crash.

    Also, are there any plans to offer more detailed instructions about the world streaming feature that you showed off in your blog? I could definitely take advantage of it, and my knowledge of Unity is still pretty limited at this point, so pointers are always helpful.
     
  48. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    Hi @amaranth and @Damaniel,

    There are two approaches I'd recommend for building larger worlds and preserving performance:

    1) The Runtime API - as you've hit on, the Runtime API is good for this, but is accessible at a procedural level, so you lose the fine-grained control and design over your map structure.

    2) Divide your level into separate adjoining Maps. I would recommend this for larger maps over which you want to retain design control - not just for Editor performance, but also for game performance.

    I'll likely put the Streaming Map feature on the Asset Store in the near future, once I've tweaked it and made sure it works nicely on mobile.
    I'm going to add a "Convert Map to Streaming Map" panel to allow the developer to pull an Editor-designed map into the Streaming Map data structure.

    -JFFM
     
  49. JFFM

    JFFM

    Joined:
    Nov 13, 2010
    Posts:
    336
    @amaranth - just while I'm thinking about it:

    When you say you flood-fill a 100x100 grid with a block - do you mean you created a map with 100x100 chunk size and click on the resulting chunk with the block you want?

    -JFFM
     
  50. AntFitch

    AntFitch

    Joined:
    Jan 31, 2012
    Posts:
    243
    Here were my map creation settings:

    Round 1
    block size: 1
    chunk size: 100
    Map created. Turn paintbrush on. Select tile. Click in map. Freeze.

    Round 2
    block size: 1
    chunk size: 5
    Map created. Turn paintbrush on. Select tile. Click in map. Paints. As each new chunk added, system slows down. Flood filling is slow painful process. My bet is there is a way not to use game objects for tiles.

    I don't suppose you could look at Minecraft? The dev found a way to create loads of blocks w/o slowing down the processor. Maybe it's something Unity can't handle, but from what I've seen you create, I bet you'll figure out a solution.
     
    Last edited: Mar 28, 2012