using System; using System.Collections.Generic; using UnityEngine; namespace Toria.Game { [RequireComponent(typeof(CapsuleCollider))] public class DitherFade : MonoBehaviour { public DitherFadeSettings settings; public List targetRenderers; public bool makeShadowClones = true; [NonSerialized] List fadeMaterials; static RPGController player = null; static new Camera camera = null; [NonSerialized] bool shouldHide = false; void Start() { fadeMaterials = new List(); foreach (Renderer renderer in targetRenderers) { if (makeShadowClones) MakeShadowClone(renderer); Material mat = Instantiate(renderer.sharedMaterial); renderer.sharedMaterial = mat; fadeMaterials.Add(mat); } } void MakeShadowClone(Renderer renderer) { if (!renderer.TryGetComponent(out MeshFilter filter)) return; GameObject shadowClone = new GameObject("Shadow clone"); shadowClone.transform.SetParent(renderer.transform); shadowClone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); shadowClone.transform.localScale = Vector3.one; MeshRenderer shadowRenderer = shadowClone.AddComponent(); MeshFilter shadowFilter = shadowClone.AddComponent(); shadowRenderer.sharedMaterial = renderer.sharedMaterial; shadowRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; shadowFilter.sharedMesh = filter.sharedMesh; foreach (Component comp in shadowClone.GetComponents()) { if (comp is not MeshRenderer && comp is not MeshFilter && comp is not Transform) Destroy(comp); } renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; } void Update() { if (!player) player = FindAnyObjectByType(); if (shouldHide) { Vector2 viewPortPoint = camera.WorldToViewportPoint(player.transform.position + Vector3.up * settings.verticalOffset); float hideRadius = settings.GetHideRadius(player.transform, camera.transform); foreach (Material mat in fadeMaterials) { mat.SetVector("_PlayerPosition", viewPortPoint); mat.SetFloat("_HideRadius", hideRadius); } } if (!camera) camera = Camera.main; if (!player || !camera) return; Vector3 playerPos = player.transform.position + Vector3.up; Vector3 cameraPos = camera.transform.position; Vector3 rayDir = (playerPos - cameraPos).normalized; //move back the origin point so the raycast doesn't start from within a tree collider RaycastHit[] hits = Physics.RaycastAll(cameraPos + rayDir * -100f, rayDir, float.PositiveInfinity, 1 << gameObject.layer, QueryTriggerInteraction.Collide); for (int i = 0; i < hits.Length; i++) { if (hits[i].collider.gameObject == gameObject) { SetCutoutEnabled(true); return; } } SetCutoutEnabled(false); } void SetCutoutEnabled(bool enabled) { if (shouldHide == enabled) return; shouldHide = enabled; foreach (Material mat in fadeMaterials) mat.SetFloat("_ShouldHide", enabled ? 1 : 0); } } }