示例#1
0
    public SceneLoader(SyncNode node)
    {
        this.node = node;

        typeEstimator = new MimeTypeEstimator(Settings.Instance.MimeTypesPath);
        sceneFileDir  = Path.GetDirectoryName(Path.GetFullPath(Settings.Instance.SceneFile));
    }
示例#2
0
    public override void Setup(SyncObject syncObject)
    {
        obj  = syncObject;
        node = obj.Node;

        obj.RegisterEventHandler("collisionStart", OnCollisionStart);
        obj.WriteDebugLog("objectMoveButton", $"Registered event handlers");
    }
示例#3
0
    public override void Setup(SyncObject syncObject)
    {
        obj  = syncObject;
        node = obj.Node;

        obj.RegisterEventHandler("grab", OnGrab);
        obj.RegisterEventHandler("ungrab", OnUngrab);
        obj.WriteDebugLog("grabbable", $"Registered event handlers");
    }
示例#4
0
    // Start is called before the first frame update
    async void Start()
    {
        if (Application.isEditor)
        {
            // Load settings (because Startup scene is probably not used in Editor)
            SettingsManager.Instance.InitializeSettings();
            // Override some StreamingAssets-related settings
            Settings.Instance.MimeTypesPath = Application.streamingAssetsPath + "/config/mime.types";
        }

        if (IsServer)
        {
            Node = new SyncServer(Settings.Instance.SignalerUrlForServer);
        }
        else
        {
            Node = new SyncClient(Settings.Instance.SignalerUrlForClient);
        }

        Node.ObjectCreated += OnObjectCreated;
        Node.ObjectDeleted += OnObjectDeleted;

        RegisterTags();

        try
        {
            await Node.Initialize();
        }
        catch (SignalingException e)
        {
            await FadeLoadingScreen();

            await GameObject.Find("LocalPlayer")?.GetComponent <Menu>()?.ShowDialog(
                "Signaling Error",
                e.ToString()
                );

            Application.Quit(); // Note: Does not stop in Unity Editor. https://docs.unity3d.com/ja/current/ScriptReference/Application.html
            return;
        }
        catch (ConnectionException e)
        {
            await FadeLoadingScreen();

            await GameObject.Find("LocalPlayer")?.GetComponent <Menu>()?.ShowDialog(
                "Connection Error",
                e.ToString()
                );

            Application.Quit(); // Note: Does not stop in Unity Editor. https://docs.unity3d.com/ja/current/ScriptReference/Application.html
            return;
        }

        Ready = true;

        if (IsServer)
        {
            // World object has a tag called "world" (WorldTag.cs)
            // TODO: Move to core?
            Node.Objects[SyncNode.WorldObjectId].SetField(
                "tags",
                new Sequence(new List <IValue> {
                new Primitive <string>("world")
            }));

            // Load scene from YAML
            var loader = new SceneLoader(Node);
            await loader.LoadFile(Settings.Instance.SceneFile);
        }

        // Add objects defined in Unity scene, such as player avatar
        foreach (GameObject obj in OriginalObjects)
        {
            var id = await Node.CreateObject();

            OriginalObjectIds.Add(id);
            if (GameObjects.ContainsKey(id))
            {
                // Delete provisional GameObject created in OnObjectCreated
                ReplaceObject(Node.Objects[id], obj);
            }
            // With SynchronizationContext of Unity, the line below will run in main thread.
            // https://qiita.com/toRisouP/items/a2c1bb1b0c4f73366bc6
            SetupObjectSync(obj, Node.Objects[id]);
        }
    }
示例#5
0
    // Called by ObjectSync when become ready
    async void OnSyncReady()
    {
        Debug.Log("OnSyncReady");

        SyncObject obj  = GetComponent <ObjectSync>().SyncObject;
        SyncNode   node = GetComponent <ObjectSync>().Node;

        obj.BeforeSync += OnBeforeSync;
        obj.AfterSync  += OnAfterSync;
        obj.RegisterFieldUpdateHandler("leftHand", OnLeftHandUpdated);
        obj.RegisterFieldUpdateHandler("rightHand", OnRightHandUpdated);
        obj.RegisterFieldUpdateHandler("mouseGrabber", OnMouseGrabberUpdated);

        OnLeftHandUpdated();
        OnRightHandUpdated();
        OnMouseGrabberUpdated();

        Blob vrmBlob;

        if (GetComponent <ObjectSync>().IsOriginal)
        {
            byte[] vrmData = File.ReadAllBytes(Settings.Instance.AvatarPath);
            // Use MIME type for GLTF binary https://www.iana.org/assignments/media-types/model/gltf-binary
            vrmBlob = new Blob(vrmData, "model/gltf-binary");
            BlobHandle vrmHandle = vrmBlob.GenerateHandle();
            node.WriteBlob(vrmHandle, vrmBlob);
            obj.SetField("vrm", vrmHandle);
        }
        else
        {
            while (!obj.HasField("vrm") || !(obj.GetField("vrm") is BlobHandle))
            {
                obj.WriteDebugLog("PlayerAvatar", "Field vrm not ready");
                await UniTask.WaitForFixedUpdate();
            }
            BlobHandle blobHandle = (BlobHandle)obj.GetField("vrm");
            vrmBlob = await node.ReadBlob(blobHandle);
        }

        // Disable collision detection (and character control) during VRM load
        // When the avatar collides with something during creation,
        // it goes to wrong position (e.g. floating).
        // Note: CharacterController inherits Collider.
        //  (See https://docs.unity3d.com/2019.3/Documentation/ScriptReference/CharacterController.html )
        GetComponent <CharacterController>().enabled = false;

        // Load VRM from byte array
        // https://github.com/vrm-c/UniVRM/wiki/Runtime-import
        // https://qiita.com/sh_akira/items/8155e4b69107c2a7ede6
        ctx      = new VRMImporterContext();
        ctx.Root = new GameObject();    // VRM is loaded as a separate object
        ctx.ParseGlb(vrmBlob.Data);

        var meta = ctx.ReadMeta();

        obj.WriteLog("PlayerAvatar", $"Loading VRM {meta.Title} created by {meta.Author} ({meta.ContactInformation})");
        obj.WriteLog("PlayerAvatar", $"AllowedUser={meta.AllowedUser}, ViolentUsage={meta.ViolentUssage}");
        obj.WriteLog("PlayerAvatar", $"SexualUsage={meta.SexualUssage}, CommercialUsage={meta.CommercialUssage}");
        obj.WriteLog("PlayerAvatar", $"OtherPermissionUrl={meta.OtherPermissionUrl}");
        obj.WriteLog("PlayerAvatar", $"LicenseType={meta.LicenseType}");
        obj.WriteLog("PlayerAvatar", $"OtherLicenseUrl={meta.OtherLicenseUrl}");

        await ctx.LoadAsyncTask();

        ctx.EnableUpdateWhenOffscreen();
        ctx.ShowMeshes();

        // Enable collision (and character controller) again (see the disabling line above)
        GetComponent <CharacterController>().enabled = true;

        // Move VRM avatar inside this gameObject
        ctx.Root.transform.SetParent(transform);
        ctx.Root.transform.localPosition = Vector3.zero;
        ctx.Root.transform.localRotation = Quaternion.identity;

        GetComponent <Animator>().avatar = ctx.Root.GetComponent <Animator>().avatar;

        obj.WriteLog("PlayerAvatar", $"VRM loaded");

        if (GetComponent <ObjectSync>().IsOriginal)
        {
            // Set up first person view (do not display avatar of the player)
            //  https://vrm.dev/en/univrm/components/univrm_firstperson/
            //  https://vrm.dev/en/dev/univrm-0.xx/programming/univrm_use_firstperson/
            var fp = GetComponentInChildren <VRMFirstPerson>();
            fp.Setup();
            if (XRRig != null)
            {
                XRRig.transform.position = fp.FirstPersonBone.position + fp.FirstPersonBone.rotation * fp.FirstPersonOffset;
                XRRig.transform.rotation = transform.rotation;  // face forward
                // Do not render layer "VRMThirdPersonOnly" on first person camera
                xrCamera.cullingMask &= ~LayerMask.GetMask("VRMThirdPersonOnly");
                SetHeadShadow();
            }
            if (ThirdPersonCamera != null)
            {
                // Do not render layer "VRMFirstPersonOnly" on third person camera
                ThirdPersonCamera.cullingMask &= ~LayerMask.GetMask("VRMFirstPersonOnly");
            }

            // Left hand
            if (leftController.HasValue)
            {
                // If left hand device is present
                var leftId = await node.CreateObject();

                leftHandObj = node.Objects[leftId];
                leftHandObj.SetField("parent", obj.GetObjectRef());
                leftHandObj.SetField("tags", new Sequence(new IValue[] {
                    new Primitive <string>("constantVelocity"),
                    new Primitive <string>("collider")
                }));
                obj.SetField("leftHand", leftHandObj.GetObjectRef());
            }
            // Right hand
            if (rightController.HasValue)
            {
                // If right hand device is present
                var rightId = await node.CreateObject();

                rightHandObj = node.Objects[rightId];
                rightHandObj.SetField("parent", obj.GetObjectRef());
                rightHandObj.SetField("tags", new Sequence(new IValue[] {
                    new Primitive <string>("constantVelocity"),
                    new Primitive <string>("collider")
                }));
                obj.SetField("rightHand", rightHandObj.GetObjectRef());
            }
            // Mouse
            var mouseGrabberId = await node.CreateObject();

            mouseGrabberObj = node.Objects[mouseGrabberId];
            mouseGrabberObj.SetField("parent", obj.GetObjectRef());
            mouseGrabberObj.SetField("tags", new Sequence(new IValue[] {
                new Primitive <string>("constantVelocity"),
                new Primitive <string>("collider")
            }));
            obj.SetField("mouseGrabber", mouseGrabberObj.GetObjectRef());
        }
    }
示例#6
0
 public SyncStatus PutFileNode(SyncNode node)
 {
     object[] results = this.Invoke("PutFileNode", new object[] {
                 node});
     return ((SyncStatus)(results[0]));
 }
示例#7
0
 /// <remarks/>
 public System.IAsyncResult BeginPutFileNode(SyncNode node, System.AsyncCallback callback, object asyncState)
 {
     return this.BeginInvoke("PutFileNode", new object[] {
                 node}, callback, asyncState);
 }