Одержимость от первого лица: тело зомби для своего экрана - только тень

Вместо сжатия головы все рендеры одержимого в ShadowsOnly (у паука на бегу в кадре были лапы и череп); другие игроки видят тело как обычно.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-13 15:03:36 +03:00
co-authored by Claude Opus 5.5
parent 4b81f65cab
commit 25019f5791
+36 -23
View File
@@ -144,13 +144,14 @@ namespace NecromancerTome
/// <summary>Камера - позади и выше головы зомби.</summary>
public const float CamBack = 2.6f;
/// <summary>Вид от первого лица (указание 13.10): клавиша ~/ё - как переключение вида у персонажа в игре
/// (QuickMenu, по умолчанию Backquote; и CameraChange геймпада), каждое вселение начинается от третьего лица. Камера - в голове, голова сжата
/// (HideHead), положение глаз сглажено (FpSmooth) - голова зомби на ходу мотается.</summary>
/// (QuickMenu, по умолчанию Backquote; и CameraChange геймпада), каждое вселение начинается от третьего лица. Камера - в голове, тело - только тень
/// (HideBody), положение глаз сглажено (FpSmooth) - голова зомби на ходу мотается.</summary>
public static bool FirstPerson;
public const float FpForward = 0.12f, FpSmooth = 12f;
static Vector3 _fpEye;
static Transform _hiddenHead;
static Vector3 _hiddenHeadScale;
static readonly List<Renderer> _hiddenRenderers = new List<Renderer>();
static readonly List<UnityEngine.Rendering.ShadowCastingMode> _hiddenModes = new List<UnityEngine.Rendering.ShadowCastingMode>();
static EntityAlive _hiddenBody;
public const float CamUp = 0.6f;
/// <summary>Как далеко зомби замечают одержимого: зрение зомби - 30 м (entityclasses.xml SightRange).</summary>
public const float TauntRange = 30f;
@@ -354,7 +355,7 @@ namespace NecromancerTome
}
Active = false;
FirstPerson = false;
HideHead(null);
HideBody(null);
RatLoot.CloseIfViewing();
WolfBag.CloseWindow();
RatPhase.Stop(GameManager.Instance?.World, Zombie, "выход из одержимости");
@@ -579,7 +580,7 @@ namespace NecromancerTome
_fpEye = Vector3.zero;
if (!FirstPerson)
{
HideHead(null);
HideBody(null);
}
Debug.Log("[NecromancerTome] Possession: вид от " + (FirstPerson ? "первого" : "третьего") + " лица");
}
@@ -2024,26 +2025,39 @@ namespace NecromancerTome
_flyZoomHeld = false;
}
/// <summary>Голова одержимого сжата почти в точку, пока вид от первого лица, - иначе камера внутри черепа
/// (у зомби модель цельная, отдельных рук, как у персонажа, нет). Ставится каждый кадр после аниматора;
/// null - вернуть прежний масштаб.</summary>
static void HideHead(Transform _head)
/// <summary>Тело одержимого в виде от первого лица - только тень (тест 13.10: изнутри видно тело, у паука на
/// бегу лапы и череп в кадре; сжатие одной головы не спасало). Видимость - дело своего экрана: другие игроки
/// рисуют этого зомби сами и видят его как обычно; так же игра прячет тело персонажа от первого лица.
/// Рендеры собираются один раз на вход в вид; null - вернуть каждому прежний режим тени.
///
/// ПАМЯТЬ. Ссылки на рендеры держим только пока вид от первого лица (null чистит список).</summary>
static void HideBody(EntityAlive _z)
{
if (_hiddenHead != null && _hiddenHead != _head)
{
_hiddenHead.localScale = _hiddenHeadScale;
_hiddenHead = null;
}
if (_head == null)
if (_hiddenBody == _z)
{
return;
}
if (_hiddenHead == null)
for (int i = 0; i < _hiddenRenderers.Count; i++)
{
_hiddenHead = _head;
_hiddenHeadScale = _head.localScale;
if (_hiddenRenderers[i] != null)
{
_hiddenRenderers[i].shadowCastingMode = _hiddenModes[i];
}
}
_head.localScale = Vector3.one * 0.001f;
_hiddenRenderers.Clear();
_hiddenModes.Clear();
_hiddenBody = _z;
if (_z == null || _z.emodel == null)
{
return;
}
_z.emodel.GetComponentsInChildren(true, _hiddenRenderers);
for (int i = 0; i < _hiddenRenderers.Count; i++)
{
_hiddenModes.Add(_hiddenRenderers[i].shadowCastingMode);
_hiddenRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
}
Debug.Log("[NecromancerTome] Possession: тело " + _z.EntityName + " - только тень, рендеров " + _hiddenRenderers.Count);
}
/// <summary>Из постфикса vp_FPCamera.LateUpdate: камера позади и выше головы зомби, не сквозь стены.</summary>
@@ -2065,13 +2079,12 @@ namespace NecromancerTome
Quaternion rot = Quaternion.Euler(-_pitch, _yaw, 0f);
if (FirstPerson)
{
// Положение головы - уже после аниматора (мы в LateUpdate камеры), до сжатия: сжатие масштаба
// самой кости её положения не меняет.
// Положение головы - уже после аниматора (мы в LateUpdate камеры).
Vector3 want = anchor + rot * Vector3.forward * FpForward;
_fpEye = _fpEye == Vector3.zero || (want - _fpEye).sqrMagnitude > 4f
? want
: Vector3.Lerp(_fpEye, want, 1f - Mathf.Exp(-FpSmooth * Time.deltaTime));
HideHead(head);
HideBody(z);
_camera.SetPositionAndRotation(_fpEye, rot);
return;
}