2026-05-22 13:58:46 +02:00

133 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering;
[RequireComponent(typeof(CapsuleCollider))]
public class LeavesHiding : MonoBehaviour
{
public Material invisibleMaterial;
Dictionary<MeshRenderer, (Material[], Material[])> matLists = new Dictionary<MeshRenderer, (Material[], Material[])>();
HashSet<MeshRenderer> singleMatLeavesMeshes = new HashSet<MeshRenderer>();
static RPGController player = null;
static new Camera camera = null;
static int ignoreRaycastLayer = -1;
private void Awake()
{
if (ignoreRaycastLayer == -1)
ignoreRaycastLayer = LayerMask.NameToLayer("Ignore Raycast");
}
void Start()
{
foreach (Collider collider in GetComponents<Collider>())
collider.isTrigger = true;
LODGroup lodGroup = GetComponentInChildren<LODGroup>();
foreach (MeshRenderer renderer in GetComponentsInChildren<MeshRenderer>(true))
{
MeshRenderer newRenderer = Instantiate(renderer.gameObject, renderer.transform.parent, true).GetComponent<MeshRenderer>();
newRenderer.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
renderer.shadowCastingMode = ShadowCastingMode.Off;
if (!lodGroup)
continue;
LOD[] lods = lodGroup.GetLODs();
for (int i = 0; i < lods.Length; i++)
{
if (lods[i].renderers.Any(r => r == renderer))
lods[i].renderers = lods[i].renderers.Append(newRenderer).ToArray();
}
lodGroup.SetLODs(lods);
}
foreach (MeshRenderer renderer in GetComponentsInChildren<MeshRenderer>(true))
{
Material[] rendererSharedMats = renderer.sharedMaterials;
Material[] leavelessMats = new Material[rendererSharedMats.Length];
if (renderer.shadowCastingMode == ShadowCastingMode.ShadowsOnly)
continue;
bool didReplace = false;
for (int i = 0; i < rendererSharedMats.Length; i++)
{
if (rendererSharedMats[i].name.Contains("leaves", StringComparison.InvariantCultureIgnoreCase))
{
leavelessMats[i] = invisibleMaterial;
didReplace = true;
}
else
leavelessMats[i] = rendererSharedMats[i];
}
if (!didReplace)
continue;
matLists.Add(renderer, (rendererSharedMats, leavelessMats));
}
}
void Update()
{
if (!player)
player = FindAnyObjectByType<RPGController>();
if (!camera)
camera = Camera.main;
if (!player || !camera)
return;
if (gameObject.layer != ignoreRaycastLayer)
gameObject.layer = ignoreRaycastLayer;
Vector3 playerPos = player.transform.position + Vector3.up;
Vector3 cameraPos = camera.transform.position;
Vector3 rayDir = (playerPos - cameraPos).normalized;
RaycastHit[] hits = Physics.RaycastAll(cameraPos, rayDir, float.PositiveInfinity, 1 << gameObject.layer, QueryTriggerInteraction.Collide);
for (int i = 0; i < hits.Length; i++)
{
if (hits[i].collider.gameObject == gameObject)
{
SetLeavesVisible(false);
return;
}
}
SetLeavesVisible(true);
}
/*
void OnTriggerEnter(Collider other)
{
if (other.GetComponent<RPGController>() || other.GetComponentInParent<RPGController>())
SetLeavesVisible(false);
}
void OnTriggerExit(Collider other)
{
if (other.GetComponent<RPGController>() || other.GetComponentInParent<RPGController>())
SetLeavesVisible(true);
}
*/
void SetLeavesVisible(bool visible)
{
foreach (MeshRenderer renderer in matLists.Keys)
renderer.sharedMaterials = visible ? matLists[renderer].Item1 : matLists[renderer].Item2;
}
}