Как правильно разработать "Интерполяцию" движения в Unity
Сервер обрабатывает каждого игрока, в случаи его движения, всем отправляет конечную точку направления и текущее направления с учетом скорости. Не как не получается синхронизировать движение. На клиенте частые подергивания, из-за того, что на сервере игрок отстает от клиента. И при дистанции больше чем в 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;
}
}
}
Источник: Stack Overflow на русском