Monday, August 26, 2019

Unity: How do I only show parts of objects that overlap [2D]


I'm working on a 2D Unity project where the player can only see objects in their field of view. I have successfully created a mesh that overlaps anything that would be in the player's field of view, but now I'm having trouble with only showing parts of objects that the mesh overlaps with.


Here is what I have so far (the gray area is the player's field of view which is a mesh:


Currently:


Here is the type of thing that I'm looking for:


Goal:


What can I do to get that desired effect? Shaders (I have no clue how to use shaders)? Colliders? Any ideas would be greatly appreciated. If there is any info you need that I didn't provide, comment and I add the necessary info. Thank you in advance!



Answer



First, create a simple mesh (such as a quad or a cube). Place it over top the actual game area, and stretch it so that it covers the entire camera view.


Next, create a new shader named "ObscurityShader", and paste in the following shader code:



Shader "Custom/ObscurityShader"
{
SubShader
{
Tags{"Queue" = "Transparent+1" "RenderType" = "Transparent"}

Pass
{
CGPROGRAM
#pragma vertex vert

#pragma fragment frag

struct appdata
{
float4 vertex : POSITION;
};

struct v2f
{
float4 pos : SV_POSITION;

};

v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}

half4 frag(v2f i) : SV_Target

{
return 0;
}
ENDCG
}
}
}

Everything inside "Pass" is just a bare-bones vertex/fragment shader. The most important part for us is the "Tags" at the top of the code.


Now create a new material and set it to use ObscurityShader. Select the mesh we made earlier and set it to use this material.



Next, create a second shader named "VisibilityShader", and paste in the following shader code:


Shader "Custom/VisibilityShader"
{
SubShader
{
Tags{"Queue" = "Transparent" "RenderType" = "Transparent"}
ColorMask 0

Pass
{

CGPROGRAM
#pragma vertex vert
#pragma fragment frag

struct appdata
{
float4 vertex : POSITION;
};

struct v2f

{
float4 pos : SV_POSITION;
};

v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}


half4 frag(v2f i) : SV_Target
{
return 0;
}
ENDCG
}
}
}


Note that this shader is near-identical to the first, with two small differences:



  1. The rendering queue is "Transparent" rather than "Transparent+1", ensuring VisibilityShader is rendered before ObscurityShader.

  2. We use ColorMask 0, which essentially sets an invisible pixel that the ObscurityShader doesn't overwrite.


Create a new material and set it to use VisibilityShader. Set your "visible area" mesh to use this material.


Finally, set your "visible area" mesh to sit above the obscuring mesh, and you should see a hole in the black void in the shape of your visibility mesh!


Final Result


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...