NetworkTransformComponent.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Multiplayer/Components/NetworkTransformComponent.h>
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Serialization/EditContext.h>
  11. #include <AzCore/EBus/IEventScheduler.h>
  12. #include <AzFramework/Components/TransformComponent.h>
  13. namespace Multiplayer
  14. {
  15. void NetworkTransformComponent::Reflect(AZ::ReflectContext* context)
  16. {
  17. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  18. if (serializeContext)
  19. {
  20. serializeContext->Class<NetworkTransformComponent, NetworkTransformComponentBase>()
  21. ->Version(1);
  22. }
  23. NetworkTransformComponentBase::Reflect(context);
  24. AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
  25. if (behaviorContext)
  26. {
  27. behaviorContext->Class<NetworkTransformComponent>("NetworkTransformComponent")
  28. ->Attribute(AZ::Script::Attributes::Module, "multiplayer")
  29. ->Attribute(AZ::Script::Attributes::Category, "Multiplayer")
  30. ->Method("IncrementResetCount", [](AZ::EntityId id)
  31. {
  32. const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
  33. if (!entity)
  34. {
  35. AZ_Warning("Network Property", false, "NetworkTransformComponent IncrementResetCount failed. "
  36. "The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str());
  37. }
  38. NetworkTransformComponent* networkComponent = entity->FindComponent<NetworkTransformComponent>();
  39. if (!networkComponent)
  40. {
  41. AZ_Warning("Network Property", false, "NetworkTransformComponent IncrementResetCount failed. "
  42. "Entity '%s' (id: %s) is missing NetworkTransformComponent, be sure to add NetworkTransformComponent to this entity.", entity->GetName().c_str(), id.ToString().c_str());
  43. }
  44. else
  45. {
  46. if (networkComponent->HasController())
  47. {
  48. static_cast<NetworkTransformComponentController*>(networkComponent->GetController())->ModifyResetCount()++;
  49. }
  50. else
  51. {
  52. AZ_Warning("Network Property", false, "NetworkTransformComponent IncrementResetCount failed. "
  53. "Entity '%s' (id: %s) does not have Authority or Autonomous role.", entity->GetName().c_str(), id.ToString().c_str());
  54. }
  55. }
  56. });
  57. }
  58. }
  59. NetworkTransformComponent::NetworkTransformComponent()
  60. : m_entityPreRenderEventHandler([this](float deltaTime) { OnPreRender(deltaTime); })
  61. , m_entityCorrectionEventHandler([this]() { OnCorrection(); })
  62. , m_rotationChangedEventHandler([this](AZ::Quaternion) { OnTransformChanged(); })
  63. , m_translationChangedEventHandler([this](AZ::Vector3) { OnTransformChanged(); })
  64. , m_scaleChangedEventHandler([this](float) { OnTransformChanged(); })
  65. , m_parentChangedEventHandler([this](NetEntityId parentId) { OnParentChanged(parentId); })
  66. , m_resetCountChangedEventHandler([this]([[maybe_unused]] uint8_t resetCount) { m_syncTransformImmediate = true; })
  67. {
  68. ;
  69. }
  70. void NetworkTransformComponent::OnInit()
  71. {
  72. ;
  73. }
  74. void NetworkTransformComponent::OnActivate([[maybe_unused]] EntityIsMigrating entityIsMigrating)
  75. {
  76. GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler);
  77. GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler);
  78. RotationAddEvent(m_rotationChangedEventHandler);
  79. TranslationAddEvent(m_translationChangedEventHandler);
  80. ScaleAddEvent(m_scaleChangedEventHandler);
  81. ParentEntityIdAddEvent(m_parentChangedEventHandler);
  82. ResetCountAddEvent(m_resetCountChangedEventHandler);
  83. if (!GetNetBindComponent()->IsNetEntityRoleAuthority())
  84. {
  85. OnParentChanged(GetParentEntityId());
  86. }
  87. }
  88. void NetworkTransformComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating)
  89. {
  90. m_resetCountChangedEventHandler.Disconnect();
  91. m_parentChangedEventHandler.Disconnect();
  92. m_entityCorrectionEventHandler.Disconnect();
  93. m_entityPreRenderEventHandler.Disconnect();
  94. }
  95. void NetworkTransformComponent::OnPreRender([[maybe_unused]] float deltaTime)
  96. {
  97. if (!HasController())
  98. {
  99. AZ::Transform blendTransform(GetTranslation(), GetRotation(), GetScale());
  100. if (!m_syncTransformImmediate)
  101. {
  102. const float blendFactor = GetMultiplayer()->GetCurrentBlendFactor();
  103. if (!AZ::IsClose(blendFactor, 1.0f))
  104. {
  105. const AZ::Transform blendTransformPrevious(GetTranslationPrevious(), GetRotationPrevious(), GetScalePrevious());
  106. if (!blendTransform.IsClose(blendTransformPrevious))
  107. {
  108. blendTransform.SetRotation(blendTransformPrevious.GetRotation().Slerp(blendTransform.GetRotation(), blendFactor));
  109. blendTransform.SetTranslation(
  110. blendTransformPrevious.GetTranslation().Lerp(blendTransform.GetTranslation(), blendFactor));
  111. blendTransform.SetUniformScale(
  112. AZ::Lerp(blendTransformPrevious.GetUniformScale(), blendTransform.GetUniformScale(), blendFactor));
  113. }
  114. }
  115. }
  116. else
  117. {
  118. m_syncTransformImmediate = false;
  119. }
  120. AzFramework::TransformComponent* transformComponent = GetTransformComponent();
  121. if (GetParentEntityId() == InvalidNetEntityId)
  122. {
  123. if (!transformComponent->GetWorldTM().IsClose(blendTransform))
  124. {
  125. transformComponent->SetWorldTM(blendTransform);
  126. }
  127. }
  128. else
  129. {
  130. if (!transformComponent->GetLocalTM().IsClose(blendTransform))
  131. {
  132. transformComponent->SetLocalTM(blendTransform);
  133. }
  134. }
  135. }
  136. }
  137. void NetworkTransformComponent::OnCorrection()
  138. {
  139. // Snap to latest
  140. AZ::Transform targetTransform;
  141. targetTransform.SetRotation(GetRotation());
  142. targetTransform.SetTranslation(GetTranslation());
  143. targetTransform.SetUniformScale(GetScale());
  144. // Hard set the entities transform
  145. AzFramework::TransformComponent* transformComponent = GetTransformComponent();
  146. if (GetParentEntityId() == InvalidNetEntityId)
  147. {
  148. if (!transformComponent->GetWorldTM().IsClose(targetTransform))
  149. {
  150. transformComponent->SetWorldTM(targetTransform);
  151. }
  152. }
  153. else
  154. {
  155. if (!transformComponent->GetLocalTM().IsClose(targetTransform))
  156. {
  157. transformComponent->SetLocalTM(targetTransform);
  158. }
  159. }
  160. }
  161. void NetworkTransformComponent::OnTransformChanged()
  162. {
  163. OnPreRender(0.0f);
  164. }
  165. void NetworkTransformComponent::OnParentChanged(NetEntityId parentId)
  166. {
  167. if (AZ::TransformInterface* transformComponent = GetEntity()->GetTransform())
  168. {
  169. const ConstNetworkEntityHandle parentEntityHandle = GetNetworkEntityManager()->GetEntity(parentId);
  170. if (parentEntityHandle.Exists())
  171. {
  172. if (const AZ::Entity* parentEntity = parentEntityHandle.GetEntity())
  173. {
  174. transformComponent->SetParent(parentEntity->GetId());
  175. }
  176. }
  177. else
  178. {
  179. transformComponent->SetParent(AZ::EntityId());
  180. }
  181. }
  182. }
  183. NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent)
  184. : NetworkTransformComponentControllerBase(parent)
  185. , m_transformChangedHandler([this](const AZ::Transform& localTm, const AZ::Transform& worldTm) { OnTransformChangedEvent(localTm, worldTm); })
  186. , m_parentIdChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId newParent) { OnParentIdChangedEvent(oldParent, newParent); })
  187. {
  188. ;
  189. }
  190. void NetworkTransformComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
  191. {
  192. if (AzFramework::TransformComponent* parentTransform = GetParent().GetTransformComponent())
  193. {
  194. parentTransform->BindTransformChangedEventHandler(m_transformChangedHandler);
  195. OnTransformChangedEvent(parentTransform->GetLocalTM(), parentTransform->GetWorldTM());
  196. parentTransform->BindParentChangedEventHandler(m_parentIdChangedHandler);
  197. OnParentIdChangedEvent(AZ::EntityId(), parentTransform->GetParentId());
  198. }
  199. }
  200. void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
  201. {
  202. m_parentIdChangedHandler.Disconnect();
  203. m_transformChangedHandler.Disconnect();
  204. }
  205. void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& localTm, const AZ::Transform& worldTm)
  206. {
  207. const AZ::Transform& localOrWorld = GetParentEntityId() == InvalidNetEntityId ? worldTm : localTm;
  208. SetRotation(localOrWorld.GetRotation());
  209. SetTranslation(localOrWorld.GetTranslation());
  210. SetScale(localOrWorld.GetUniformScale());
  211. }
  212. void NetworkTransformComponentController::OnParentIdChangedEvent([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent)
  213. {
  214. AZ::Entity* parentEntity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(newParent);
  215. if (parentEntity)
  216. {
  217. const ConstNetworkEntityHandle parentHandle(parentEntity, GetNetworkEntityTracker());
  218. if (parentHandle.Exists())
  219. {
  220. SetParentEntityId(parentHandle.GetNetEntityId());
  221. }
  222. }
  223. }
  224. #if AZ_TRAIT_SERVER
  225. void NetworkTransformComponentController::HandleMultiplayerTeleport(
  226. [[maybe_unused]] AzNetworking::IConnection* invokingConnection, const AZ::Vector3& teleportToPosition)
  227. {
  228. GetEntity()->GetTransform()->SetWorldTranslation(teleportToPosition);
  229. ModifyResetCount()++;
  230. }
  231. #endif
  232. }