public SceneLoader(SyncNode node) { this.node = node; typeEstimator = new MimeTypeEstimator(Settings.Instance.MimeTypesPath); sceneFileDir = Path.GetDirectoryName(Path.GetFullPath(Settings.Instance.SceneFile)); }
public override void Setup(SyncObject syncObject) { obj = syncObject; node = obj.Node; obj.RegisterEventHandler("collisionStart", OnCollisionStart); obj.WriteDebugLog("objectMoveButton", $"Registered event handlers"); }
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"); }
// 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]); } }
// 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()); } }
public SyncStatus PutFileNode(SyncNode node) { object[] results = this.Invoke("PutFileNode", new object[] { node}); return ((SyncStatus)(results[0])); }
/// <remarks/> public System.IAsyncResult BeginPutFileNode(SyncNode node, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("PutFileNode", new object[] { node}, callback, asyncState); }