Merge pull request #2146 from aws-lumberyard-dev/mp_lerp_jitter

Fix inconsistent client lerp and account for blend factor on server
This commit is contained in:
puvvadar
2021-08-02 10:32:27 -07:00
committed by GitHub
16 changed files with 121 additions and 26 deletions
@@ -155,9 +155,12 @@ namespace Multiplayer
// Discard move input events, client may be speed hacking
if (m_clientBankedTime < sv_MaxBankTimeWindowSec)
{
// Client blends from previous frame to target so here we subtract blend factor to get to that state
const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.f);
const AZ::TimeMs blendMs = AZ::TimeMs(static_cast<float>(static_cast<AZ::TimeMs>(cl_InputRateMs)) * (1.f - blendFactor));
m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary
{
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId());
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId());
GetNetBindComponent()->ProcessInput(input, static_cast<float>(clientInputRateSec));
}
@@ -311,7 +314,7 @@ namespace Multiplayer
++ModifyLastInputId();
input.SetClientInputId(GetLastInputId());
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId());
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId());
GetNetBindComponent()->ProcessInput(input, clientInputRateSec);
AZLOG
@@ -391,7 +394,7 @@ namespace Multiplayer
{
// Reprocess the input for this frame
NetworkInput& input = m_inputHistory[replayIndex];
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId());
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId());
GetNetBindComponent()->ProcessInput(input, clientInputRateSec);
AZLOG
@@ -499,6 +502,7 @@ namespace Multiplayer
input.SetClientInputId(m_clientInputId);
input.SetHostFrameId(networkTime->GetHostFrameId());
input.SetHostTimeMs(multiplayer->GetCurrentHostTimeMs());
input.SetHostBlendFactor(multiplayer->GetCurrentBlendFactor());
// Allow components to form the input for this frame
GetNetBindComponent()->CreateInput(input, inputRate);
@@ -573,7 +577,7 @@ namespace Multiplayer
NetworkInput& input = m_lastInputReceived[0];
{
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), AzNetworking::InvalidConnectionId);
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, AzNetworking::InvalidConnectionId);
GetNetBindComponent()->ProcessInput(input, inputRate);
}
@@ -61,18 +61,21 @@ namespace Multiplayer
{
m_previousTransform.SetRotation(m_targetTransform.GetRotation());
m_targetTransform.SetRotation(rotation);
UpdateTargetHostFrameId();
}
void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation)
{
m_previousTransform.SetTranslation(m_targetTransform.GetTranslation());
m_targetTransform.SetTranslation(translation);
UpdateTargetHostFrameId();
}
void NetworkTransformComponent::OnScaleChangedEvent(float scale)
{
m_previousTransform.SetUniformScale(m_targetTransform.GetUniformScale());
m_targetTransform.SetUniformScale(scale);
UpdateTargetHostFrameId();
}
void NetworkTransformComponent::OnResetCountChangedEvent()
@@ -83,14 +86,31 @@ namespace Multiplayer
m_previousTransform = m_targetTransform;
}
void NetworkTransformComponent::UpdateTargetHostFrameId()
{
HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId();
if (currentHostFrameId > m_targetHostFrameId)
{
m_targetHostFrameId = currentHostFrameId;
}
}
void NetworkTransformComponent::OnPreRender([[maybe_unused]] float deltaTime, float blendFactor)
{
if (!HasController())
{
AZ::Transform blendTransform;
blendTransform.SetRotation(m_previousTransform.GetRotation().Slerp(m_targetTransform.GetRotation(), blendFactor));
blendTransform.SetTranslation(m_previousTransform.GetTranslation().Lerp(m_targetTransform.GetTranslation(), blendFactor));
blendTransform.SetUniformScale(AZ::Lerp(m_previousTransform.GetUniformScale(), m_targetTransform.GetUniformScale(), blendFactor));
if (Multiplayer::GetNetworkTime() && Multiplayer::GetNetworkTime()->GetHostFrameId() > m_targetHostFrameId)
{
m_previousTransform = m_targetTransform;
blendTransform = m_targetTransform;
}
else
{
blendTransform.SetRotation(m_previousTransform.GetRotation().Slerp(m_targetTransform.GetRotation(), blendFactor));
blendTransform.SetTranslation(m_previousTransform.GetTranslation().Lerp(m_targetTransform.GetTranslation(), blendFactor));
blendTransform.SetUniformScale(AZ::Lerp(m_previousTransform.GetUniformScale(), m_targetTransform.GetUniformScale(), blendFactor));
}
if (!GetTransformComponent()->GetWorldTM().IsClose(blendTransform))
{
@@ -809,6 +809,11 @@ namespace Multiplayer
}
}
float MultiplayerSystemComponent::GetCurrentBlendFactor() const
{
return m_renderBlendFactor;
}
INetworkTime* MultiplayerSystemComponent::GetNetworkTime()
{
return &m_networkTime;
@@ -856,12 +861,12 @@ namespace Multiplayer
{
m_tickFactor += deltaTime / serverRateSeconds;
// Linear close to the origin, but asymptote at y = 1
const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f);
m_renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f);
AZLOG
(
NET_Blending,
"Computed blend factor of %0.3f using a tick factor of %0.3f, a frametime of %0.3f and a serverTickRate of %0.3f",
renderBlendFactor,
m_renderBlendFactor,
m_tickFactor,
deltaTime,
serverRateSeconds
@@ -908,7 +913,7 @@ namespace Multiplayer
for (NetBindComponent* netBindComponent : gatheredEntities)
{
netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor);
netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor);
}
}
else
@@ -920,7 +925,7 @@ namespace Multiplayer
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (netBindComponent != nullptr)
{
netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor);
netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor);
}
}
}
@@ -113,6 +113,7 @@ namespace Multiplayer
void Terminate(AzNetworking::DisconnectReason reason) override;
void SendReadyForEntityUpdates(bool readyForEntityUpdates) override;
AZ::TimeMs GetCurrentHostTimeMs() const override;
float GetCurrentBlendFactor() const override;
INetworkTime* GetNetworkTime() override;
INetworkEntityManager* GetNetworkEntityManager() override;
void SetFilterEntityManager(IFilterEntityManager* entityFilter) override;
@@ -155,6 +156,7 @@ namespace Multiplayer
HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0);
double m_serverSendAccumulator = 0.0;
float m_renderBlendFactor = 0.0f;
float m_tickFactor = 0.0f;
#if !defined(AZ_RELEASE_BUILD)
@@ -76,6 +76,16 @@ namespace Multiplayer
return m_hostTimeMs;
}
void NetworkInput::SetHostBlendFactor(float hostBlendFactor)
{
m_hostBlendFactor = hostBlendFactor;
}
float NetworkInput::GetHostBlendFactor() const
{
return m_hostBlendFactor;
}
void NetworkInput::AttachNetBindComponent(NetBindComponent* netBindComponent)
{
m_wasAttached = true;
@@ -91,7 +101,8 @@ namespace Multiplayer
{
if (!serializer.Serialize(m_inputId, "InputId")
|| !serializer.Serialize(m_hostTimeMs, "HostTimeMs")
|| !serializer.Serialize(m_hostFrameId, "HostFrameId"))
|| !serializer.Serialize(m_hostFrameId, "HostFrameId")
|| !serializer.Serialize(m_hostBlendFactor, "HostBlendFactor"))
{
return false;
}
@@ -164,6 +175,7 @@ namespace Multiplayer
m_inputId = rhs.m_inputId;
m_hostFrameId = rhs.m_hostFrameId;
m_hostTimeMs = rhs.m_hostTimeMs;
m_hostBlendFactor = rhs.m_hostBlendFactor;
m_componentInputs.resize(rhs.m_componentInputs.size());
for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i)
{
@@ -55,6 +55,11 @@ namespace Multiplayer
return m_hostTimeMs;
}
float NetworkTime::GetHostBlendFactor() const
{
return m_hostBlendFactor;
}
AzNetworking::ConnectionId NetworkTime::GetRewindingConnectionId() const
{
return m_rewindingConnectionId;
@@ -72,6 +77,11 @@ namespace Multiplayer
m_rewindingConnectionId = rewindConnectionId;
}
void NetworkTime::AlterBlendFactor(float blendFactor)
{
m_hostBlendFactor = blendFactor;
}
void NetworkTime::SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume)
{
// Since the vis system doesn't support rewound queries, first query with an expanded volume to catch any fast moving entities
@@ -95,6 +105,7 @@ namespace Multiplayer
if (networkTransform != nullptr)
{
// We're not presently factoring in interpolated position here
const AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); // Get the rewound position
const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions
const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb
@@ -30,9 +30,11 @@ namespace Multiplayer
HostFrameId GetUnalteredHostFrameId() const override;
void IncrementHostFrameId() override;
AZ::TimeMs GetHostTimeMs() const override;
float GetHostBlendFactor() const override;
AzNetworking::ConnectionId GetRewindingConnectionId() const override;
HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const override;
void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) override;
void AlterBlendFactor(float blendFactor) override;
void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) override;
void ClearRewoundEntities() override;
//! @}
@@ -44,6 +46,7 @@ namespace Multiplayer
HostFrameId m_hostFrameId = HostFrameId{ 0 };
HostFrameId m_unalteredFrameId = HostFrameId{ 0 };
AZ::TimeMs m_hostTimeMs = AZ::TimeMs{ 0 };
float m_hostBlendFactor = DefaultBlendFactor;
AzNetworking::ConnectionId m_rewindingConnectionId = AzNetworking::InvalidConnectionId;
};
}