Search Unity

Rotorz Tile System for painting 2D and 3D tiles!

Discussion in 'Assets and Asset Store' started by numberkruncher, May 10, 2012.

  1. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    What would be the best API method (if available) to get the top, bottom, left, and right positions of the grid? I'm working on a mouse camera scrolling action for PlayMaker and the scrolling works great, but I need to get the grid boundaries so I can limit the camera to only the grid.
     
  2. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Hello Krileon

    There are a number of ways to get the minimum and maximum extents, but the following is probably the simpler:

    Code (csharp):
    1.  
    2. TileSystem s = ... ;
    3.  
    4. Vector3 minPosition = s.transform.position;
    5. Vector3 maxPosition = s.WorldPositionFromTileIndex(s.rows, s.columns, false);
    6.  
    You may find the following documentation useful:

    Let me know if this helps!
     
  3. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Awesome, thank you; will give it a shot.

    Update: Got it completely working. Now have a PlayMaker action that lets me scroll the camera with the boundaries of the screen upto the boundaries of the grid. The below gave me the boundaries (note this is for side scroller so X and Y axis, but can be easily adjusted).

    Code (csharp):
    1.  
    2.             Vector3 worldPosition = system.WorldPositionFromTileIndex( system.rows, system.columns, false );
    3.  
    4.             gridTop.Value = system.transform.position.y;
    5.             gridBottom.Value = worldPosition.y;
    6.             gridLeft.Value = system.transform.position.x;
    7.             gridRight.Value = worldPosition.x;
    8.  
    Thanks for the help!
     
    Last edited: Feb 7, 2013
  4. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    No problem, glad that I could help :)
     
  5. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    The only suggestion that I would make would be to use the following instead to avoid multiple component lookups and simplify access to position. The position is calculated from matrix multiplications upon each access.

    Code (csharp):
    1.  
    2. Vector3 worldPosition = system.WorldPositionFromTileIndex( system.rows, system.columns, false );
    3. Vector3 anchorPosition = system.transform.position;
    4.  
    5. gridTop.Value = anchorPosition.y;
    6. gridBottom.Value = worldPosition.y;
    7. gridLeft.Value = anchorPosition.x;
    8. gridRight.Value = worldPosition.x;
    9.  
     
    Last edited: Feb 7, 2013
  6. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    lol, already made that change after my above post and just didn't edit it in. Thanks. :)
     
  7. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Is it possible to render the grid seen in the editor in gameplay mode? My idea is to render the grid during realtime editing so the user has an easier time seeing where they're painting. My game consists of placing various tools to help the minions escape and being able to see the grid plus box highlighting would be extremely helpful.
     
  8. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    The grid that is displayed in the Unity editor is drawn using an editor-only class. Though there are ways to present a similar grid at runtime:
     
  9. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Ok, thank you for the pointers. I'll tinker around and see what I can come up with. Vectrosity looks pretty neat. I also have Unity Pro now so GL one maybe a good option as well.
     
  10. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Hey guys,

    Version 2.0.1 released to the asset store with some minor bug fixes, new standalone preferences window. You can now choose between the wireframe cube / flat shaded tile cursor - whichever you prefer! By default the wireframe cube is used for 3D tiles and the flat shaded cursor is used for 2D tiles.

    See release notes for more information.

    Special offer - 35% off until 20th February 2013!!

    $icon.png
     
    Last edited: Feb 15, 2013
  11. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Possible to have blocks that take up more than 1 block space? for example XX instead of just X when painting (where X = 1 block).
     
  12. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    @Krileon Each block will only consume one cell in the tile system. Though your block mesh can overlap multiple cells in the tile system which will visually appear to consume multiple cells. That way you paint a single tile and it will appear to consume multiple cells.

    I hope that this is of help :)
     
  13. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    If the mesh consumes multiple spaces will I be able to paint another tile in one of the other spots that it consumes? Don't want to end up with overlap.
     
  14. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Yes, you would still be able to paint in the surrounding cells because they are actually still vacant.

    Generally you cannot take advantage of automatic orientation for singular tiles that are spread across multiple tile spaces. It is usually better to paint such tiles individually to avoid overlap.
     
    Last edited: Feb 15, 2013
  15. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Ok, will just have to deal with the overlap maybe at runtime if it should happen (raycast and remove if needed). Not too big a deal. I'm also curious about a level editor. I noticed you can turn a grid into a prefab; does this work at runtime? It'd be cool to be able to paint a level (easy to implement) then when it's done click a save button that turns it into a prefab and stores to their computer.. you could then load that prefab level back in an edit it again.. seams like a cool idea and be easier then some odd save system. Think this could work?
     
  16. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Unity does not provide an API for creating prefabs a runtime. Prefabs are an editor-only concept.

    There are many, many ways to achieve this. Here is the solution that I would use if I were going to implement such a thing. This may not be the best solution, but it would certainly work!

    Implement your own serialization and pick one of the following:

    The idea of using both local storage (perhaps file based) and WWW is that you can create levels and then share them with friends online!

    There is no catch all way of representing your in-game level designs because you will likely need to store information that is very specific to your implementation. For example, if you allowed the player to paint keys and doors, then you would likely need a way to specify which key works with which door using a custom GUI and MonoBehaviour classes. Thus your data structure would need to cater for that.

    XML is probably the easiest representation to persist your data in. You would need to store some meta information about your level, a lookup table for brushes, and information about non-empty tiles. The following might be a good starting point:
    Code (csharp):
    1.  
    2. <?xml version="1.0" encoding="utf-8"?>
    3. <level>
    4.    <meta>
    5.       <title>Some Amazing Level</title>
    6.       <description>Get to the end without falling down the hole. Things are
    7.           not as they appear!</description>
    8.       <rows>10</rows>
    9.       <columns>10</columns>
    10.    </meta>
    11.    <brush-map>
    12.       <brush i="0" guid="7360cee2-3a47-4b73-a8aa-89d1eccab30f"/>
    13.       <brush i="1" guid="3bfdeb2d-aefb-4443-91bd-67187916c65f"/>
    14.       <brush i="2" guid="d7ccfe5c-e4b5-4e25-a4b4-7e1570bed889"/>
    15.       <brush i="3" guid="0a0ff522-5038-4a92-a7ab-81441d1c2417"/>
    16.    </brush-map>
    17.    <tiles>
    18.       <tile x="2" y="2" brush="1">
    19.          <param name="door-id">1</param>
    20.       </tile>
    21.       <tile x="8" y="4" brush="3">
    22.          <param name="open-mode">slide</param>
    23.       </tile>
    24.    </tiles>
    25. </level>
    26.  
    The brush map at the start is a simple lookup table which allows tiles to reference brushes by a shorter zero-based index instead of by GUIDs. The only reason to do this is to reduce the file size of your levels!

    You could create a relatively simple editor script which creates and maintains an asset file which a) allows your level loader to access the brushes that it needs to, and b) associate available brushes with GUIDs. The script would need to generate GUIDs for brushes that it does not already contain, remove mappings for brushes that have been deleted (just check for null), and maintain GUIDs for existing brushes (so as not to break any saved levels!).

    Your editor script can access all brushes via the BrushDatabase and generate GUIDs in the regular .NET fashion. You might even want to filter the brushes that you choose to provide at runtime by filtering brush categories.

    Your brush map asset could use a scriptable object like the following for its data representation:
    Code (csharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Rotorz.Tile;
    5.  
    6. public class LevelLoaderBrushMap : ScriptableObject {
    7.     public Brush[] brushes;
    8.     public string[] guids;
    9.  
    10.     // Unity cannot serialize dictionaries unfortunately, so we must do this ourself!
    11.     [System.NonSerialized] // just in case things change in the future!
    12.     private Dictionary<string, Brush> _map;
    13.  
    14.     void OnEnable() {
    15.         int entries = Mathf.Min(brushes.Length, guids.Length);
    16.  
    17.         _map = new Dictionary<string, Brush>();
    18.         for (int i = 0; i < entries; ++i) {
    19.             // Brush can be ignored because it doesn't exist anymore.
    20.             // An editor script should automatically remove these unwanted entries!
    21.             if (brushes[i] == null)
    22.                 continue;
    23.  
    24.             // Add brush to map
    25.             _map[guids[i]] = brushes[i];
    26.         }
    27.     }
    28.  
    29.     public IEnumerable<KeyValuePair<string, Brush>> Entries {
    30.         get { return _map; }
    31.     }
    32.  
    33.     public Brush Lookup(string guid) {
    34.         return _map.ContainsKey(guid)
    35.             ? _map[guid]
    36.             : null;
    37.     }
    38. }
    39.  
    When loading levels it is very important to utilise the bulk painting feature of Rotorz Tile System. This allows the data structure to be formed before tiles are picked and painted. This helps performance a lot!!
    Code (csharp):
    1.  
    2. tileSystem.BeginBulkEdit();
    3.  
    4. // paint lots of tiles
    5.  
    6. tileSystem.EndBulkEdit(); // this is the most intensive part of level load
    7.  
    See:
     
    Last edited: Feb 16, 2013
  17. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    I see, awesome! Thank you, has given me some good ideas and will explore various approaches. Still a bit off from implementing the level editor, but I got a lot of good features working now (grid that 1:1 matches the Rotorz grid as well as Grid Highlighting!).
     
  18. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Fantastic stuff! Please post a screeny when your done, I would love to see what you come up with :)
     
  19. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Sure, here's a current progress screenshot. The GUI is temporary and just so I can get functionality implemented, but you can see the grid, highlighting, and placement.



    For all but Pick Axe the highlight will be green if on an empty space. If on a space that is occupied by a block it'll turn red and disable the preview. Pick Axe is basically the opposite of that. Basically you can't place blocks where a block already exists (intentional gameplay).

    All of my gameplay is done with PlayMaker as well, average FPS is over 60 with vsync, with vsync off it's well over 200.. I've also Pro so have profiled it and it's very lightweight.. no idea how it'd work mobile though as I develop for PC only.
     
    Last edited: Feb 17, 2013
  20. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Awesome, its looking neat!

    I like the ghosted preview piece. Somebody created a plugin to Rotorz Tile System which added a similar effect to the in-editor paint tool which I thought was quite cool. I have been experimenting with an in-editor solution which has very little overhead and seems to work in both Unity Pro and non-Pro. This has been requested several times so I will try to get that into a near future update if it doesn't damage in-editor performance.

    Until recently (with my latest GPU) I have had to play games with vsync disabled because it caused them to run poorly. My current GPU is fantastic though and I can get very high average FPS. And the best part was that the card was relatively cheap compared to what I paid for my previous GPU.
     
  21. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Thanks, the way I do the ghosting is to just create a game object of the brush object and enable/disable it as needed and replace its material with one that has opacity; the collisions are also removed.

    I'll have more screenshots and videos when I get closer to a completed beta, but this is a hobby for me and have a full time web development career so only putting in 1-2 hours a day.. might take me awhile, lol.
     
  22. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    The approach that I am considering is using the Graphics class. At runtime this is Unity Pro only, but in edit mode it appears to work for non-Pro also!!
    Code (csharp):
    1.  
    2. Material previewMaterial;
    3. Mesh previewMesh;
    4.  
    5. Matrix4x4 matrix = Matrix4x4.TRS(position, rotations, scale);
    6.  
    7. foreach (int pass = 0; pass < previewMaterial.passCount; ++pass) {
    8.     previewMaterial.SetPass(pass);
    9.     Graphics.DrawMeshNow(previewMesh, matrix);
    10. }
    11.  
    Sweet! I would be happy to BETA test your game for you :)
     
  23. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Yeah, I don't think Editor is restricted by license as to allow 3rd party assets to utilize additional features. Sounds like a good addition for next release!

    Sounds good to me, after internal Alpha testing by my family I'll have a limited public beta after I launch the website and such. Hoping I'll have a beta by summer time, but just depends on how long this all takes me (being 1-2hrs a day at most usually). Gameplay is nearly complete though and then I've all the UI to get implemented.. then finalize the art, lol.. only art I got finalized was the actual characters, because I got tired of looking at a cube lol.
     
  24. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Still more testing to do before I release this update, but the previews appear to be working fine for all brush types:

    $tile-previews.jpg

    I am also going to add some options so that you can change the colour of the preview, or alternatively hide it altogether.
     
    Last edited: Feb 19, 2013
  25. Wenceslao

    Wenceslao

    Joined:
    Feb 7, 2009
    Posts:
    142
    Does the Rotorz Tile System easily handle tiles to create ramps? I don't see why it would be a problem but I thought I'd ask.
     
  26. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Yes you can create ramps:
    • A 3D ramp can be defined by creating a prefab and then adding that to an oriented brush for painting. Custom colliders can be added to prefab as usual if required.
    • A 2D ramp can be defined by creating a tileset. Custom colliders can be attached to tileset brush if required by using a prefab. Alternatively you might opt for custom collision detection based upon index of tile used in 2D tileset.

    I hope that this helps!

    See Krileon's screenshot which has a ramp:
     
  27. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I have submitted the new "Immediate Tile Preview" feature to the asset store for approval! It is now far easier to paint tiles using meshes that are larger than one tile unit in size:

    $ghost-preview.png
     
    Last edited: Feb 21, 2013
  28. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Nice! I have a question though; what exactly does the Scale Mode of "Use Tile Size" do? I tried using it on a prefab larger than a tile and it didn't do anything. I was under the impression it'd scale the prefab down to the exact size of a tile.
     
  29. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Scale Mode: Use Tile Size
    Scale of painted tile is magnified by specified tile size (of tile system). If your tile size is 1x1x1, then this option it will behave no differently to "Dont Touch".

    Here is an illustration to hopefully demonstrate this:

    $scale-mode-illustration.png

    In version 2.0.2 this functionality has been revamped offer better performance. Also due to request, prefab rotation transform is now applied to tile scale for consistency purposes.
     
    Last edited: Feb 21, 2013
  30. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
  31. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
  32. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    New feature in version 2.0.3 (available very soon) making it extremely easy to utilise the prefab offset feature:



    Note: Better to switch to HD version of video!
     
    Last edited: Feb 23, 2013
  33. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Nice! Looks like a very handy feature to have. As is I've been just keeping my models as single tiles then using variants to tile them together. This basically lets me have an endless bridge, short or long, it's very cool.. really love this asset.. it and PlayMaker are my most used for sure.
     
  34. AntFitch

    AntFitch

    Joined:
    Jan 31, 2012
    Posts:
    243
    I'm not doing 3D right now, but that looks awesome!
     
  35. GermyGames

    GermyGames

    Joined:
    May 20, 2012
    Posts:
    38
    Is there a way to change the folder that TilePrefabs are generated to? I want them to be generated in a resources folder so that specific brushes designated by a config file can be loaded when needed.

    I can move them by hand and everything works fine as long as it's moved inside of Unity. It's just one extra step that could potentially break at some point down the line.
     
  36. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    The destination of generated brush assets cannot be changed. I take it your using version 1.x of Rotorz Tile System since in later versions this folder is called "TileBrushes"?

    In either case, you can move them by hand if you need to. You can still modify them using the brush designer after they have been moved provided that they are in a folder called "TilePrefabs" (v1) or "TileBrushes" (v2).

    If you want to be able to access brushes at runtime then a better approach might be to write a simple editor script which generates a configuration asset (ScriptableObject) which provides access to all of the brushes at runtime. You can then associate your custom asset with your custom scripts to access the brushes as needed. This is a technique which several people have used. Your editor script can enumerate all available brushes and tilesets using the BrushDatabase class.

    I hope that this is of help, but please let me know if you have further questions and I will do my best to assist :)
     
  37. x_ming_x

    x_ming_x

    Joined:
    Jan 1, 2013
    Posts:
    46
    Hello There Numberkruncher

    Thanks for your earlier help, i managed to get everything working perfectly, but with the new changes in v2 im now going to have to rework a few areas of my tile creator script to support the new scriptable object brushes, and im a bit stuck..

    Im trying to create one of these scriptable object brushes by script in the editor, should i be calling the CreateOrientedBrush method ? if so please could you give me an example of how this is done, or the method i should use.

    many thanks and nice work on the upgrade.
    ;)
     
  38. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Sure, no problem!

    Yes that's right.

    Code (csharp):
    1.  
    2. // Create a blank oriented brush
    3. OrientedBrush newBrush = BrushUtility.CreateOrientedBrush("Name For Brush");
    4. if (newBrush == null) {
    5.     // An error occurred whilst attempting to create brush...
    6.     return;
    7. }
    8.  
    9. // Brush will already contain the "default" orientation
    10. BrushOrientation orientation = newBrush.DefaultOrientation;
    11.  
    12. // Add tile prefab variation to orientation
    13. GameObject prefabVariation = somePrefabGameObject;
    14. ArrayUtility.Add<Object>(ref orientation.variations, prefabVariation);
    15.  
    16. // Add nestable brush to orientation
    17. // Note: You cannot nest oriented or autotile brushes!
    18. Brush brushVariation = someNestableBrushObject;
    19. ArrayUtility.Add<Object>(ref orientation.variations, brushVariation);
    20.  
    21. // Mark brush as dirty because variations have been added
    22. EditorUtility.SetDirty(newBrush);
    23.  
    The Unity utility class ArrayUtility is particularly useful here.

    Thanks, a lot of effort went into this upgrade!
     
  39. x_ming_x

    x_ming_x

    Joined:
    Jan 1, 2013
    Posts:
    46
    wow fast support , awesome ;)

    ok im trying your code sample but im getting

    The name `BrushUtility' does not exist in the current context

    the script has "using Rotorz.Tile;"
     
  40. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    For editor scripts you also need "using Rotorz.Tile.Editor;"
     
  41. x_ming_x

    x_ming_x

    Joined:
    Jan 1, 2013
    Posts:
    46
    yep thats what i thought when reading the api but when i add "using Rotorz.Tile.Editor;" i get

    The type or namespace name `Editor' does not exist in the namespace `Rotorz.Tile'. Are you missing an assembly reference?

    heres whats at the top of my script

    using UnityEngine;
    using UnityEditor;
    using System.Collections;
    using System.Collections.Generic;
    using Rotorz.Tile.Editor;
    using Rotorz.Tile;
    using System.Linq;
    using System.IO;

    thanks again for your quick response
     
  42. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Can you verify the following for me:

    - Is your editor script in an "Editor" directory?
    - Is the assembly "Assets/Rotorz/Tile System/Editor/TileSystem.Editor.dll" present?
     
  43. x_ming_x

    x_ming_x

    Joined:
    Jan 1, 2013
    Posts:
    46
    ah ok i was using a function on the game object component to call into your editor, ive pasted it into the editor directory and its compiling ok, so ive gotta juggle things around a bit and move them over to my editor script, so all is good and ive learnt a new thing about the editor namespace.
    ill have to crack on with that tomorow as its getting late here.
    thanks for helping out a namespace noob ;)
     
  44. x_ming_x

    x_ming_x

    Joined:
    Jan 1, 2013
    Posts:
    46
    Hello Numberkruncher

    im almost there , ive setup the funcs in the editor script and its all good , buuut ive just spent a few hours trying to add an orientation to the new brush with no success,

    please could you post an example of how to create / add a new orientation to the brush weve just created,

    thanks
     
  45. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    To add a new orientation to your brush:

    Code (csharp):
    1.  
    2. // Create empty orientation for Upper-Left corner
    3. //    000
    4. //    0X1
    5. //    011
    6. int topLeftCornerMask = OrientationUtility.MaskFromName("00001011");
    7. BrushOrientation topLeftCorner = new BrushOrientation(topLeftCornerMask);
    8.  
    9. // Add orientation to brush
    10. brush.AddOrientation(topLeftCorner);
    11.  
    12. // Add variations to brush like before
    13. ...
    14.  
    15. // Mark brush as dirty now that you have added orientation/variations
    16. EditorUtility.SetDirty(brush);
    17.  
     
  46. x_ming_x

    x_ming_x

    Joined:
    Jan 1, 2013
    Posts:
    46
    nice one, ive managed to get everything working thanks to your help ,

    5 star support ;)
     
  47. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I would like to apologise to people who have upgraded to version 2.0.3 because a bug was introduced which is causing problems for some users.

    This issue has been resolved in version 2.0.4 which has been submitted to the asset store for approval and will be available very soon. Please contact support (http://rotorz.com/contact) with your invoice number if you would like to have version 2.0.4 sent to you directly.

    If you haven't updated to version 2.0.3, please wait until 2.0.4.
     
  48. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Rotorz Tile System version 2.0.4 is now available from the asset store.
     
  49. DeepShader

    DeepShader

    Joined:
    May 29, 2009
    Posts:
    682
    What will be the best tool to create easy tiles/graphics for Rotorz Tile System?
     
  50. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    That depends very much upon what you are aiming to create and what you are familiar with. I personally use Adobe Photoshop for all 2D artwork and Blender for most 3D stuff.

    In the past I have had quite a lot of experience with Autodesk 3D Studio Max and Maxon Cinema 4D and can confirm that they are excellent tools. Max used to be my preference but in recent years I have grown to prefer Blender.

    Choice of tools is primarily a matter of preference and financial constraints.