I've been trying to figure out a way to do some kind of masking or cropping of sprites in Unity 4.3. The intent is to have a sprite move up into another sprite and appear to be disappearing into it. I was hoping that with some kind of mask or cropping I could just move the sprite up and have it disappear when it moves above the other sprite. This gif should illustrate what I mean: Is there any way to make the paper above the rolled up part of the scroll disappear? There will be a background eventually so having a black rectangle over the top won't work. I thought there would be some kind of sprite mask or ability to crop the sprite, but I haven't been able to find anything. I've seen some stuff about shaders but I have not used shaders before and I was wondering if there was a better solution. Any help you could offer would be much appreciated. Thanks.
I'm surprised not to be able to find an easy way, either. 2 options come to mind: 1) Use a shader on an invisible block that simply hides everything inside the block. Make sure nothing else enters that block by having it on a different Z layer. (Might not work with 2D stuff, never tried it.) I've found this shader by searching for it, but don't remember where it is right now. 2) Use multiple pieces to create that long paper piece. As they are moved behind the scroll at the top, hide them. (Or show them, for rolling the paper out.) Obviously, the pieces have to be as small or smaller than the scroll at the top.
Thanks for your suggestions wccrawford. From what I've seen of the shader stuff it looks like it's tailored for the 3D, which makes sense. It looks like a whole new language and seems very arcane and bewildering. Making multiple pieces is a good idea, but it seems like it shouldn't be necessary. Fortunately I found a workable solution in having multiple cameras. I'll only have these at the top and bottom of the screen, with a bit of space above and below them respectively. So I was able to set up a second camera for the GUI which has a smaller viewport rect than the main camera, so the top and bottom are cut off, like letterboxing, with the cutoff right at the edge of the rolled up part of the scrolls. It's a weird way to achieve the desired result, but it works. I hope they will implement some sprite cropping or masking functionality at some point though. It would be very useful.
Can you please explain on how to do #1? I've been searching for hours now for a way to crop sprites. If this is the only solution, I'll take it.. but I have no idea how to make such "invisible blocks" that can hide its contents. Please help!
http://forum.unity3d.com/threads/215465-More-than-backface-culling See my comment there for the solution I found for him. There are others, too, but this is the simplest one that will do the job, I believe. (I haven't used it.)
Thanks wccrawford. I'll be sure to check those out. Btw, I've found a way to crop.. but offset is a bit weird due to pivot. You basically need to create a new Sprite object from the old one's textures and edit the rect. It's extra messy when dealing with a muti-image texture. Sprite cropped = new Sprite(); cropped = Sprite.Create(oldSprite.texture, oldSprite.rect ,new Vector2(0.5f,0.5f),100.0f); In the sample code above you basically replace the "oldSprite.rect" with the cropped rectangle. Kinna works.. I stopped fully developing it out since I came across other workarounds. Just wanted to post this here for anyone still investigating.
Sorry for kicking open this old thread, but I just ran into exactly the same need, and didn't find a good ready-to-go solution. But, based on comments here and elsewhere, I took the Sprites/Default shader and modified it slightly to only render within a rectangular area of the screen. It seems to work great in my testing so far. Here it is, in case anybody else finds it useful... (Just save this to a file called Sprites-Cropped.shader, create a material out of it, and set the properties on that material to reflect the area of the screen where it should draw.) Code (ShaderLab): Shader "Custom/Sprites/Cropped" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 _MinX ("Min X", Float) = 0 _MaxX ("Max X", Float) = 1 _MinY ("Min Y", Float) = 0 _MaxY ("Max Y", Float) = 1 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile _ PIXELSNAP_ON #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; half2 texcoord : TEXCOORD0; float2 screenPos: TEXCOORD2; }; fixed4 _Color; float _MinX; float _MaxX; float _MinY; float _MaxY; v2f vert(appdata_t IN) { v2f OUT; OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex); OUT.texcoord = IN.texcoord; OUT.color = IN.color * _Color; OUT.screenPos = (float2)ComputeScreenPos(OUT.vertex); #ifdef PIXELSNAP_ON OUT.vertex = UnityPixelSnap (OUT.vertex); #endif return OUT; } sampler2D _MainTex; fixed4 frag(v2f IN) : SV_Target { fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color; c.a *= (IN.screenPos.x >= _MinX); c.a *= (IN.screenPos.x <= _MaxX); c.a *= (IN.screenPos.y >= _MinY); c.a *= (IN.screenPos.y <= _MaxY); c.rgb *= c.a; return c; } ENDCG } } }
Not sure what's gone wrong (I have zero understanding of shaders), but this isn't working for me. I copy-pasted the code, created the material and assigned it to a sprite... altering the min and max values shows me the required segment of my texture in the Unity scene editor, but when I run, it looks like moving the camera position around messes this up! Any way this could be modified so that the cropping is constant, no matter what the camera's position?
Hmm, I don't know... I haven't observed any problem like that. The ComputeScreenPos position is supposed to calculate the actual screen pos, for the camera in use. Maybe it has something to do with the camera settings? I'm at a bit of a loss here.
Is there any reason for not upgrading to latest version of Unity? The new Unity UI has masking support. Take a look at this https://unity3d.com/learn/tutorials/modules/beginner/ui/ui-mask
That's a good point — though UI stuff and sprite stuff often have an uncomfortable relationship (completely different coordinate systems, awkward layering, etc.). But yeah, for something like the OP's need, using a canvas would probably be an easier solution.
On a side note, we do have some preview stuff on sprite masking Its enabled for testing and feedback on a special preview build available here (requires a pro license) https://bitbucket.org/Unity-Technologies/2ddemos/wiki/Home