microsoft / MixedRealityToolkit-Unity

This repository is for the legacy Mixed Reality Toolkit (MRTK) v2. For the latest version of the MRTK please visit https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity
https://aka.ms/mrtkdocs
MIT License
6.01k stars 2.12k forks source link

SharingWithUNET - Non-Player-Objects not syncing on other clients. #722

Closed Subere23 closed 7 years ago

Subere23 commented 7 years ago

Using the SharingWithUnet as the starting point for a project, I can get things up and going fine with player objects. Network spawning non-player objects work fine(using the InputModule to control it, specifically IInputClickHandler). And of course, it moves around and works correctly on the system that is moving it. For some reason, nothing I have tried over the last 2 days has been about to get transform to sync on the other clients. If I parent the non-player object to the player it syncs fine as well. My research tells me this is an issue with the unet authority system and I have tried everything I can think of to alleviate this issue. My question is this- is there something in the Generic Network Transmitter that could be messing with the Unet authority system?

Ziugy commented 7 years ago

Are you using a WorldAnchor and parenting children under that? If you are, you will need to create a NetworkBehaviour with SyncVar for localPosition, localRotation, and localScale. Unity space between HoloLenses are different and need to be accounted for. NetworkTransform / NetworkTransformChild cannot be used because they sync position and rotation. Hopefully soon I will be able to move up a "SharedTransform" component I worked on that works around this issue.

Subere23 commented 7 years ago

I have gone through many iterations in the last few days. I have pulled Anchor usage out altogether at one point. After failing for some time with NetworkTransforms, I wrote my own transform sync class with a position/rotation as well as localposition/localrotation. I will give your recommendation a go. I am not sure that I have had all of those conditions at the same time.

darax commented 7 years ago

So regarding the generic network transmitter, I doubt it is interfering with unity's authority system. But I do believe that the authority system is messing with you. :)

If you are working in the RS2 branch, I've added a couple of scripts that I think address your issue. First is UNETSharedHologram, second is a function added to PlayerController.cs, SendSharedTransform. The way this works is the UNETSharedHologram script routes it's request to be moved through the player controller (which will have local player authority) to trigger a command on the host that will actually move the object for everyone.

Here is what is in PlayerController.cs [Command] private void CmdSendSharedTransform(GameObject target, Vector3 pos, Quaternion rot) { UNetSharedHologram ush = target.GetComponent(); ush.CmdTransform(pos, rot); }

    /// <summary>
    /// For sending transforms for holograms which do not frequently change.
    /// </summary>
    /// <param name="target">The shared hologram (must have a </param>
    /// <param name="pos"></param>
    /// <param name="rot"></param>
    public void SendSharedTransform(GameObject target, Vector3 pos, Quaternion rot)
    {
        if (isLocalPlayer)
        {
            CmdSendSharedTransform(target, pos, rot);
        }
    }

and the important stuff in UNetSharedHologram

///

/// The position relative to the shared world anchor. /// [SyncVar(hook="xformchange")] private Vector3 localPosition;

void xformchange(Vector3 update)
{

    localPosition = update;

}
/// <summary>
/// The rotation relative to the shared world anchor.
/// </summary>
[SyncVar]
private Quaternion localRotation;

/// <summary>
/// Sets the localPosition and localRotation on clients.
/// </summary>
/// <param name="postion">the localPosition to set</param>
/// <param name="rotation">the localRotation to set</param>
[Command]
public void CmdTransform(Vector3 postion, Quaternion rotation)
{
    if (!isLocalPlayer)
    {
        localPosition = postion;
        localRotation = rotation;
    }
}

bool Moving = false;
int layerMask;
InputManager inputManager;
public Vector3 movementOffset = Vector3.zero;
bool isOpaque;

// Use this for initialization
void Start ()
{
    isOpaque = UnityEngine.VR.WSA.HolographicSettings.IsDisplayOpaque;
    transform.SetParent(SharedCollection.Instance.transform, true);
    if (isServer)
    {
        localPosition = transform.localPosition;
        localRotation = transform.localRotation;
    }

    layerMask = HoloToolkit.Unity.SpatialMapping.SpatialMappingManager.Instance.LayerMask;
    inputManager = InputManager.Instance;

}

These scripts assume the shared object is parented to the common world anchor established by WorldAnchorManager.

Subere23 commented 7 years ago

I found a hack of a workaround. But I will look at this solution. Thanks

Subere23 commented 7 years ago

I worked on this for some time and never could get the spawned object to be !isLocalPlayer.And then hit the ohh duh moment.

For anyone that comes across this in the future. This solution requires the main object to have the shared worldAnchor which does not happen in Unity editor at this point. So it has to be tested on the HoloLens or other compatible mixed reality device.

Subere23 commented 7 years ago

The one issue I am running into, I did not catch because I only have one head, is that the transform is not actually being synced real-time currently. When the user air taps to release the object and the anchor is set, the object then moves on the other client's machines. So the are updating and the shared syncing is perfect, just not transitioning currently. Just to be clear it appears that the transforms are syncing based on the reapplication of the world anchor. That or when the user A air taps.

I did not adopt the entirety of the RS2 HTK because I do not have the special version of 5.6.1p1 - **** that is required. And that could possibly be the issue getting this solution to work correctly.

That said, I did just get the email from the Windows Mixed Reality Dev team saying that my Acer dev kit will be shipping soon, so hopefully, that will be alleviated shortly.

Either way, I will see if I can get any luck on a real-time updating fix.

Ziugy commented 7 years ago

A WorldAnchor is an agreement between HoloLenses on a real-world location. Removing the WorldAnchor means you will not be able to communicate correctly with the others in the shared experience about transforms anymore.

My suggestion would be that you have a root GameObject that always has a WorldAnchor; never removed or moved. Any object you want to pick up and move would be either located under, or transformed into, this root. You could still have your placeable GameObjects create their own WorldAnchor, but you will need to do work parenting / unparenting to the root while moving them if you're wanting the transform tracked by the others in the shared experience.

Does this help? I can go into more detail on parts that aren't making sense.

Subere23 commented 7 years ago

That is what I have going on. A root object that is anchored and I am manipulating objects that are children of that object. The only time the children objects sync the transform is when we reapply that child anchor. You think parenting/unparenting will enable the synced transform?

Ziugy commented 7 years ago

I would try leaving off the WorldAnchors on the children of the root, as a test. A single WorldAnchor will be enough unless the distance between the children and the root is over many meters. I'm not sure what happens in regards to a hierarchy of WorldAnchors. Thus my suggestion of parenting / unparenting.

The code from @darax will work for your Player prefab, but you may be running into other problems if the objects your moving do not have authority by that client to be moved. You may have to change isLocalPlayer to hasAuthority in cases too.

Subere23 commented 7 years ago

I got it sorted. UNetSharedHologram was updating the transform in the Oninputclicked function, not the update function. I just needed to pay a little more attention to it :)

StephenHodgson commented 7 years ago

Going to close this. It's probably been archived by google by now.

smhk commented 6 years ago

Important .. for 2018 ..

we determined

There is some flakiness with NetworkTransform if you are using localhost during development, perhaps particularly on Mac.

it's a real PITA. Be sure to test on normal LAN with a few machines. Hope it helps someone.