Fur: Albedo-gekoppelte Länge, Toggle-Gate, Soft-Edge, World-Gravity, Pipette & FP-Hide

- Fur-Map trägt nur noch R = Länge (linearer Datenkanal); Farbe kommt per-texel
  aus der Live-Albedo-RT (an _BaseMap des Shell-Shaders gebunden)
- Toggle_Fur als echtes Gate (IsChannelActive = fur), Default aus, furLength 0.5
- Weicher Alpha-Übergang (radial/tip/length coverage) statt Hard-Clip; Transparent-
  Pass mit Depth-Bias (Offset -1,-1) gegen Body-Durchflimmern
- Root dunkler / Tip heller aus gemalter Farbe abgeleitet (kein Fix-Tint)
- Gravity/Curl in World-Space nach Transform (unabhängig von Mesh-Rotation)
- Pipette aktiviert Fur-Toggle immer; liest R-Kanal als Länge
- First-Person blendet FurShellRenderer mit aus
- Netzwerk (FlagFur), Undo, Persistence (fur.png R=Länge) mitgezogen

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-07-03 23:40:58 +02:00
1 parent 7536e8ec8b
commit 1b783a39be
15 files changed
+254 -306

No files matched your search

@@ -1,5 +1,6 @@
using UnityEngine;
using Unity.Cinemachine;
using Chameleon.Components;
/// <summary>
/// First-person camera. Drives its OWN dedicated <see cref="CinemachineCamera"/>: each frame it snaps
@@ -24,6 +25,9 @@ public class FirstPersonController : MonoBehaviour
[Tooltip("Renderers hidden while first-person is active (so you don't see your own body). Empty = the player's SkinnedMeshRenderers, auto-resolved.")]
public Renderer[] hiddenRenderers;
[Tooltip("Fur renderers disabled while first-person is active (they draw via GPU instancing, not a Renderer, so they need their own toggle). Empty = the player's FurShellRenderers, auto-resolved.")]
public FurShellRenderer[] hiddenFurRenderers;
[Header("Look")]
[Tooltip("Horizontal look sensitivity (degrees of yaw per pixel).")]
public float horizontalSensitivity = 0.2f;
@@ -139,9 +143,15 @@ public class FirstPersonController : MonoBehaviour
void SetMeshHidden(bool hidden)
{
if (hiddenRenderers == null) return;
foreach (var r in hiddenRenderers)
if (r) r.enabled = !hidden;
if (hiddenRenderers != null)
foreach (var r in hiddenRenderers)
if (r) r.enabled = !hidden;
// The fur draws from RenderPipelineManager.beginCameraRendering, not through a Renderer, so hiding
// the SkinnedMeshRenderer above doesn't stop it - disabling the component unsubscribes that hook.
if (hiddenFurRenderers != null)
foreach (var f in hiddenFurRenderers)
if (f) f.enabled = !hidden;
}
/// <summary>
@@ -157,6 +167,7 @@ public class FirstPersonController : MonoBehaviour
Transform t = p.transform.Find("FirstPersonTarget");
if (t) cameraTarget = t;
hiddenRenderers = p.GetComponentsInChildren<SkinnedMeshRenderer>(true);
hiddenFurRenderers = p.GetComponentsInChildren<FurShellRenderer>(true);
_resolved = true;
}
@@ -180,5 +191,8 @@ public class FirstPersonController : MonoBehaviour
if (hiddenRenderers == null || hiddenRenderers.Length == 0)
hiddenRenderers = player.GetComponentsInChildren<SkinnedMeshRenderer>(true);
if (hiddenFurRenderers == null || hiddenFurRenderers.Length == 0)
hiddenFurRenderers = player.GetComponentsInChildren<FurShellRenderer>(true);
}
}