Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sdk other players transform propagation #1030

Merged
merged 22 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a2cae1f
added systems to propagate and write
pravusjif May 9, 2024
397a718
Merge branch 'main' of github.com:decentraland/unity-explorer into fe…
pravusjif Jun 13, 2024
b4aefb1
Merge branch 'main' into feat/sdk-other-players-transform-propagation
NickKhalow Jul 17, 2024
282a34e
remove unused arg
NickKhalow Jul 17, 2024
2e55d15
Merge branch 'main' into feat/sdk-other-players-transform-propagation
NickKhalow Jul 17, 2024
b84f2bc
Merge branch 'main' into feat/sdk-other-players-transform-propagation
NickKhalow Jul 17, 2024
ca5937b
transform propagation test
NickKhalow Jul 17, 2024
20ca672
Merge remote-tracking branch 'origin/feat/sdk-other-players-transform…
NickKhalow Jul 17, 2024
81f389e
fixed other players transform data not being propagated correctly
pravusjif Jul 17, 2024
8e73a7e
Merge branch 'main' into feat/sdk-other-players-transform-propagation
NickKhalow Jul 18, 2024
1befc16
Merge branch 'main' of github.com:decentraland/unity-explorer into fe…
pravusjif Jul 24, 2024
a76af77
fixed problems from main merge
pravusjif Jul 24, 2024
f710968
RealmLauncherSettings drawer property fix
pravusjif Jul 24, 2024
6cb76e1
Merge branch 'main' of github.com:decentraland/unity-explorer into fe…
pravusjif Sep 11, 2024
b6c7fd5
tackled some PR review feedback
pravusjif Sep 12, 2024
b5c6df3
Made SDKTransform implement IExplosedTransform to be able to use Expo…
pravusjif Sep 12, 2024
f03598b
Merge branch 'main' into feat/sdk-other-players-transform-propagation
pravusjif Sep 12, 2024
82608fb
fixed missing import on main merge
pravusjif Sep 12, 2024
931e5e2
fixed test
pravusjif Sep 12, 2024
c507c67
Merge branch 'main' of github.com:decentraland/unity-explorer into fe…
pravusjif Sep 17, 2024
7ee519e
removed 'fake' class/interfaces introduced and replaced them with NSu…
pravusjif Sep 17, 2024
3b13941
Merge branch 'main' of github.com:decentraland/unity-explorer into fe…
pravusjif Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace DCL.CharacterMotion.Systems
/// Executes on the scene level to propagate the shared transform data to the SDK Scene
/// </summary>
[UpdateInGroup(typeof(SyncedInitializationSystemGroup))]
public partial class WritePlayerTransformSystem : BaseUnityLoopSystem
public partial class WriteMainPlayerTransformSystem : BaseUnityLoopSystem
{
private readonly IECSToCRDTWriter ecsToCrdtWriter;
private readonly ISceneData sceneData;
Expand All @@ -29,7 +29,7 @@ public partial class WritePlayerTransformSystem : BaseUnityLoopSystem
private IComponentPool<SDKTransform> sdkTransformPool;
private readonly Entity playerEntity;

internal WritePlayerTransformSystem(World world, IECSToCRDTWriter ecsToCrdtWriter, ISceneData sceneData, IExposedTransform exposedTransform, IPartitionComponent scenePartition,
internal WriteMainPlayerTransformSystem(World world, IECSToCRDTWriter ecsToCrdtWriter, ISceneData sceneData, IExposedTransform exposedTransform, IPartitionComponent scenePartition,
byte bucketThreshold, IComponentPool<SDKTransform> sdkTransformPool, Entity playerEntity) : base(world)
{
this.ecsToCrdtWriter = ecsToCrdtWriter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public WorldPlugin(ExposedTransform exposedTransform, IExposedCameraData exposed

public void InjectToWorld(ref ArchSystemsWorldBuilder<World> builder, in ECSWorldInstanceSharedDependencies sharedDependencies, in PersistentEntities persistentEntities, List<IFinalizeWorldSystem> finalizeWorldSystems, List<ISceneIsCurrentListener> sceneIsCurrentListeners)
{
WritePlayerTransformSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter, sharedDependencies.SceneData,
WriteMainPlayerTransformSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter, sharedDependencies.SceneData,
exposedTransform, sharedDependencies.ScenePartition, bucketPropagationLimit, sdkTransformPool, persistentEntities.Player);

WriteCameraComponentsSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter, exposedCameraData, sharedDependencies.SceneData,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Arch.Core;
using Arch.System;
using Arch.SystemGroups;
using CrdtEcsBridge.Components;
using CrdtEcsBridge.Components.Transform;
using DCL.Character.Components;
using DCL.Diagnostics;
using DCL.Multiplayer.SDK.Components;
using ECS.Abstract;
using ECS.Groups;
using ECS.LifeCycle.Components;
using Utility;
using Quaternion = UnityEngine.Quaternion;
using Vector3 = UnityEngine.Vector3;

namespace DCL.Multiplayer.SDK.Systems.GlobalWorld
{
[UpdateInGroup(typeof(SyncedPreRenderingSystemGroup))]
[LogCategory(ReportCategory.PLAYER_SDK_DATA)]
public partial class PlayerTransformPropagationSystem : BaseUnityLoopSystem
{
public PlayerTransformPropagationSystem(World world) : base(world) { }

protected override void Update(float t)
{
PropagateTransformToSceneQuery(World);
}

[Query]
[None(typeof(DeleteEntityIntention))]
private void PropagateTransformToScene(in CharacterTransform characterTransform, in PlayerCRDTEntity playerCRDTEntity)
{
if (!characterTransform.Transform.hasChanged) return;

// Main player Transform is handled by 'WriteMainPlayerTransformSystem'
if (playerCRDTEntity.CRDTEntity.Id == SpecialEntitiesID.PLAYER_ENTITY) return;

World sceneEcsWorld = playerCRDTEntity.SceneFacade.EcsExecutor.World;

// Position is updated to scene-relative on the writer system
if (sceneEcsWorld.TryGet(playerCRDTEntity.SceneWorldEntity, out SDKTransform? sdkTransform))
{
sdkTransform!.Position.Value = characterTransform.Transform.position;
sdkTransform.Rotation.Value = characterTransform.Transform.rotation;
sdkTransform.IsDirty = true;
sceneEcsWorld.Set(playerCRDTEntity.SceneWorldEntity, sdkTransform);
return;
}

sdkTransform = new SDKTransform
{
Position = new CanBeDirty<Vector3>(characterTransform.Transform.position),
Rotation = new CanBeDirty<Quaternion>(characterTransform.Transform.rotation),
IsDirty = true
};
sceneEcsWorld.Add(playerCRDTEntity.SceneWorldEntity, sdkTransform);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Arch.Core;
using Arch.System;
using Arch.SystemGroups;
using CrdtEcsBridge.Components;
using CrdtEcsBridge.Components.Transform;
using CrdtEcsBridge.ECSToCRDTWriter;
using DCL.Diagnostics;
using DCL.Multiplayer.SDK.Components;
using ECS.Abstract;
using ECS.Groups;
using ECS.LifeCycle.Components;
using ECS.Unity.Transforms;
using SceneRunner.Scene;

namespace DCL.Multiplayer.SDK.Systems.SceneWorld
{
[UpdateInGroup(typeof(SyncedPreRenderingSystemGroup))]
[LogCategory(ReportCategory.PLAYER_SDK_DATA)]
public partial class WritePlayerTransformSystem : BaseUnityLoopSystem
{
private readonly IECSToCRDTWriter ecsToCRDTWriter;
private readonly ISceneData sceneData;

public WritePlayerTransformSystem(World world, IECSToCRDTWriter ecsToCRDTWriter, ISceneData sceneData) : base(world)
{
this.ecsToCRDTWriter = ecsToCRDTWriter;
this.sceneData = sceneData;
}

protected override void Update(float t)
{
HandleComponentRemovalQuery(World);
UpdateSDKTransformQuery(World);
}

[Query]
[None(typeof(DeleteEntityIntention))]
private void UpdateSDKTransform(in PlayerSceneCRDTEntity playerCRDTEntity, ref SDKTransform sdkTransform)
{
if (!sdkTransform.IsDirty) return;

// Main player Transform is handled by 'WriteMainPlayerTransformSystem'
if (playerCRDTEntity.CRDTEntity.Id == SpecialEntitiesID.PLAYER_ENTITY) return;

// Patches position to be scene-relative before sending it through CRDT
ExposedTransformUtils.Put(
ecsToCRDTWriter,
sdkTransform,
playerCRDTEntity.CRDTEntity,
sceneData.Geometry.BaseParcelPosition,
false);
}

[Query]
[All(typeof(DeleteEntityIntention))]
private void HandleComponentRemoval(in PlayerSceneCRDTEntity playerCRDTEntity)
{
ecsToCRDTWriter.DeleteMessage<SDKTransform>(playerCRDTEntity.CRDTEntity);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Arch.Core;
using CRDT;
using CrdtEcsBridge.Components.Transform;
using CrdtEcsBridge.ECSToCRDTWriter;
using DCL.Character.Components;
using DCL.Multiplayer.SDK.Components;
using DCL.Multiplayer.SDK.Systems.GlobalWorld;
using DCL.Multiplayer.SDK.Systems.SceneWorld;
using NSubstitute;
using NUnit.Framework;
using SceneRunner.Scene;
using System;
using UnityEngine;
using Utility;

namespace DCL.Multiplayer.SDK.Tests
{
public class PropagateTransformTest
{
[Test]
public void PropagateTransform()
{
const int CRDT_ID = 100;

var globalWorld = World.Create();
var sceneWorld = World.Create();

var writer = Substitute.For<IECSToCRDTWriter>();
var sceneData = Substitute.For<ISceneData>();
Vector3 sceneBasePos = new Vector3(15, 0, -56);
var sceneGeometry = new ParcelMathHelper.SceneGeometry(sceneBasePos, new ParcelMathHelper.SceneCircumscribedPlanes(), 20);
sceneData.Geometry.Returns(sceneGeometry);

var propagationSystem = new PlayerTransformPropagationSystem(globalWorld);
var writeSystem = new WritePlayerTransformSystem(sceneWorld, writer, sceneData);

var sceneFacade = Substitute.For<ISceneFacade>();
var sceneEcsExecutor = new SceneEcsExecutor(sceneWorld);
sceneFacade.EcsExecutor.Returns(sceneEcsExecutor);

var sceneWorldEntity = sceneWorld.Create();
var crdtEntity = new CRDTEntity(CRDT_ID);
var playerCRDTEntity = new PlayerCRDTEntity(
crdtEntity,
sceneFacade,
sceneWorldEntity
);
var playerSceneCRDTEntity = new PlayerSceneCRDTEntity(crdtEntity);

Transform fakeCharaTransform = new GameObject("fake character").transform;
fakeCharaTransform.position = Vector3.one * 6;
fakeCharaTransform.rotation = Quaternion.Euler(15, 6, 89);
var charaTransform = new CharacterTransform(fakeCharaTransform);
globalWorld.Create(
charaTransform,
playerCRDTEntity
);
sceneWorld.Add(sceneWorldEntity, playerSceneCRDTEntity);

propagationSystem.Update(0);
writeSystem.Update(0);

writer.Received(1)
.PutMessage(
Arg.Any<Action<SDKTransform, (IExposedTransform, Vector3)>>(),
playerCRDTEntity.CRDTEntity,
Arg.Is<(IExposedTransform exposedTransform, Vector3 scenePosition)>(data =>
data.exposedTransform.Position.Value.Equals(fakeCharaTransform.position)
&& data.exposedTransform.Rotation.Value.Equals(fakeCharaTransform.rotation)
&& data.scenePosition.Equals(sceneData.Geometry.BaseParcelPosition)));
writer.ClearReceivedCalls();

// Cleanup
globalWorld.Dispose();
sceneWorld.Dispose();
propagationSystem.Dispose();
writeSystem.Dispose();
GameObject.DestroyImmediate(fakeCharaTransform.gameObject);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder<Arch.Core.World> builder,
PlayerProfileDataPropagationSystem.InjectToWorld(ref builder, characterDataPropagationUtility, globalPluginArguments.PlayerEntity);
ResetDirtyFlagSystem<AvatarEmoteCommandComponent>.InjectToWorld(ref builder);
AvatarEmoteCommandPropagationSystem.InjectToWorld(ref builder, emoteStorage);
PlayerTransformPropagationSystem.InjectToWorld(ref builder);
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder<Arch.Core.World> builder,
WriteSDKAvatarBaseSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter);
WriteAvatarEquippedDataSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter);
WriteAvatarEmoteCommandSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter, sharedDependencies.SceneStateProvider);
WritePlayerTransformSystem.InjectToWorld(ref builder, sharedDependencies.EcsToCRDTWriter, sharedDependencies.SceneData);

CleanUpAvatarPropagationComponentsSystem.InjectToWorld(ref builder);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ protected override (Vector3, Vector3) GetTweenValues(PBTween pbTween, Transform

public override void SetResult(ref SDKTransform sdkTransform)
{
sdkTransform.Position = currentValue;
sdkTransform.Position.Value = currentValue;

sdkTransform.Rotation = startRotation;
sdkTransform.Rotation.Value = startRotation;
sdkTransform.Scale = startScale;
}
}
Expand All @@ -54,8 +54,8 @@ public override void SetResult(ref SDKTransform sdkTransform)
{
sdkTransform.Scale = currentValue;

sdkTransform.Position = startPosition;
sdkTransform.Rotation = startRotation;
sdkTransform.Position.Value = startPosition;
sdkTransform.Rotation.Value = startRotation;
}
}

Expand All @@ -79,9 +79,9 @@ protected override TweenerCore<Quaternion, Quaternion, NoOptions> CreateTweener(

public override void SetResult(ref SDKTransform sdkTransform)
{
sdkTransform.Rotation = currentValue;
sdkTransform.Rotation.Value = currentValue;

sdkTransform.Position = startPosition;
sdkTransform.Position.Value = startPosition;
sdkTransform.Scale = startScale;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using Utility;

namespace CrdtEcsBridge.Components.Transform
{
/// <summary>
/// Special type (not Proto) to serialize/deserialize faster according to the ADR
/// </summary>
public class SDKTransform : IDirtyMarker, IMessage
public class SDKTransform : IDirtyMarker, IMessage, IExposedTransform
{
public CanBeDirty<Vector3> Position = new CanBeDirty<Vector3>(Vector3.zero);
public CanBeDirty<Quaternion> Rotation = new CanBeDirty<Quaternion>(Quaternion.identity);
CanBeDirty<Vector3> IExposedTransform.Position => Position;
CanBeDirty<Quaternion> IExposedTransform.Rotation => Rotation;

public CRDTEntity ParentId = 0;
public Vector3 Position = Vector3.zero;
public Quaternion Rotation = Quaternion.identity;
public Vector3 Scale = Vector3.one;
public bool IsDirty { get; set; }

Expand All @@ -38,8 +42,8 @@ public int CalculateSize() =>
public void Clear()
{
ParentId = 0;
Position = Vector3.zero;
Rotation = Quaternion.identity;
Position.Value = Vector3.zero;
Rotation.Value = Quaternion.identity;
Scale = Vector3.one;
IsDirty = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ public class SDKTransformSerializer : IComponentSerializer<SDKTransform>
public void DeserializeInto(SDKTransform instance, in ReadOnlySpan<byte> data)
{
ReadOnlySpan<byte> pointer = data;
instance.Position = pointer.Read<Vector3>();
instance.Rotation = pointer.Read<Quaternion>();
instance.Position.Value = pointer.Read<Vector3>();
instance.Rotation.Value = pointer.Read<Quaternion>();
instance.Scale = pointer.Read<Vector3>();
instance.ParentId = pointer.Read<CRDTEntity>();
}

public void SerializeInto(SDKTransform instance, in Span<byte> span)
{
Span<byte> pointer = span;
pointer.Write(instance.Position);
pointer.Write(instance.Rotation);
pointer.Write(instance.Position.Value);
pointer.Write(instance.Rotation.Value);
pointer.Write(instance.Scale);
pointer.Write(instance.ParentId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"GUID:7f6c11dd1400cef4f838168f18ce244a",
"GUID:3c7b57a14671040bd8c549056adc04f5",
"GUID:0f4c0f120707fb74497f5d581b9858f8",
"GUID:fa7b3fdbb04d67549916da7bd2af58ab",
"GUID:3640f3c0b42946b0b8794a1ed8e06ca5"
],
"includePlatforms": [
Expand Down
3 changes: 2 additions & 1 deletion Explorer/Assets/Scripts/ECS/TestSuite/EcsTestsUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using CrdtEcsBridge.Components.Transform;
using ECS.Unity.Transforms.Components;
using UnityEngine;
using Utility;

namespace ECS.TestSuite
{
Expand All @@ -21,7 +22,7 @@ public static TransformComponent AddTransformToEntity(World world, in Entity ent

var transformComponent = new TransformComponent(t);

world.Add(entity, transformComponent, new SDKTransform { IsDirty = isDirty, Position = Vector3.zero, Rotation = Quaternion.identity, Scale = Vector3.one });
world.Add(entity, transformComponent, new SDKTransform { IsDirty = isDirty, Position = new CanBeDirty<Vector3>(Vector3.zero), Rotation = new CanBeDirty<Quaternion>(Quaternion.identity), Scale = Vector3.one });
return transformComponent;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public static class ExposedTransformUtils

return ecsToCrdtWriter.PutMessage<SDKTransform, (IExposedTransform, Vector3)>(static (c, data) =>
{
c.Position = ParcelMathHelper.GetSceneRelativePosition(data.Item1.Position.Value, data.Item2);
c.Rotation = data.Item1.Rotation.Value;
c.Position.Value = ParcelMathHelper.GetSceneRelativePosition(data.Item1.Position.Value, data.Item2);
c.Rotation.Value = data.Item1.Rotation.Value;
}, entity, (exposedTransform, scenePosition));
}
}
Expand Down
Loading
Loading