0

Сервер обрабатывает каждого игрока, в случаи его движения, всем отправляет конечную точку направления и текущее направления с учетом скорости. Не как не получается синхронизировать движение. На клиенте частые подергивания, из-за того, что на сервере игрок отстает от клиента. И при дистанции больше чем в 2f телепортирует его на серверные координаты. Пробовал таймер ставить на 500 мл/с, но тогда уже клиент телепортирует его вперед, что на стороне клиента не успевает его двигать. А подбирать значение как-то костыльно я так думаю. Пожалуйста, киньте кто пример простейший, на стороне клиента и сервера как правильно интерполяцию можно сделать. Движок unity, протокол транспортировки tcp. Заранее спасибо.

namespace KOBServer.Models.Base
{
    public sealed class CharacterMovement
    {
        public CharacterMovement(NetCharacter character)
        {
            _character = character;
            IsMoving = false;
            _timer = new System.Timers.Timer(1000);
            _timer.Elapsed += MovedElapsed;
        }
    private readonly NetCharacter _character;

    public bool IsMoving { get; private set; }

    private float DestinationX = 0;
    private float DestinationY = 0;
    private float DestinationZ = 0;
    private float PositionX { get => _character.PositionX; set => _character.PositionX = value; }
    private float PositionY { get => _character.PositionY; set => _character.PositionY = value; }
    private float PositionZ { get => _character.PositionZ; set => _character.PositionZ = value; }

    private System.Timers.Timer _timer;

    [MethodImpl(MethodImplOptions.Synchronized)]
    private void PerformMove()
    {
        if (!IsMoving)
            return;

        float distance = (float)Math.Sqrt(Math.Pow(DestinationX - PositionX, 2) +
            Math.Pow(DestinationY - PositionY, 2) + Math.Pow(DestinationZ - PositionZ, 2));

        float vectorDirectionX = ((DestinationX - PositionX) / distance) * _character._characterStats.MoveSpeed;
        float vectorDirectionY = ((DestinationY - PositionY) / distance) * _character._characterStats.MoveSpeed;
        float vectorDirectionZ = ((DestinationZ - PositionZ) / distance) * _character._characterStats.MoveSpeed;

        if (distance < _character._characterTemplate.AttackDistance)
        {
            NotifyStopMove();
            return;
        }

        if (!_character.IsBot)
        {
            Console.WriteLine($"{new string('-', 100)}\n[server] debug: distance: {distance}");
            Console.WriteLine($"[server] message: added vector tick: x:{vectorDirectionX} y:{vectorDirectionY} z:{vectorDirectionZ}");
            Console.WriteLine($"{new string('-', 100)}");
        }

        PositionX += vectorDirectionX;
        PositionY += vectorDirectionY;
        PositionZ += vectorDirectionZ;
    }

    private async void MovedElapsed(object? sender, System.Timers.ElapsedEventArgs e)
    {
        PerformMove();

        await _character.SendPacketAsync(CharacterUpdatePosition.ToPacket(_character));
        await _character.BroadcastPacketAsync(BroadcastCharacterPosition.ToPacket(_character));
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void UpdatePosition(float x, float y, float z)
    {
        if (!IsMoving)
            _timer.Enabled = true;

        IsMoving = true;

        DestinationX = x;
        DestinationY = y;
        DestinationZ = z;
    }

    private void NotifyStopMove()
    {
        IsMoving = false;
        _timer.Enabled = false;
        _timer.Stop();
    }

    public void ClearMovement()
    {
        if (IsMoving)
            _timer.Stop();

        _timer.Elapsed -= MovedElapsed;
    }
}

}

Alexey
  • 58
  • 8
  • протокол транспортировки tcp - не делаются клиентские реалтайм игры на TCP уже давно из-за HoL задержек, такие игры делаются на UDP. TCP подойдет для игр типа шахмат разве что. Кстати, раз уж вы умеете await, то зачем Timer? https://ru.stackoverflow.com/a/1257322/373567 А по поводу клиентского предсказания, просто физика должна быть реализована на сервере одинаково как на клиенте, плюс учитывать во всей математике jitter - лаг между клиентом и сервером (половина пинга), иначе точного предсказания не получится. То есть это не просто интерполяция, а полное повторение вычислений. – aepot Jan 29 '23 at 19:22
  • Кстати, async void зло. По куче причин. Судя по тому что не обрабатываете в нем исключения, вы не в курсе, что это зло. Советую поизучать, материалов на эту тему много. – aepot Jan 29 '23 at 19:33
  • Не какая физика не учитывается на клиенте. vector3.movetowards использую для движени и расчет дистанции между реальными координатами позиции сервера и клиентскими. Пример синхронизации бы... – Alexey Jan 29 '23 at 20:06

0 Answers0