How to have a point light with no falloff in Unity 3D?

Does anyone know of a good strategy to make point lights with no falloff, eg. anything in the radius of the light will be 100% illumination while anything outside the radius will be 0% illumination.

I want to use this as a sort of 3D line of sight drawing. The line of sight is a big sphere originating from the character’s head that I thought would be a clever idea to have that represented as a point light, however with the falloff it doesn’t correctly show where the edge of the line of site is.

I’ve tried a few solutions, such as a custom falloff package (doesn’t seem to have the options I want) and a few shaders, but I am terrible at shaders so it’s difficult for me to debug. I’ll post the shader here in case somebody can tell me if I’m being dumb, otherwise if someone can point me to a different solution that would be great. Thanks!

Here’s a shader I tried, but it just turns everything invisible and it’s not immediately obvious to me why:

Shader "Custom/No Falloff v2"
{
	Properties
	{
		_Color("Color", Color) = (1,1,1,1)
		_MainTex("Texture", 2D) = "white" {}
	}
		SubShader
	{
		Tags{ "Queue" = "Transparent" }

		Pass
	{
		Blend SrcAlpha OneMinusSrcAlpha

		Tags{ "LightMode" = "ForwardAdd" }
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"
		#include "Lighting.cginc"

		// compile shader into multiple variants, with and without shadows
		#pragma multi_compile_fwdadd_fullshadows
		// shadow helper functions and macros
		#include "AutoLight.cginc"

		sampler2D _MainTex;
	float4 _MainTex_ST;

	fixed4 _Color;

	struct v2f
	{
		float2 uv : TEXCOORD0;
		SHADOW_COORDS(1) // put shadows data into TEXCOORD1
			float4 pos : SV_POSITION;
	};

	v2f vert(appdata_base v)
	{
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
		TRANSFER_SHADOW(o)
			return o;
	}

	fixed4 frag(v2f i) : SV_Target
	{
		fixed4 col = tex2D(_MainTex, i.uv) * _Color;

	// compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed)
	fixed shadow = SHADOW_ATTENUATION(i);

	if (shadow < 0.5)
	{
		return fixed4(0.0156862745, 0, 0.23529411764,1.0); //or any other color for shadow
	}

	return col;
	}
		ENDCG
	}

		// shadow casting support
		UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
	}
}

This’ll do it. The key part is in the custom lighting function,

#ifdef POINT
     atten = step(_PointThreshold, atten);
#endif

step returns either 0 or 1. if the point light is stronger than the threshold, it’ll become full strength. If less, it’ll become 0. Other lights are unaffected, so you can still have normal shading from a directional light.

Shader "Xibanya/HardPointLight"
{
	Properties
	{
		_Color("Color", Color) = (1,1,1,1)
		_MainTex("Albedo (RGB)", 2D) = "white" {}
		_BumpMap("Normal", 2D) = "bump" {}
		_BumpScale("Normal Strength", float) = 1
		_Threshold("Shadow Threshold", Range(0,2)) = 1
		_ShadowSoftness("Shadow Smoothness", Range(0.5, 1)) = 0.6
		_ShadowColor("Shadow Color", Color) = (0,0,0,1)
		_PointThreshold("Point Threshold", Range(0, 1)) = 0.5
	}
		SubShader
		{
			Tags { "RenderType" = "Opaque" }
			LOD 200

			CGPROGRAM
			#pragma surface surf Toon

			half		_Threshold;
			half		_ShadowSoftness;
			half3		_ShadowColor;

			sampler2D	_MainTex;
			sampler2D	_BumpMap;

			struct Input
			{
				float2 uv_MainTex;
			};

			half4		_Color;
			float		_BumpScale;
			half		_PointThreshold;

            inline half4 LightingToon(SurfaceOutput s, half3 lightDir, half atten)
            {
            #ifndef USING_DIRECTIONAL_LIGHT
                lightDir = normalize(lightDir);
            #endif
			#ifdef POINT
				atten = step(_PointThreshold, atten);
			#endif
				half shadowDot = pow(dot(s.Normal, lightDir) * 0.5 + 0.5, _Threshold);
				float threshold = smoothstep(0.5, _ShadowSoftness, shadowDot);
                half3 diffuseTerm = threshold * atten;
                half3 diffuse = lerp(_ShadowColor, _LightColor0.rgb, diffuseTerm);
                return half4(s.Albedo * diffuse, 1);
            }

			void surf(Input IN, inout SurfaceOutput o)
			{
				o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color;
				o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
			}
			ENDCG
		}
		FallBack "Diffuse"
}

here’s a screenshot of this shader in action