Cleaning up NetworkTime and reworking how we approach network interpolation

Signed-off-by: puvvadar <puvvadar@amazon.com>
This commit is contained in:
puvvadar
2021-09-02 14:24:46 -07:00
parent de512db010
commit c5d8c194df
9 changed files with 66 additions and 102 deletions
@@ -35,7 +35,7 @@ namespace Multiplayer
using EntityMigrationStartEvent = AZ::Event<ClientInputId>;
using EntityMigrationEndEvent = AZ::Event<>;
using EntityServerMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, HostId, AzNetworking::ConnectionId>;
using EntityPreRenderEvent = AZ::Event<float, float>;
using EntityPreRenderEvent = AZ::Event<float>;
using EntityCorrectionEvent = AZ::Event<>;
//! @class NetBindComponent
@@ -118,7 +118,7 @@ namespace Multiplayer
void NotifyMigrationStart(ClientInputId migratedInputId);
void NotifyMigrationEnd();
void NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId);
void NotifyPreRender(float deltaTime, float blendFactor);
void NotifyPreRender(float deltaTime);
void NotifyCorrection();
void AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler);
@@ -29,24 +29,9 @@ namespace Multiplayer
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
private:
void OnPreRender(float deltaTime, float blendFactor);
void OnPreRender(float deltaTime);
void OnCorrection();
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
void OnTranslationChangedEvent(const AZ::Vector3& translation);
void OnScaleChangedEvent(float scale);
void OnResetCountChangedEvent();
void UpdateTargetHostFrameId();
AZ::Transform m_previousTransform = AZ::Transform::CreateIdentity();
AZ::Transform m_targetTransform = AZ::Transform::CreateIdentity();
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
AZ::Event<float>::Handler m_scaleEventHandler;
AZ::Event<uint8_t>::Handler m_resetCountEventHandler;
EntityPreRenderEvent::Handler m_entityPreRenderEventHandler;
EntityCorrectionEvent::Handler m_entityCorrectionEventHandler;
@@ -7,21 +7,21 @@
{% macro DeclareNetworkPropertyGetter(Property) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['Container'] == 'Array' %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Array() const;
{% else %}
{% else %}
const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Array() const;
{% endif %}
{% endif %}
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}(int32_t index) const;
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
void {{ PropertyName }}AddEvent(AZ::Event<int32_t, {{ Property.attrib['Type'] }}>::Handler& handler);
{% endif %}
{% elif Property.attrib['Container'] == 'Vector' %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Vector() const;
{% else %}
{% else %}
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Vector() const;
{% endif %}
{% endif %}
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}(int32_t index) const;
const {{ Property.attrib['Type'] }}& {{ PropertyName }}GetBack() const;
uint32_t {{ PropertyName }}GetSize() const;
@@ -31,6 +31,9 @@ void {{ PropertyName }}SizeChangedAddEvent(AZ::Event<uint32_t>::Handler& handler
{% endif %}
{% else %}
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const;
{% if Property.attrib['IsRewindable']|booleanTrue %}
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}Previous() const;
{% endif %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
void {{ PropertyName }}AddEvent(AZ::Event<{{ Property.attrib['Type'] }}>::Handler& handler);
{% endif %}
@@ -3,11 +3,11 @@
{% macro LowerFirst(text) %}{{ text[0] | lower}}{{ text[1:] }}{% endmacro %}
{% macro DefineNetworkPropertyGet(ClassName, Property, Prefix = '') %}
{% if Property.attrib['Container'] == 'Array' %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
{% else %}
{% else %}
const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
{% endif %}
{% endif %}
{
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
}
@@ -25,11 +25,11 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even
{% endif %}
{% elif Property.attrib['Container'] == 'Vector' %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
{% if Property.attrib['IsRewindable']|booleanTrue %}
const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const
{% else %}
{% else %}
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const
{% endif %}
{% endif %}
{
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
}
@@ -68,7 +68,12 @@ const {{ Property.attrib['Type'] }}& {{ ClassName }}::Get{{ UpperFirst(Property.
{
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
}
{% if Property.attrib['IsRewindable']|booleanTrue %}
const {{ Property.attrib['Type'] }}& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Previous() const
{
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }}.GetPrevious();
}
{% endif %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Event<{{ Property.attrib['Type'] }}>::Handler& handler)
{
@@ -12,9 +12,9 @@
<Include File="Multiplayer/MultiplayerTypes.h"/>
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="false" />
<NetworkProperty Type="AZ::Vector3" Name="translation" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="false" />
<NetworkProperty Type="uint8_t" Name="resetCount" Init="0" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="NetEntityId" Name="parentEntityId" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="int32_t" Name="parentAttachmentBoneId" Init="-1" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
@@ -403,9 +403,9 @@ namespace Multiplayer
m_entityServerMigrationEvent.Signal(m_netEntityHandle, hostId, connectionId);
}
void NetBindComponent::NotifyPreRender(float deltaTime, float blendFactor)
void NetBindComponent::NotifyPreRender(float deltaTime)
{
m_entityPreRenderEvent.Signal(deltaTime, blendFactor);
m_entityPreRenderEvent.Signal(deltaTime);
}
void NetBindComponent::NotifyCorrection()
@@ -26,11 +26,7 @@ namespace Multiplayer
}
NetworkTransformComponent::NetworkTransformComponent()
: m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); })
, m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); })
, m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); })
, m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); })
, m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); })
: m_entityPreRenderEventHandler([this](float deltaTime) { OnPreRender(deltaTime); })
, m_entityCorrectionEventHandler([this]() { OnCorrection(); })
{
;
@@ -43,15 +39,8 @@ namespace Multiplayer
void NetworkTransformComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
RotationAddEvent(m_rotationEventHandler);
TranslationAddEvent(m_translationEventHandler);
ScaleAddEvent(m_scaleEventHandler);
ResetCountAddEvent(m_resetCountEventHandler);
GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler);
GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler);
// When coming into relevance, reset all blending factors so we don't interpolate to our start position
OnResetCountChangedEvent();
}
void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
@@ -59,59 +48,31 @@ namespace Multiplayer
;
}
void NetworkTransformComponent::OnRotationChangedEvent(const AZ::Quaternion& rotation)
{
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()
{
m_targetTransform.SetRotation(GetRotation());
m_targetTransform.SetTranslation(GetTranslation());
m_targetTransform.SetUniformScale(GetScale());
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)
void NetworkTransformComponent::OnPreRender([[maybe_unused]] float deltaTime)
{
if (!HasController())
{
AZ::Transform blendTransform;
if (Multiplayer::GetNetworkTime() && Multiplayer::GetNetworkTime()->GetHostFrameId() > m_targetHostFrameId)
blendTransform.SetRotation(GetRotation());
blendTransform.SetTranslation(GetTranslation());
blendTransform.SetUniformScale(GetScale());
const float blendFactor = GetNetworkTime()->GetHostBlendFactor();
if (!!AZ::IsClose(blendFactor, 1.0f))
{
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));
AZ::Transform blendTransformPrevious;
blendTransformPrevious.SetRotation(GetRotationPrevious());
blendTransformPrevious.SetTranslation(GetTranslationPrevious());
blendTransformPrevious.SetUniformScale(GetScalePrevious());
if (!blendTransform.IsClose(blendTransformPrevious))
{
blendTransform.SetRotation(blendTransformPrevious.GetRotation().Slerp(blendTransform.GetRotation(), blendFactor));
blendTransform.SetTranslation(
blendTransformPrevious.GetTranslation().Lerp(blendTransform.GetTranslation(), blendFactor));
blendTransform.SetUniformScale(
AZ::Lerp(blendTransformPrevious.GetUniformScale(), blendTransform.GetUniformScale(), blendFactor));
}
}
if (!GetTransformComponent()->GetWorldTM().IsClose(blendTransform))
@@ -124,12 +85,15 @@ namespace Multiplayer
void NetworkTransformComponent::OnCorrection()
{
// Snap to latest
OnResetCountChangedEvent();
AZ::Transform targetTransform;
targetTransform.SetRotation(GetRotation());
targetTransform.SetTranslation(GetTranslation());
targetTransform.SetUniformScale(GetScale());
// Hard set the entities transform
if (!GetTransformComponent()->GetWorldTM().IsClose(m_targetTransform))
if (!GetTransformComponent()->GetWorldTM().IsClose(targetTransform))
{
GetTransformComponent()->SetWorldTM(m_targetTransform);
GetTransformComponent()->SetWorldTM(targetTransform);
}
}
@@ -922,7 +922,7 @@ namespace Multiplayer
for (NetBindComponent* netBindComponent : gatheredEntities)
{
netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor);
netBindComponent->NotifyPreRender(deltaTime);
}
}
else
@@ -934,7 +934,7 @@ namespace Multiplayer
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (netBindComponent != nullptr)
{
netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor);
netBindComponent->NotifyPreRender(deltaTime);
}
}
}
@@ -110,8 +110,15 @@ namespace Multiplayer
if (networkTransform != nullptr)
{
// We're not presently factoring in interpolated position here
const AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); // Get the rewound position
// Get the rewound position for target host frame ID plus the one preceding it for potential lerp
AZ::Vector3 rewindCenter = networkTransform->GetTranslation();
const AZ::Vector3 rewindCenterPrevious = networkTransform->GetTranslationPrevious();
const float blendFactor = GetNetworkTime()->GetHostBlendFactor();
if (!AZ::IsClose(blendFactor, 1.0f) && !rewindCenter.IsClose(rewindCenterPrevious))
{
// If we have a blend factor, lerp the translation for accuracy
rewindCenter = rewindCenterPrevious.Lerp(rewindCenter, blendFactor);
}
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