A lot of people have been super helpful during my time in these courses, so thought I’d give something back. I wanted to only fade the area around the player when I was walking underneath it, rather than the entire canopy so created a script.
Simply add it to your Canopy game object and it should work.
This is the effect:
using UnityEngine;
using UnityEngine.Tilemaps;
using System.Collections.Generic;
using System.Linq;
public class TileFader : MonoBehaviour
{
private Tilemap _tilemap;
private Grid _tileGrid;
private readonly Dictionary<Vector3Int, float> _fadedTiles = new();
private readonly List<PlayerController> _collidingPlayers = new();
[SerializeField] private float fadeRange = 2f;
[SerializeField] private float maxOpacity = 0.9f;
private void Awake()
{
_tilemap = GetComponent<Tilemap>();
_tileGrid = _tilemap.layoutGrid;
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.TryGetComponent<PlayerController>(out var playerController))
{
_collidingPlayers.Add(playerController);
}
}
private void Update()
{
if (_collidingPlayers.Any())
{
FadeTilesAroundPlayer();
}
}
private void FadeTilesAroundPlayer()
{
foreach (var player in _collidingPlayers)
{
var playerPosition = player.transform.position;
var bounds = _tilemap.cellBounds;
// Remove tiles that are out of bounds
foreach (var tileToRemove in _fadedTiles
.Where(x => !bounds.Contains(x.Key))
.Select(x => x.Key)
.ToList())
{
_fadedTiles.Remove(tileToRemove);
}
var nearbyTiles = GetNearbyTiles(playerPosition, fadeRange).ToList();
if (!nearbyTiles.Any())
{
// Remove from colliding players here rather than OnTriggerExit2D as that
// way leaves some alpha faded tiles where you exited
_collidingPlayers.Remove(player);
return;
}
foreach (var cellPos in nearbyTiles)
{
var distance = Vector3.Distance(playerPosition, _tileGrid.GetCellCenterWorld(cellPos));
if (distance == 0f)
{
var alpha = maxOpacity;
var fadedColor = new Color(1f, 1f, 1f, alpha);
_tilemap.SetColor(cellPos, fadedColor);
_fadedTiles[cellPos] = alpha;
}
else
{
var alpha = Mathf.Lerp(maxOpacity, 1f, distance / fadeRange);
SetCellAlpha(cellPos, alpha);
}
}
}
}
private void SetCellAlpha(Vector3Int cellPos, float alpha)
{
var cellColor = _tilemap.GetColor(cellPos);
if (Math.Abs(cellColor.a - alpha) < 0.001) return;
var fadedColor = new Color(cellColor.r, cellColor.g, cellColor.b, alpha);
_tilemap.SetColor(cellPos, fadedColor);
_fadedTiles[cellPos] = alpha;
}
private IEnumerable<Vector3Int> GetNearbyTiles(Vector3 playerPosition, float radius)
{
var playerCellPos = _tileGrid.WorldToCell(playerPosition);
for (var x = playerCellPos.x - Mathf.FloorToInt(radius); x <= playerCellPos.x + Mathf.FloorToInt(radius); x++)
{
for (var y = playerCellPos.y - Mathf.FloorToInt(radius);
y <= playerCellPos.y + Mathf.FloorToInt(radius);
y++)
{
var cellPos = new Vector3Int(x, y, playerCellPos.z);
yield return cellPos;
}
}
}
}