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

Вместо сжатия головы все рендеры одержимого в 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> /// <summary>Камера - позади и выше головы зомби.</summary>
public const float CamBack = 2.6f; public const float CamBack = 2.6f;
/// <summary>Вид от первого лица (указание 13.10): клавиша ~/ё - как переключение вида у персонажа в игре /// <summary>Вид от первого лица (указание 13.10): клавиша ~/ё - как переключение вида у персонажа в игре
/// (QuickMenu, по умолчанию Backquote; и CameraChange геймпада), каждое вселение начинается от третьего лица. Камера - в голове, голова сжата /// (QuickMenu, по умолчанию Backquote; и CameraChange геймпада), каждое вселение начинается от третьего лица. Камера - в голове, тело - только тень
/// (HideHead), положение глаз сглажено (FpSmooth) - голова зомби на ходу мотается.</summary> /// (HideBody), положение глаз сглажено (FpSmooth) - голова зомби на ходу мотается.</summary>
public static bool FirstPerson; public static bool FirstPerson;
public const float FpForward = 0.12f, FpSmooth = 12f; public const float FpForward = 0.12f, FpSmooth = 12f;
static Vector3 _fpEye; static Vector3 _fpEye;
static Transform _hiddenHead; static readonly List<Renderer> _hiddenRenderers = new List<Renderer>();
static Vector3 _hiddenHeadScale; static readonly List<UnityEngine.Rendering.ShadowCastingMode> _hiddenModes = new List<UnityEngine.Rendering.ShadowCastingMode>();
static EntityAlive _hiddenBody;
public const float CamUp = 0.6f; public const float CamUp = 0.6f;
/// <summary>Как далеко зомби замечают одержимого: зрение зомби - 30 м (entityclasses.xml SightRange).</summary> /// <summary>Как далеко зомби замечают одержимого: зрение зомби - 30 м (entityclasses.xml SightRange).</summary>
public const float TauntRange = 30f; public const float TauntRange = 30f;
@@ -354,7 +355,7 @@ namespace NecromancerTome
} }
Active = false; Active = false;
FirstPerson = false; FirstPerson = false;
HideHead(null); HideBody(null);
RatLoot.CloseIfViewing(); RatLoot.CloseIfViewing();
WolfBag.CloseWindow(); WolfBag.CloseWindow();
RatPhase.Stop(GameManager.Instance?.World, Zombie, "выход из одержимости"); RatPhase.Stop(GameManager.Instance?.World, Zombie, "выход из одержимости");
@@ -579,7 +580,7 @@ namespace NecromancerTome
_fpEye = Vector3.zero; _fpEye = Vector3.zero;
if (!FirstPerson) if (!FirstPerson)
{ {
HideHead(null); HideBody(null);
} }
Debug.Log("[NecromancerTome] Possession: вид от " + (FirstPerson ? "первого" : "третьего") + " лица"); Debug.Log("[NecromancerTome] Possession: вид от " + (FirstPerson ? "первого" : "третьего") + " лица");
} }
@@ -2024,26 +2025,39 @@ namespace NecromancerTome
_flyZoomHeld = false; _flyZoomHeld = false;
} }
/// <summary>Голова одержимого сжата почти в точку, пока вид от первого лица, - иначе камера внутри черепа /// <summary>Тело одержимого в виде от первого лица - только тень (тест 13.10: изнутри видно тело, у паука на
/// (у зомби модель цельная, отдельных рук, как у персонажа, нет). Ставится каждый кадр после аниматора; /// бегу лапы и череп в кадре; сжатие одной головы не спасало). Видимость - дело своего экрана: другие игроки
/// null - вернуть прежний масштаб.</summary> /// рисуют этого зомби сами и видят его как обычно; так же игра прячет тело персонажа от первого лица.
static void HideHead(Transform _head) /// Рендеры собираются один раз на вход в вид; null - вернуть каждому прежний режим тени.
///
/// ПАМЯТЬ. Ссылки на рендеры держим только пока вид от первого лица (null чистит список).</summary>
static void HideBody(EntityAlive _z)
{ {
if (_hiddenHead != null && _hiddenHead != _head) if (_hiddenBody == _z)
{
_hiddenHead.localScale = _hiddenHeadScale;
_hiddenHead = null;
}
if (_head == null)
{ {
return; return;
} }
if (_hiddenHead == null) for (int i = 0; i < _hiddenRenderers.Count; i++)
{ {
_hiddenHead = _head; if (_hiddenRenderers[i] != null)
_hiddenHeadScale = _head.localScale; {
_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> /// <summary>Из постфикса vp_FPCamera.LateUpdate: камера позади и выше головы зомби, не сквозь стены.</summary>
@@ -2065,13 +2079,12 @@ namespace NecromancerTome
Quaternion rot = Quaternion.Euler(-_pitch, _yaw, 0f); Quaternion rot = Quaternion.Euler(-_pitch, _yaw, 0f);
if (FirstPerson) if (FirstPerson)
{ {
// Положение головы - уже после аниматора (мы в LateUpdate камеры), до сжатия: сжатие масштаба // Положение головы - уже после аниматора (мы в LateUpdate камеры).
// самой кости её положения не меняет.
Vector3 want = anchor + rot * Vector3.forward * FpForward; Vector3 want = anchor + rot * Vector3.forward * FpForward;
_fpEye = _fpEye == Vector3.zero || (want - _fpEye).sqrMagnitude > 4f _fpEye = _fpEye == Vector3.zero || (want - _fpEye).sqrMagnitude > 4f
? want ? want
: Vector3.Lerp(_fpEye, want, 1f - Mathf.Exp(-FpSmooth * Time.deltaTime)); : Vector3.Lerp(_fpEye, want, 1f - Mathf.Exp(-FpSmooth * Time.deltaTime));
HideHead(head); HideBody(z);
_camera.SetPositionAndRotation(_fpEye, rot); _camera.SetPositionAndRotation(_fpEye, rot);
return; return;
} }