Objects changing color / rendering when entering area

I have been searching for hours and can’t find the right term for what I want to achieve - it basically looks like in the game “140” when the player object gets touched by the circle and changes color but only where it intersects:

In this screen shot the player (being the square) enters the yellow area and changes color but only the part that is inside the area, that is the effect I want and I have no Idea how to achieve that.

The game is currently a 3d project looking top down with orthographic projection (I know, but it is too late in the project to switch to 2d). Here is a video from the gameplay as it currently is (without colored areas)

The right search term makes all the difference. Thanks to @broxxar I found this blog post by @prime31 and to not just copy the work of others I changed the “Occluded” shader a tiny bit so the replacement color can be set via script on the game object with the sprite renderer.

Here are the two shaders as explained in the blog post plus my small adjustment and script to set the replacement color:

Shader "Sprites/Occluder"
{
  Properties
  {
     [PerRendererData] _MainTex ( "Sprite Texture", 2D ) = "white" {}
      _Color ( "Tint", Color ) = ( 1, 1, 1, 1 )
     [MaterialToggle] PixelSnap ( "Pixel snap", Float ) = 0
      _AlphaCutoff ( "Alpha Cutoff", Range( 0.01, 1.0 ) ) = 0.1
  }


  SubShader
  {
      Tags
      {
          "Queue" = "Transparent"
          "IgnoreProjector" = "True"
          "RenderType" = "TransparentCutout"
          "PreviewType" = "Plane"
          "CanUseSpriteAtlas" = "True"
      }

      Cull Off
      Lighting Off
      ZWrite Off
      Blend One OneMinusSrcAlpha

      Pass
      {
          Stencil
          {
              Ref 4
              Comp Always
              Pass Replace
          }

      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;
          };

          fixed4 _Color;
          fixed _AlphaCutoff;

          v2f vert( appdata_t IN )
          {
              v2f OUT;
              OUT.vertex = mul( UNITY_MATRIX_MVP, IN.vertex );
              OUT.texcoord = IN.texcoord;
              OUT.color = IN.color * _Color;
              #ifdef PIXELSNAP_ON
              OUT.vertex = UnityPixelSnap( OUT.vertex );
              #endif

              return OUT;
          }

          sampler2D _MainTex;
          sampler2D _AlphaTex;


          fixed4 frag( v2f IN ) : SV_Target
          {
              fixed4 c = tex2D( _MainTex, IN.texcoord ) * IN.color;
              c.rgb *= c.a;

              // here we discard pixels below our _AlphaCutoff so the stencil buffer only gets written to
              // where there are actual pixels returned. If the occluders are all tight meshes (such as solid rectangles)
              // this is not necessary and a non-transparent shader would be a better fit.
              clip( c.a - _AlphaCutoff );

              return c;
          }
      ENDCG
      }
  }
}

Shader for the occluded sprite:

Shader "Sprites/Occluded"
{
  Properties
  {
     [PerRendererData] _MainTex ( "Sprite Texture", 2D ) = "white" {}
      _Color ( "Tint", Color ) = ( 1, 1, 1, 1 )
     [MaterialToggle] PixelSnap ( "Pixel snap", Float ) = 0
// Making the occluded Color configurable by script
     [PerRendererData] _OccludedColor ( "Occluded Tint", Color ) = ( 0, 0, 0, 0.5 )
  }


CGINCLUDE

// shared structs and vert program used in both the vert and frag programs
struct appdata_t
{
  float4 vertex   : POSITION;
  float4 color    : COLOR;
  float2 texcoord : TEXCOORD0;
};

struct v2f
{
  float4 vertex   : SV_POSITION;
  fixed4 color    : COLOR;
  half2 texcoord  : TEXCOORD0;
};


fixed4 _Color;
sampler2D _MainTex;


v2f vert( appdata_t IN )
{
  v2f OUT;
  OUT.vertex = UnityObjectToClipPos( IN.vertex );
  OUT.texcoord = IN.texcoord;
  OUT.color = IN.color * _Color;
  #ifdef PIXELSNAP_ON
  OUT.vertex = UnityPixelSnap( OUT.vertex );
  #endif

  return OUT;
}

ENDCG



  SubShader
  {
      Tags
      {
          "Queue" = "Transparent"
          "IgnoreProjector" = "True"
          "RenderType" = "Transparent"
          "PreviewType" = "Plane"
          "CanUseSpriteAtlas" = "True"
      }

      Cull Off
      Lighting Off
      ZWrite Off
      Blend One OneMinusSrcAlpha

      Pass
      {
          Stencil
          {
              Ref 4
              Comp NotEqual
          }


      CGPROGRAM
          #pragma vertex vert
          #pragma fragment frag
          #pragma multi_compile _ PIXELSNAP_ON
          #include "UnityCG.cginc"


          fixed4 frag( v2f IN ) : SV_Target
          {
              fixed4 c = tex2D( _MainTex, IN.texcoord ) * IN.color;
              c.rgb *= c.a;
              return c;
          }
      ENDCG
      }


      // occluded pixel pass. Anything rendered here is behind an occluder
      Pass
      {
          Stencil
          {
              Ref 4
              Comp Equal
          }

      CGPROGRAM
          #pragma vertex vert
          #pragma fragment frag
          #pragma multi_compile _ PIXELSNAP_ON
          #include "UnityCG.cginc"

          fixed4 _OccludedColor;


          fixed4 frag( v2f IN ) : SV_Target
          {
              fixed4 c = tex2D( _MainTex, IN.texcoord );
              return _OccludedColor * c.a;
          }
      ENDCG
      }
  }
}

And a script that lets you set the replacement color on a per-object-basis with the same shader - inspired by this blog post by @Thomas-Mountainborn:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class ReplacementColor : MonoBehaviour
{
    public Color ReplColor;

    private Renderer _renderer;
    private MaterialPropertyBlock _propBlock;

    void OnGUI() 
    {
        #if UNITY_EDITOR
        _propBlock = new MaterialPropertyBlock();
        _renderer = GetComponent<Renderer>();
        setReplacementColor(ReplColor);
        #endif
    }

    void Awake()
    {
        _propBlock = new MaterialPropertyBlock();
        _renderer = GetComponent<Renderer>();
        setReplacementColor(ReplColor);
    }

    private void setReplacementColor( Color newColor)
    {
        if (_propBlock != null ){
            // Get the current value of the material properties in the renderer.
            _renderer.GetPropertyBlock(_propBlock);
            // Assign our new value.
            _propBlock.SetColor("_OccludedColor", newColor );
            // Apply the edited values to the renderer.
            _renderer.SetPropertyBlock(_propBlock);
        }
    }
}

Hope this will help someone who is searching for this like I have.

Take a look at the ShaderLab: Stencil Buffer page on the docs. That should get you headed in the right direction. I imagine you’d want a two-pass shader, where the two passes have different Stencil ref values. Then have areas for which you want to “flip” the color, draw before the character, writing a specific stencil value. Then the two passes of the character, would pass/fail the stencil buffer only in the areas you want them to show.