Added map and fixed other bugs

This commit is contained in:
2026-07-03 14:36:04 +03:00
parent 94739757be
commit 3d423974eb
161 changed files with 35735 additions and 315 deletions
@@ -14,7 +14,14 @@ public class GhostPlayer : NetworkBehaviour
[SerializeField] private GameObject hitEffectPrefab;
[Header("Visuals")]
[SerializeField] private Color ghostColor = new Color(0.5f, 0.5f, 0.5f, 1f);
[Tooltip("Тусклый цвет СВОЕГО клона (клон локального игрока)")]
[SerializeField] private Color ownGhostColor = new Color(0f, 0f, 0.5f, 1f);
[Tooltip("Тусклый цвет ЧУЖОГО клона (клон соперника)")]
[SerializeField] private Color enemyGhostColor = new Color(0.5f, 0f, 0f, 1f);
// ClientId оригинального игрока. Синхронизируется на клиентов для окраски
// (recording живёт только на сервере, поэтому цвет по нему клиент не узнает).
private NetworkVariable<ulong> ownerId = new NetworkVariable<ulong>(ulong.MaxValue);
private GhostRecording recording;
private int shotIdx;
@@ -22,15 +29,34 @@ public class GhostPlayer : NetworkBehaviour
private Collider[] ownColliders;
private PlayerHealth health;
private PlayerShield shield;
/// <summary> Кому засчитывать вход в яму / фраги — ClientId оригинального игрока. </summary>
public ulong OriginalOwnerId => recording != null ? recording.ownerClientId : ulong.MaxValue;
public ulong OriginalOwnerId => ownerId.Value;
public override void OnNetworkSpawn()
{
// Красим клона на всех клиентах, чтобы отличался от живых игроков
ownerId.OnValueChanged += OnOwnerChanged;
ApplyColor();
}
public override void OnNetworkDespawn()
{
ownerId.OnValueChanged -= OnOwnerChanged;
}
private void OnOwnerChanged(ulong _previous, ulong _current) => ApplyColor();
// Свой клон — тусклый синий, чужой — тусклый красный (как живые игроки, но тускло)
private void ApplyColor()
{
bool _isMine = NetworkManager.Singleton != null
&& ownerId.Value == NetworkManager.Singleton.LocalClientId;
Color _color = _isMine ? ownGhostColor : enemyGhostColor;
foreach (MeshRenderer _renderer in GetComponentsInChildren<MeshRenderer>())
_renderer.material.color = ghostColor;
_renderer.material.color = _color;
}
/// <summary> Вызывается на сервере сразу после NetworkObject.Spawn(). </summary>
@@ -40,9 +66,12 @@ public class GhostPlayer : NetworkBehaviour
shotIdx = 0;
finished = false;
ownerId.Value = _recording.ownerClientId;
ownColliders = GetComponentsInChildren<Collider>();
health = GetComponent<PlayerHealth>();
shield = GetComponent<PlayerShield>();
// Init(true): мы на сервере. Без этого TakeDamage у клона молча не работает
health.Init(true);
}
@@ -66,6 +95,9 @@ public class GhostPlayer : NetworkBehaviour
transform.position = recording.positions[_tick];
transform.rotation = recording.rotations[_tick];
if (shield != null && _tick < recording.shieldStates.Count)
shield.SetShieldState(recording.shieldStates[_tick]);
while (shotIdx < recording.shots.Count && recording.shots[shotIdx].tick <= _tick)
{
ReplayShot(recording.shots[shotIdx]);
@@ -80,7 +112,8 @@ public class GhostPlayer : NetworkBehaviour
{
if (System.Array.Exists(ownColliders, c => c == _hit.collider)) return;
if (_hit.collider.TryGetComponent(out PlayerHealth _targetHealth))
PlayerHealth _targetHealth = _hit.collider.GetComponentInParent<PlayerHealth>();
if (_targetHealth != null)
_targetHealth.TakeDamage((int)damageAmount);
SpawnHitEffectClientRpc(_hit.point);