/// <summary> /// Ensures that a MARS Scene has all required components and configuration /// </summary> public static void EnsureRuntimeState(Transform overrideUserRef = null) { // Make sure we have a MARS Session if (Instance == null) { Instance = GameObjectUtils.ExhaustiveComponentSearch <MARSSession>(null); } if (MARSSceneModule.instance.BlockEnsureSession) { return; } // Early out if nothing needs to change, otherwise we add an unnecessary undo group if (SessionConfigured(Instance)) { return; } using (var undoBlock = new UndoBlock("Ensure MARS Runtime State")) { if (Instance == null) { CreateSession(undoBlock); DirtySimulatableSceneIfNeeded(); } else { undoBlock.RecordObject(Instance.gameObject); } if (!TestMode) { EnsureSessionConfigured(Instance, undoBlock, overrideUserRef); } } }
static void EnsureSessionConfigured(MARSSession session, UndoBlock undoBlock, Transform overrideUserRef = null) { var sessionObject = session.gameObject; var sessionTransform = session.transform; var changed = false; // Make sure we have a properly configured MARS Camera if (!TestMode && session.m_CameraReference == null) { var marsCameraRef = GameObjectUtils.ExhaustiveComponentSearch <MARSCamera>(sessionObject); // If we can't find a MARS camera, get the main camera and create one on that if (marsCameraRef == null) { LogRuntimeIssue("MARSCamera not present in the scene. Adding one to the main camera."); var createdNewCamera = false; var cameraRef = GameObjectUtils.ExhaustiveTaggedComponentSearch <Camera>(sessionObject, k_CameraTag); if (cameraRef == null) { cameraRef = CreateCamera(sessionTransform, undoBlock); createdNewCamera = true; } marsCameraRef = undoBlock.AddComponent <MARSCamera>(cameraRef.gameObject); if (!createdNewCamera) { var nearPlane = cameraRef.nearClipPlane; var cameraParent = cameraRef.transform.parent; if (cameraParent == null) { cameraParent = sessionTransform; } var worldScale = cameraParent.localScale.x; var scaledMaxNearPlane = k_MaxNearPlane * worldScale; if (nearPlane > scaledMaxNearPlane) { LogRuntimeIssue("Camera near clip plane is greater than the recommended distance. " + $"Setting near plane from {nearPlane} to {scaledMaxNearPlane}."); undoBlock.RecordObject(cameraRef); cameraRef.nearClipPlane = scaledMaxNearPlane; } } } session.m_CameraReference = marsCameraRef; changed = true; } const string correctBrokenSessionMessage = "If you have not customized the MARSSession game object, just delete " + "the object and go to Create > MARS > Session."; var cameraTrans = session.m_CameraReference.transform; if (!TestMode && cameraTrans.GetComponentInParent <MARSSession>() == null) { const string cameraParentRequirementMessage = "MARSCamera must have a MARSSession object in its list of parents."; var canReparent = true; #if INCLUDE_AR_FOUNDATION if (cameraTrans.GetComponentInParent <ARSessionOrigin>() != null) { canReparent = false; Debug.LogError($"{cameraParentRequirementMessage} Please make sure the MARSSession component " + $"is on the same game object as the ARSessionOrigin. {correctBrokenSessionMessage}"); } #endif if (canReparent) { LogRuntimeIssue($"{cameraParentRequirementMessage} Re-parenting."); var cameraParent = cameraTrans.parent; if (cameraParent) { sessionTransform.position = cameraParent.position; sessionTransform.rotation = cameraParent.rotation; sessionTransform.localScale = cameraParent.localScale; } undoBlock.SetTransformParent(cameraTrans, sessionTransform); changed = true; } } // Look for the user object, if it's not in the scene, make a new one var userRef = session.m_UserReference; if (!TestMode && userRef == null) { userRef = session.m_CameraReference.transform.Find(k_UserName); if (userRef == null) { if (overrideUserRef == null) { userRef = GameObjectUtils.Instantiate(MARSRuntimePrefabs.instance.UserPrefab).transform; } else { userRef = overrideUserRef; } userRef.name = k_UserName; userRef.parent = session.m_CameraReference.transform; userRef.localPosition = Vector3.zero; userRef.localRotation = Quaternion.identity; userRef.localScale = Vector3.one; undoBlock.RegisterCreatedObject(userRef.gameObject); } session.m_UserReference = userRef; changed = true; } // One more bizarre scenario to catch - the MARS Session and Camera being *one* object. // We can't just delete the MARS Session since the user might have other scripts there, so we just throw up a warning telling them to fix things manually if (!TestMode && session.m_CameraReference.transform == sessionTransform) { Debug.LogError("The MARS Session should be a parent of the MARSCamera, *NOT* the same object! " + $"Please correct this in your scene! {correctBrokenSessionMessage}"); } if (sessionObject.activeInHierarchy == false) { LogRuntimeIssue("There is a MARS Session object in your scene that is *not* active. Running your scene with an inactive MARS Session will cause problems."); sessionObject.SetActive(true); changed = true; } var cameraObject = session.cameraReference.gameObject; if (cameraObject.activeInHierarchy == false) { LogRuntimeIssue("There is a MARS Camera GameObject in your scene that is *not* active. " + "Re-enabling here, as running your scene with an inactive MARS Camera would cause problems."); cameraObject.SetActive(true); changed = true; } if (changed) { DirtySimulatableSceneIfNeeded(); } }