SyncedTransform only works with DragControls?

Hi everyone one!

I am trying to move a cube on a scene by clicking on a plane using lerp. It works but the cube position is not replicated in other screens. But if I move the cube using DragControls component it works fine.

Is that a way to replicate some GameObject position without using DragControls component?

Original Post on Discord

by user 918470773134483507

Hey, i think you need to request ownership on the synctransform - its what the drag controls does when you start the drag. Im not at the pc anymore so can not look it up right now but take a look at the drag controls source

(you can click the blue link on drag controls in unity to open the typescript source)

(in other scenes i assume you mean for other clients in a networked room / multiple people visiting the same url, right?)

SyncTransform.requestOwnership() is the method you need to call

Thank God! It worked!

by user 918470773134483507

Here the component that I wrote:

import { Behaviour, GameObject, serializable, SyncedTransform } from "@needle-tools/engine" 
import { IPointerEventHandler, PointerEventData } from "@needle-tools/engine/engine-components/ui/PointerEvents"; 
import { Vector3 } from "three" 
 
export class Teste extends Behaviour implements IPointerEventHandler { 
 
  @serializable(GameObject) 
  cube?: GameObject; 
 
  lerpAlpha = 1 
  lerpDestination: Vector3 | undefined 
 
  start() { 
 
  } 
 
  onPointerClick(args: PointerEventData) { 
 
    this.lerpAlpha = 0; 
    this.lerpDestination = this.context.physics.raycast()[0].point; 
 
  } 
 
  update() { 
 
    if (this.lerpAlpha < 1) { 
      GameObject.getComponentInChildren(this.cube, SyncedTransform)?.requestOwnership() 
      this.cube?.position.lerp(this.lerpDestination, this.lerpAlpha += 1) 
    } 
 
  } 
}

by user 918470773134483507

Thanks @marcel :cactus: to answer me so quickly!

by user 918470773134483507

Sure thing.

Could you wrap your code in 3 backticks that way its easier to read :slightly_smiling_face:

You can also add ts after the first 3 ` to add typescript syntax highlighting

Like this:

Oh another tip: you should only request ownership once when you start doing something (e.g. onPointerClick)

Otherwise youll send network requests every frame which could get expensive and also make the backend slow if you have a lot of those cases

Hi again @marcel :cactus: :grin:

Now I am trying to move two objects on the scene and replicate their positions. But when I try, they has the same position on the replicated screen.

Here the component code:

import { AssetReference, Behaviour, GameObject, serializable, SyncedTransform } from "@needle-tools/engine"

import { IPointerEventHandler } from "@needle-tools/engine/engine-components/ui/PointerEvents";

import { IGameObject } from "@needle-tools/engine/engine/engine_types";

import { Object3D } from "three"

export class Teste extends Behaviour implements IPointerEventHandler {

  @serializable(AssetReference)

  cube?: AssetReference;
  @serializable(AssetReference)
  capsule?: AssetReference;

private instantiatedCube: IGameObject | undefined;
private instantiatedCapsule: IGameObject | undefined;

  private i = 0;

  async start() {

this.instantiatedCube = await this.cube?.instantiate() as IGameObject;
    this.instantiatedCube.addNewComponent(SyncedTransform);

this.instantiatedCapsule = await this.capsule?.instantiate() as IGameObject;
 this.instantiatedCapsule.addNewComponent(SyncedTransform); 

  } 

  // @ts-ignore
  async onPointerClick(args: PointerEventData) {
 
    if (this.i++ % 2) {

await this.instantiatedCube?.getComponent(SyncedTransform)?.requestOwnership();
      this.instantiatedCube?.position.setY(this.instantiatedCube.position.y + 0.1);

    } else {

 await this.instantiatedCapsule?.getComponent(SyncedTransform)?.requestOwnership();
      this.instantiatedCapsule?.position.setY(this.instantiatedCapsule.position.y + 0.1);

    } 

  }
 
  update() {
 
  }

}

Can you help me to replicate the movement correctly?

by user 918470773134483507

You need to give the synced transforms a guid for each object. Use an InstanceIdProvider for it (i can give you better info later, im not yet at the pc). You should initialize it with a known seed (e.g. new InstanceIdProvider(this.guid))

Basically what happens is (i think) that the synced transform component is created with the same guid and so they take the networking events for both objects.

I didn’t understand how to use the InstaceIdProvider in my code. Can you be more specific? :sweat_smile:

by user 918470773134483507

So in general if you dont need to add components on the fly like you do above you could also just add it in Unity as a component on your prefab (e.g. add a SyncedTransform component on the cube asset that you reference).

Here is a little codesnippet that should work for how you do it right now:

        const idProvider = new InstantiateIdProvider(this.guid);
        const st = GameObject.addNewComponent(this.gameObject, SyncedTransform, false);
        st.guid = idProvider.generateUUID();

the this.guid I pass in the id provider here is the seed (it can be either a string or a number)

I am adding components in this way because I intend to download the assets from the internet in the project that I am working, so then I will not have access to them through Unity editor

by user 918470773134483507

Ok then its fine :slightly_smiling_face:

This part brakes my code with ‘Invalid assignment target’ error :sob:

st.guid = idProvider.generateUUID();

by user 918470773134483507