Hello Guest

Author Topic: Animated tiles and a suggestion  (Read 8291 times)

ComputerNerd

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 18
    • View Profile
Animated tiles and a suggestion
« on: June 11, 2016, 08:44:51 am »
Hi,

Great tool!

I spent some time agonizing over the pain of implementing animated tiles to complement my game.  I saw your suggestion about using materials, and decided that that is the best approach, although it had some drawbacks.

Due to the heavy use of animations in my game, each tile set needed quite a few Materials made.  This is where I ran into problem number 1.  Adding a new material performs a Commit.  Each commit takes five minutes, so adding 20 materials takes quite a long time.  My suggestion here is to remove the automatic Commit when adding a material since you need to still perform some work before you do your real Commit.  I tested out this theory and everything works fine.  You can also probably remove the automatic commit when deleting a material.

Then problem number 2 came.  Animated tiles' materials' textures don't normally have the same UV coordinates as the tile set.  Modifying material tiling and offsets seemed kind of hacky and didn't solve some of my issues.  There is no great solution to this problem, but what worked for me is to keep it simple and allow the Sprite Collection to store custom UV values - only when doing additive materials - and let the Material and Shader do the rest.  I think this solution would work for most use cases.

Which leads me into problem number 3.  I am now stuck in my current version of the 2D Toolkit.  Unless you were kind enough to consider implementing a UV solution similar to mine...

My main goal was not to touch tk2dSpriteDefinition.  Here's my code.

Class: tk2dSpriteCollectionDefinition
Added public fields:
    public bool UseCustomUV = false;
    public Vector2[] CustomUV = new Vector2[] {new Vector2(0,0),
                                               new Vector2(1,0),
                                               new Vector2(0,1),
                                               new Vector2(1,1)};
    public Vector2 UvOffset;
   
   
Function: CopyFrom
Added:
        CustomUV = src.CustomUV;
        UseCustomUV = src.UseCustomUV;
      

Class: tk2dSpriteCollectionBuilder
Function: UpdateVertexCache
Code location: Directly above the line:
coll.spriteDefinitions.normalizedUvs = CalculateNormalizedUvs(uvs);
Code:
   if (gen.textureParams.UseCustomUV)
   {
      coll.spriteDefinitions.uvs = gen.textureParams.CustomUV;
      for (int l = 0; l < coll.spriteDefinitions.uvs.Length; l++)
      {
         coll.spriteDefinitions.uvs[l] = coll.spriteDefinitions.uvs[l] + gen.textureParams.UvOffset;
      }
   }
            
And then the Editor changes.
Class: tk2dSpriteCollectionEditorSpriteView.cs
Function: DrawSpriteEditorInspector
Code location: Just after the Material popup.
Code:
   param.UseCustomUV = EditorGUILayout.Toggle("Custom UV", param.UseCustomUV);
   param.CustomUV[0] = EditorGUILayout.Vector2Field("uv1", param.CustomUV[0]);
   param.CustomUV[1] = EditorGUILayout.Vector2Field("uv2", param.CustomUV[1]);
   param.CustomUV[2] = EditorGUILayout.Vector2Field("uv3", param.CustomUV[2]);
   param.CustomUV[3] = EditorGUILayout.Vector2Field("uv4", param.CustomUV[3]);
   param.UvOffset = EditorGUILayout.Vector2Field("uvOffset", param.UvOffset);

Note: When it is placed in this location, it will only show if the user is using multiple materials.


Thank you for the great tool!

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Animated tiles and a suggestion
« Reply #1 on: June 20, 2016, 09:00:15 pm »
Hi there,

I wonder why you're doing this -
coll.spriteDefinitions.uvs[l] = coll.spriteDefinitions.uvs[l] + gen.textureParams.UvOffset;

Instead of simply adding a bool that will assign the normalized uvs to the main uvs as an option? Do you need access to the rect in the atlas too?

Every time I've done this I simply have a full texture animation and only ever use the main sprite as an icon representing it in the picker

ComputerNerd

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: Animated tiles and a suggestion
« Reply #2 on: June 21, 2016, 05:33:55 am »
Thanks for the reply!

Regarding the line of code you commented about - prior to that loop I set the uv's to the custom coordinates with this:
coll.spriteDefinitions.uvs = gen.textureParams.CustomUV;

I do not use the atlas' uv coordinates.  In hindsight I should have applied the offset to CustomUV first before setting it to spriteDefinitions.uvs to eliminate confusion.

I have a bool to turn it on or off called UseCustomUV.  I sometimes have an animation that is larger than a single tile, where a series of tiles represent that animation.  The offset makes this easier and faster to enter coordinates for these larger animations.  These larger animations are also why I allow entry for all four UV coordinates.  Well, that or if the user wants to do something funky.

I am handling things similar to you - the Tile in the Tileset is merely a placeholder for the animated material.  The original UV rect does not apply to me in these animations, so I use the custom uv values to properly handle my animations.

How do you handle these situations without plugging in UV values?  Do you adjust the material scale and offset?  I was unable to acquire 1:1 accuracy with this method; the animations were always a little too big or a little too small.  I was also unable to reuse an animation with another Sprite Collection without creating a new material.  With the scope of my game in mind that would have caused me to create hundreds of extra materials.  It also didn't seem compatible with larger animations without creating more materials.  Custom UV's allowed me to use just one material per animation no matter how large the animation and across all Sprite Collections.  I imagine this would also result in fewer draw calls.  I need them to be 1:1 with the rest of the tiles.

My requirements are this:
1:1
Support for larger animations where the tile represents only a piece of it.
Keep the material count limited

What do you recommend?

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Animated tiles and a suggestion
« Reply #3 on: June 27, 2016, 10:59:15 pm »
> Keep the material count limited
This is the tricky one - I've not really bothered with trying to save for draw calls here as the materials have always been custom shaders or animations with a lot of frames. And even when they haven't been, frankly not really bothered with anything else as performance has never been an issue.
1:1 has not been an issue either, as the material is set up correctly.

But I do see your point about the custom UV range, that could come in handy. I'll see what I can do for the next release.

Kirb

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 36
    • View Profile
Re: Animated tiles and a suggestion
« Reply #4 on: July 11, 2016, 11:38:19 pm »
Thanks for this, this solution looks exactly like what I need. Trying to use materials and shaders for my fairly basic tileset animations is very quickly growing unwieldy with multiple identical animations per tilemap. (Also, my animation UVs break every single time I add or remove tiles from the spritesheet in question, making the entire process super frustrating...)



@ComputerNerd

I run into errors whenever I try this:

Code: [Select]
Class: tk2dSpriteCollectionBuilder
Function: UpdateVertexCache
Code location: Directly above the line:
coll.spriteDefinitions.normalizedUvs = CalculateNormalizedUvs(uvs);
Code:
   if (gen.textureParams.UseCustomUV)
   {
      coll.spriteDefinitions.uvs = gen.textureParams.CustomUV;
      for (int l = 0; l < coll.spriteDefinitions.uvs.Length; l++)
      {
         coll.spriteDefinitions.uvs[l] = coll.spriteDefinitions.uvs[l] + gen.textureParams.UvOffset;
      }
   }

into the specified script.

Quote
Assets/TK2DROOT/tk2d/Editor/Sprites/tk2dSpriteCollectionBuilder.cs(1935,55): error CS1061: Type `tk2dSpriteCollectionDefinition[]' does not contain a definition for `UseCustomUV' and no extension method `UseCustomUV' of type `tk2dSpriteCollectionDefinition[]' could be found (are you missing a using directive or an assembly reference?)

Assets/TK2DROOT/tk2d/Editor/Sprites/tk2dSpriteCollectionBuilder.cs(1938,50): error CS1061: Type `tk2dSpriteDefinition[]' does not contain a definition for `uvs' and no extension method `uvs' of type `tk2dSpriteDefinition[]' could be found (are you missing a using directive or an assembly reference?)

Any ideas?
« Last Edit: July 12, 2016, 01:37:21 am by Kirb »

Kirb

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 36
    • View Profile
Re: Animated tiles and a suggestion
« Reply #5 on: August 02, 2016, 03:17:56 am »
No dice? Could there be some missing code in the OP? As far as I can tell, I had pasted the lines appropriately.

ComputerNerd

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: Animated tiles and a suggestion
« Reply #6 on: August 02, 2016, 05:35:25 am »
Might be a version incompatibility.  I think I'm using a version that's about a year old.  I don't see any indication of which specific version I am on though.

Kirb

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 36
    • View Profile
Re: Animated tiles and a suggestion
« Reply #7 on: August 03, 2016, 11:09:33 pm »
Ah, dang. Yeah, that's probably it; I'm using the most recent version.