• No results found

Scene downloads

In document Remote vessel survey using VR (sider 63-66)

If the application is to be used by multiple users each surveying different environments, the file size of the application will quickly become large. A usual model generated from a LiDAR scan takes up between 200 and 1500 MB depending on the scan resolution and the size of the environment being scanned. When a model is exported to Unity as an.obj file, this file size is significantly reduced.

When Unity builds a project, project files can be further compressed by LZ4 or LZ4HC compression which significantly reduces the applications size. The difference between the two compression methods are their speed and compression rate. LZ4 is faster than LZ4HC, but LZ4HC has a higher compression rate. If enough scans are added, the application will still have a significant file size. To help reduce file size, the application should allow virtual environments to be downloaded from within the application. The maximum size of the application being built on the Oculus Quest is 1 GB (Oculus, 2021b). This emphasises the importance of being able to reduce the file size of the application, and being able to download additional scenes through extensions. By uploading pre-built and compressed Unity scenes, users can download the environments they need which significantly reduces the total file size of the application. Since the uploaded Unity scenes will be compressed, the download size for the individual scenes will be reasonably small and mainly less than 100 MB.

4.8.1 Creating Asset bundles

An asset bundle is is an archive file that contains platform-specific non-code Assets such as Models, Textures, Prefabs, and entire scenes that Unity can load at run time. In order to be able to download and run a scene at runtime, the downloaded scene must be a pre-built executable file.

Because the downloaded file has to be executable, the downloaded file must be built for the specific target downloading and running it. Therefore, a PC and an Android based device such as the Oculus Quest 2 requires two different versions of an assetbundle in order to be able to run it. Since the Oculus Quest 2 can be run either standalone or via a connected PC (discussed in further detail in section 3.2), an asset bundled scene must be built two times, one for each platform.

In order to provide a quick way to pre-build Unity scenes, a Unity editor extension is implemented with a script calledCreateAssetBundle.cs. TheCreateAssetBundle.csscript sets up an assetbundle directory within the Unity environment and uses the UnityBuildPipeline class to build an asset-bundle of a specified object. The BuildPipeline.BuildAssetBundles() function enables a user to specify build target, stored directory and other asset bundle options for an assetbundle. Once the CreateAssetBundle.csscript is implemented, it is possible to create assetbundles of desired objects directly in the Unity inspector. After a desired environment is pre-built for both platforms and placed in two individual assetbundles, they are ready to be extracted from the Unity project. The assetbundles can then be uploaded to any online platform like Google Drive or Azure. By providing the direct download link to the uploaded assetbundles, it is possible to access the uploaded scenes.

4.8.2 Scene structure

To keep track of which scenes are available for download online and which are already part of the application build, changes are made to the SceneList.cs script and SceneList object. Instead of just storing the scene name, a scene object in theSceneList.cs script now also stores the download URL for both the Android and PC version of the assetbundle and two boolean variables indicating if the scene object is part of the application build and whether it is downloaded or not. An example of a public scene object in the sceneList which is visible in the Unity inspector window can be seen in Figure 4.18.

Three new functions are implemented in theSceneList.cs script. These areCheckAssetBundles(), CheckBuiltScenes() and RefreshSceneList(). The CheckAssetBundles() function iterates through the SceneList and constructs a filepath for each scene which corresponds to the filepath where that scene would be stored if it was downloaded. If the function finds that the filepath exists, it means that the selected scene has in fact been downloaded and is therefore not a part of the

Figure 4.18: A Scene object in the public Scene List. A Scene object has both a display name and a scene name in order to be able to display a different name for a scene in the menu than what its name string reference is.

build. The isPartOfBuild boolean variable for that scene is therefore automatically set to false and itsisDownloaded variable is set to true. If the filepath does not exist, the scenesisDownloaded property is set to false. TheCheckBuiltScenes() function gets the string name of all scenes in the application build. The function then iterates through the scene list and compares them to the string names of the application in the build. If the names match, it means that the selected scene is part of the application build. It’s IsPartOfBuild variable is then set to true. If no match is found for a scene, itsIsPartOfBuild variable is set to false. The RefreshSceneList() function is used to get an updated status on the variables of the scenes in the scene list. In order to do this, theRefreshSceneList() function runs both the CheckAssetBundles() and theCheckBuiltScenes() function.

After the RefreshSceneList() function has been run, a scene in the scene list is in one of three different states. For each state a different action must be taken. The first state is if a scene is part of the application build. If this is the case, no new action has to be taken. It’s button icon will be generated as before in the scene selection menu view and it will be loaded as before when it is selected. The second state a scene can be in is if it is not a part of the build and it is not downloaded. If this is the case, the scene button icon in the scene selection menu view should have a different color indicating that it is unavailable and have a button next to it that should trigger a download for that scene. The third state a scene can be in is if the scene is not a part of the build but it is downloaded. If this is the case, the scene button icon in the scene selection menu view should look similar to the ones that are part of the build. In addition, it should have a button next to it that can be pressed in order to delete the downloaded version of the scene. If a scene is in the third state and a user wants to load it, it can not be loaded the same way as scenes that are part of the build since a downloaded scene is stored in a separate folder outside the built application file.

The different scene button icons generated depending on scene state can be seen in Figure 4.19.

4.8.3 Downloading exported scenes

The SceneList object with the SceneList.cs script will serve as an extra security measure by providing access control. By manipulating theSceneList object of the application, one can easily decide which scenes should be available to different users. If for instance two different customers wants to use the application, they will both be able to use the same features but have access to completely different scenes depending on their version of theSceneList object in their application.

TheSceneList object can therefore help protect sensitive scans by only providing access to them for approved users. In addition, theSceneList object makes it easy to add or remove scenes from an existing application build.

When a user presses the download icon on a scan in the scene selection menu view, the icon will call a function in AvailableScenesManager.cs called DownloadScan() which initiates a coroutine.

Figure 4.19: The three different generated button types. Scenes part of the build have no icon next to them. Scenes available for download have a download icon next to them which display a download progress text field when pressed. Downloaded scenes can be deleted by pressing the red cross icon next to them.

A coroutine (discussed in section 2.4.2) is a function that can suspend its execution (yield) un-til the given yield instruction finishes. The coroutine stores the string name of the scene whose download button was pressed. It then compares the stored string to the scene list. When the coroutine finds a match, it will run theApplication.RuntimePlatform()function which returns the platform the application is running on. The coroutine then creates a GET UnityWebRequest() to either the Android or PC download URL of the scene, depending on the result from Applica-tion.RuntimePlatform(). ADownloadHandler object is added to the Web request to define how it should handle the HTTP response body data received from it. The GET request is then sent and the coroutine suspends its execution until it gets a result from the request. When the coroutine gets a result it runs aSave() function which creates a directory on the device running the application and uses theFile.WriteAllBytes() function to store the received data. All downloaded scenes will be stored at the pathApplication.persistentDataPath/AssetData/sceneName.unity. The Applic-ation.persistentDataPathis a read only string that contains the path to a persistent data directory.

The filepath of a downloaded assetbundle containing a scene therefore only depends on the name of the scene. After the assetbundle is downloaded, the RefreshSceneList() is run to update the status of the downloaded scene in the application scene list. New icons for the scene buttons in the scene selection menu view is then generated to display the changes using theGenerateMenuIcons() function.

In order to provide user feedback regarding the download status, a new coroutine called Download-Progress() is created. It is called just before the GETUnityWebRequest() is sent. The coroutine takes the web request as an input and displays its download status in a text field on the scene button icon while it is downloading.

4.8.4 Loading and deleting assetbundled scenes

If a user wants to load a downloaded scene, it is not possible to do so using the method used on scenes that are part of the application build. This is because the downloaded scenes are stored in a separate directory outside of the built executable file that is the application. In order to load a downloaded scene, a coroutine calledLoadObject()is implemented. TheLoadObject() coroutine takes the scene name of the scene to be loaded as an input. It recreates its filepath from the scene name and starts loading it using theAssetBundle.LoadFromFileAsync() function which loads the assetbundle asynchronously. The assetbundle is loaded asynchronously to avoid the application freezing while the assetbundle is being loaded. TheLoadObject()coroutine suspends its execution until the load is complete. Once the assetbundle is loaded, theLoadObject()coroutine extracts the scene from the assetbundle using theGetAllScenePaths() function which returns the scene asset paths within the assetBundle. The scene can then be loaded using theSceneManager.LoadScene function.

To delete a downloaded scene, a coroutine calledDeleteScan()is implemented. When a user presses the delete icon on the scene button in the scene selection menu view,DeleteScan() is run. The coroutine uses the string name of the scene whose delete icon was pressed to recreate its file path.

TheFile.Delete()function is then run which deletes the file at its input file path. To remove the assetbundle content that has been cached by the application, theCaching.ClearCache()function is run. After the assetbundle containing the scene has been deleted, theRefreshSceneList()function is run to update the status of the deleted scene in the application scene list. New icons for the scene buttons in the scene selection menu view is then generated to display the changes.

In document Remote vessel survey using VR (sider 63-66)