2D Toolkit Forum
2D Toolkit => Support => Topic started by: Biktor on October 17, 2014, 06:39:38 pm
-
First of all, excuse me because maybe this is a very basic question, but I'm a noob on Unity and 2d Toolkit.
I guess there are two techniques to animate tiles:
- Setting up certain tiles to be replaced by prefabs, this technique is explained in your tutorial ( http://www.2dtoolkit.com/docs/latest/tilemap/tutorial.html (http://www.2dtoolkit.com/docs/latest/tilemap/tutorial.html)) I understand it, no problema with it.
- The other option is what I don't understand. Here is your answer on this topic ( http://forum.unity3d.com/threads/2d-toolkit-2d-in-unity-made-simple-released.93287/page-49 (http://forum.unity3d.com/threads/2d-toolkit-2d-in-unity-made-simple-released.93287/page-49)):
About animated tiles. This is always super tricky as sprites in the tile map aren't really sprites at all, they're merged and optimised into a larger mesh. However, this is doable using shaders - use material overrides on the sprite collection ( http://2dtoolkit.com/docs/latest/tutorial/multiple_materials_in_a_sprite_collection.html (http://2dtoolkit.com/docs/latest/tutorial/multiple_materials_in_a_sprite_collection.html)) to assign an animating material. Whenever you paint that sprite in, it gets replaced with your sprite. We'll possibly make a sample showing how you can achieve this in the next version of tk2d.
Could explain me this technique?
Thank you very much.
-
2. If you use material overrides, you can replace the material with ANYTHING. It doesn't even need to use the same texture as the atlas. Eg. if you want to make a water shader, you create a placeholder sprite in your main sprite collection, then override the material on that and apply a completely different water texture. You can then animate this material / shader. Your water wont be atlased with the rest but that really isn't a problem because its animated anyway.
-
First of all, thank you for the quick answer.
This weekend I have read some tutorials about this.
My game is targeted to mobiles and tables, so my question is:
What would be the best way to achieve this, by script ( http://wiki.unity3d.com/index.php?title=Animating_Tiled_texture (http://wiki.unity3d.com/index.php?title=Animating_Tiled_texture)) or creating a special shader that basically does the same thing?
Please give me some clue.
Thank you very much.
-
Hi,
I think the shader will be easiest to do. Be sure to use a vertex and frag shader and not a surface shader. You can perform the animation in the vertex shader and can afford to be quite lazy there.
-
Ok, here is my shader:
Shader "Custom/2DAnimatedTile"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
// Create the inspector values
_TotalFrames ("Total FRames", Float) = 0.0
_FPS ("FPS", Float) = 0.0
}
SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//Create the connection to the properties inside of the
//CG program
float _TotalFrames;
float _FPS;
float _Tick;
v2f vert (appdata_base v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f i) : COLOR
{
//ANIMATION
//Lets calculate the width of a single cell in our
//sprite sheet and get a uv percentage that each cel takes up.
float frameUVPercentage = 1.0/_TotalFrames;
//Lets store our UVs in a variable
float2 spriteUV = i.texcoord;
_Tick = frac(( _Time.y + frameUVPercentage ) * _FPS) - frameUVPercentage;
spriteUV.x = ( spriteUV.x + frameUVPercentage ) + ( floor( _Tick * _TotalFrames ) * frameUVPercentage );
fixed4 col = tex2D(_MainTex, spriteUV);
return col;
}
ENDCG
}
}
}
Works perfectly with sprites, but... if I make a TileMap and use " Multiple Materials" on the tile sprite collection, the material is animated but is over sized and I have no idea where is the problem.
What am I doing wrong?
Some idea or clue?
-
the material is animated but is over sized - what does that mean? Screenshots might help?
-
Ok, I will try to explain my best ( please, excuse my english)
I use a "filmstrip texture":
(http://i60.tinypic.com/2hp857q.png)
So step by step:- I am usign your Tile Map tutorial
- A new material is created, with my custom shader and with the filmstrip like the texture...
- ... and use " Multiple Materials" on the tile sprite collection ( first screenshot)
(http://i59.tinypic.com/23ua62w.gif)
If I use my shader in a quad, all works perfectly ( second screenshot):
(http://i57.tinypic.com/15zmwxc.gif)
But in the tilemap, the tile with the " multiple material" doesn't work ( is animated, but " over sized"?)
(http://i62.tinypic.com/qrj5e1.gif)
I'm playing with the tilling and offset values, but I haven't got to fix it.
-
The UVs are still referencing the original rectangle. The easiest (non intrusive) way to do this is to calculate uvs based on world position instead of using in.texcoord. Seeing that your sprites are rectangles it shouldn't be an issue.
-
I'm lost... :-\
I'm trying to fix it with _Object2World, but... I haven't been successful.
Could anyone give me some clue about the way to fix it?
-
Something like this in the vertex shader will do the job -
o.texcoord = mul(_Object2World, v.vertex).xy * _MainTex_ST.xy + _MainTex_ST.zw;
You can then use the texture tiling / offset values to adjust the tiling ratio to get it to fit to match pixels to world unit.
-
Great, now works :)
Thank you very much.
-
Sorry to resurrect this topic, but being a related question I think is the best place.
I'm using material overrides in the sprite collection for my tilemap.
The material is animated with this shader:
Shader "Custom/2DToolkit_AnimatedTexture"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
// Create the inspector values
_FrameWidth ("Frame Width", Float) = 0.0
_TotalFrames ("Total Frames", Float) = 0.0
_FPS ("FPS", Float) = 0.0
}
SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//Create the connection to the properties inside of the
//CG program
float _FrameWidth;
float _TotalFrames;
float _FPS;
float _Tick;
v2f vert (appdata_base v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
//o.texcoord = mul(_Object2World, v.vertex).xy * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag (v2f i) : COLOR
{
//ANIMATION
float2 spriteUV = i.texcoord;
_Tick = frac(_Time.y * _FPS);
spriteUV.x = spriteUV.x + ( floor( _Tick * _TotalFrames ) * _FrameWidth );
fixed4 col = tex2D(_MainTex, spriteUV);
return col;
}
ENDCG
}
}
}
Here is the test texture for the material:
(http://i61.tinypic.com/2hmkf81.jpg)
And here the shader inspector:
(http://i57.tinypic.com/zld9vc.png)
The performance is great and the animations works perfectly with all sprites except with the water tiles.
The tile is not drawn correctly and consequently the animation has an ugly result.
(http://i61.tinypic.com/30rpj49.png)
Where is the problem?
I've been playing with the sprite collection settings with no success and I'm lost.
Thank you.
-
That is a result of bilinear filtering onto the adjacent tile. There isn't much you can do about this except to add padding manually (and make your shader more complicated as a result). Or you could just use point filtering and be done with it.
-
Great, you are right :)
Padding between each tile-frame is the solution.
2dToolkit is an awesome tool.
One more time, thank you very much.