├── .gitignore ├── README.md ├── XcodePostBuild.cs ├── demo ├── unity │ ├── .gitignore │ ├── Assets │ │ ├── Demo.unity │ │ ├── Demo.unity.meta │ │ ├── Scripts.meta │ │ └── Scripts │ │ │ ├── CubeController.cs │ │ │ ├── CubeController.cs.meta │ │ │ ├── Editor.meta │ │ │ ├── Editor │ │ │ ├── XcodePostBuild.cs │ │ │ └── XcodePostBuild.cs.meta │ │ │ ├── NativeBridge.cs │ │ │ └── NativeBridge.cs.meta │ ├── ProjectSettings │ │ ├── AudioManager.asset │ │ ├── ClusterInputManager.asset │ │ ├── DynamicsManager.asset │ │ ├── EditorBuildSettings.asset │ │ ├── EditorSettings.asset │ │ ├── GraphicsSettings.asset │ │ ├── InputManager.asset │ │ ├── NavMeshAreas.asset │ │ ├── NetworkManager.asset │ │ ├── Physics2DSettings.asset │ │ ├── ProjectSettings.asset │ │ ├── ProjectVersion.txt │ │ ├── QualitySettings.asset │ │ ├── TagManager.asset │ │ ├── TimeManager.asset │ │ └── UnityConnectSettings.asset │ └── UnityPackageManager │ │ └── manifest.json └── xcode │ ├── .gitignore │ ├── DemoApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── DemoApp │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── Unity │ ├── Bridging-Header.h │ ├── Unity.xcconfig │ ├── UnityUtils.h │ ├── UnityUtils.mm │ └── rsync_exclude │ └── ViewController.swift └── images ├── demo.gif ├── unity_configuration_file.png ├── xcode_build_script_1.png ├── xcode_build_script_2.png └── xcode_source_tree.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Integrating Unity Project into Xcode Swift Project 2 | 3 | This repo contains a demo Xcode 9.1 iOS project (Swift 4.0) that builds a single view app with an embeded Unity scene 4 | (Unity 2017.2.0f3) with two-way communication between Unity and Swift. It contains automation script that could be 5 | easily re-used in existing Unity and Swift projects. 6 | 7 | ![Demo Video](https://github.com/jiulongw/swift-unity/raw/master/images/demo.gif) 8 | 9 | This would not be possible without [tutorial by BLITZ][1] and [video by the-nerd Frederik Jacques][2]. Several updates 10 | are applied to fit latest Xcode and Unity releases. 11 | 12 | ## Compatibility 13 | ### Unity 14 | * 2017.1.1 15 | * 2017.1.2 16 | * 2017.2.0 17 | * 2017.3.0 18 | * 2017.3.1 19 | * 2017.4.1 20 | * 2017.4.2 21 | 22 | ### Xcode 23 | * Xcode 9.0 24 | * Xcode 9.1 25 | * Xcode 9.2 26 | 27 | ## FAQ 28 | * [Exports.xcconfig file missing][6] 29 | * [Xcode compile error when using .Net 4.6 backend in Unity][9] 30 | * [Entry point (`_main`) undefined][10] 31 | 32 | ## Why did I create this 33 | I like to automate things when I find myself doing the same thing several times, and potentially over and over again. 34 | If you are (like I am) tired of these tedious steps every time you export a new Unity build, you will love this 35 | automation. Once integrated, Swift project gets updated automatically everytime a new Unity build is exported. 36 | 37 | ## How to run the demo 38 | First open Unity project, open `Demo` scene, open `Build Settings` and switch to iOS platform, then hit `Build`. You 39 | can put output anywhere but better put it to some temporary folder such as `/tmp`. 40 | 41 | Once build succeeded, open Xcode project, select target device (Unity does not support `x86_64`) and hit 42 | `Build and then run`. You might need to change bundle identifier if Xcode has problem creating provisioning profile. 43 | 44 | ## How to use it in other projects 45 | ### Unity 46 | Copy this [post build script][5] to your Unity project's `Assets` folder. Put anywhere you like but since this is an 47 | editor script, Unity requires it to be under a folder named `Editor`. 48 | 49 | Open the script and follow the instructions in the comments. You need to tell it the path to your Swift project and 50 | the name of your awesome product. 51 | 52 | ```cs 53 | /// 54 | /// Path to the root directory of Xcode project. 55 | /// This should point to the directory of '${XcodeProjectName}.xcodeproj'. 56 | /// It is recommended to use relative path here. 57 | /// Current directory is the root directory of this Unity project, i.e. the directory of 'Assets' folder. 58 | /// Sample value: "../xcode" 59 | /// 60 | private const string XcodeProjectRoot = ; 61 | 62 | /// 63 | /// Name of the Xcode project. 64 | /// This script looks for '${XcodeProjectName} + ".xcodeproj"' under '${XcodeProjectRoot}'. 65 | /// Sample value: "DemoApp" 66 | /// 67 | private const string XcodeProjectName = ; 68 | ``` 69 | 70 | You're done with Unity part! 71 | 72 | ### Xcode 73 | Xcode side requires a bit more *one time* effort. 74 | 75 | 1. Copy entire [Unity][7] folder to the root of your Swift project and add it to Xcode source tree. Make sure all the 76 | `.mm` files are added to correct build target. 77 | 78 | ![Xcode source tree](https://github.com/jiulongw/swift-unity/raw/master/images/xcode_source_tree.png) 79 | 80 | 2. Add following lines to the .gitignore file in the same directory of your `.xcodeproj` entry. If you don't have one 81 | there, create one or merge it to your higher level git ignore file with proper updates to the paths. 82 | 83 | ``` 84 | # This file is generated by Unity post build action 85 | DemoApp/Unity/Exports.xcconfig 86 | 87 | # Files under Libraries will be copied from Unity build during Xcode build 88 | DemoApp/Unity/Libraries/ 89 | 90 | # Files under Classes will be copied from Unity build during Xcode build 91 | DemoApp/Unity/Classes/ 92 | ``` 93 | 94 | 3. Select `Unity` as project configuration file. If you already have your own, merge `Unity/Unity.xcconfig` to your own. 95 | 96 | ![Unity configuration file](https://github.com/jiulongw/swift-unity/raw/master/images/unity_configuration_file.png) 97 | 98 | 4. If you don't have Objective-C bridging header file, you can skip this. Otherwise, merge `Unity/Bridging-Header.h` 99 | to your own bridging header and comment out following lines in `Unity/Unity.xcconfig`: 100 | ``` 101 | SWIFT_OBJC_BRIDGING_HEADER = $(PRODUCT_NAME)/Unity/Bridging-Header.h; 102 | SWIFT_PRECOMPILE_BRIDGING_HEADER = YES; 103 | ``` 104 | 105 | 5. Add following build scripts to your Xcode build target. You can copy from `DemoApp` settings. Note the order. If your project name has space(s) in it, surround the `$PRODUCT_NAME` with double quote. 106 | 107 | ```sh 108 | echo "Syncing code from $UNITY_IOS_EXPORT_PATH..." 109 | rsync -rc --exclude-from="$PRODUCT_NAME"/Unity/rsync_exclude --delete $UNITY_IOS_EXPORT_PATH/Classes/ "$PRODUCT_NAME"/Unity/Classes/ 110 | rsync -rc --exclude-from="$PRODUCT_NAME"/Unity/rsync_exclude --delete $UNITY_IOS_EXPORT_PATH/Libraries/ "$PRODUCT_NAME"/Unity/Libraries/ 111 | ``` 112 | ![Xcode build script 1](https://github.com/jiulongw/swift-unity/raw/master/images/xcode_build_script_1.png) 113 | 114 | 115 | ```sh 116 | echo "Syncing data from $UNITY_IOS_EXPORT_PATH..." 117 | rm -rf "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Data" 118 | cp -Rf "$UNITY_IOS_EXPORT_PATH/Data" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Data" 119 | ``` 120 | 121 | ![Xcode build script 2](https://github.com/jiulongw/swift-unity/raw/master/images/xcode_build_script_2.png) 122 | 123 | 6. Update `AppDelegate.swift` to initialize Unity during application start. Follow the [sample AppDelegate code][4]. 124 | 125 | 7. Once Unity is loaded, a `UnityReady` notification will be triggered. Subscribe to that notification, grab Unity 126 | view or view controller and present them as you like. Follow the [sample ViewController code][8]. 127 | ```swift 128 | // Get Unity View 129 | UnityGetGLView() 130 | 131 | // Get Unity View Controller 132 | UnityGetGLViewController() 133 | ``` 134 | Now you should be good to go. Give it a try! 135 | 136 | Note: Building the Unity project for the first time will modify Xcode project file a lot. 137 | It is safe to commit the change into source control as it only performs necessary updates going forward. 138 | 139 | 140 | ## Updates 141 | * 02/19/2018 - Support Unity version 2017.3.1f3. 142 | * 12/22/2017 - Support Unity version 2017.3.0f3. 143 | * 11/15/2017 - Updated demo focusing on reusability. Updated README accordingly. 144 | * 11/2/2017 - Support Unity version from 2017.1.1f1 to 2017.2.0f3. 145 | * 10/25/2017 - Added FAQ about missing Exports.xcconfig file. 146 | * 10/6/2017 - Fix previous known issue that new files generated by Unity are not added to Xcode project automatically. 147 | * 9/26/2017 - Initial commit 148 | 149 | 150 | [1]: https://github.com/blitzagency/ios-unity5 151 | [2]: http://www.the-nerd.be/2015/08/20/a-better-way-to-integrate-unity3d-within-a-native-ios-application/ 152 | [3]: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html 153 | [4]: https://github.com/jiulongw/swift-unity/blob/master/demo/xcode/DemoApp/AppDelegate.swift 154 | [5]: https://github.com/jiulongw/swift-unity/blob/master/XcodePostBuild.cs 155 | [6]: https://github.com/jiulongw/swift-unity/issues/8 156 | [7]: https://github.com/jiulongw/swift-unity/tree/master/demo/xcode/DemoApp/Unity 157 | [8]: https://github.com/jiulongw/swift-unity/blob/master/demo/xcode/DemoApp/ViewController.swift 158 | [9]: https://github.com/jiulongw/swift-unity/issues/31 159 | [10]: https://github.com/jiulongw/swift-unity/issues/17 160 | -------------------------------------------------------------------------------- /XcodePostBuild.cs: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2017 Jiulong Wang 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #if UNITY_IOS 26 | 27 | using System; 28 | using System.Linq; 29 | using System.Collections.Generic; 30 | using System.IO; 31 | using System.Text; 32 | 33 | using UnityEngine; 34 | using UnityEditor; 35 | using UnityEditor.Callbacks; 36 | using UnityEditor.iOS.Xcode; 37 | 38 | /// 39 | /// Adding this post build script to Unity project enables Unity iOS build output to be embedded 40 | /// into existing Xcode Swift project. 41 | /// 42 | /// However, since this script touches Unity iOS build output, you will not be able to use Unity 43 | /// iOS build directly in Xcode. As a result, it is recommended to put Unity iOS build output into 44 | /// a temporary directory that you generally do not touch, such as '/tmp'. 45 | /// 46 | /// In order for this to work, necessary changes to the target Xcode Swift project are needed. 47 | /// Especially the 'AppDelegate.swift' should be modified to properly initialize Unity. 48 | /// See https://github.com/jiulongw/swift-unity for details. 49 | /// 50 | public class XcodePostBuild : EditorWindow 51 | { 52 | /// 53 | /// The version of Unity for which we need to edit Unity's Metal code. 54 | /// 55 | static Version UNITY_VERSION_FOR_METAL_HELPER = ParseUnityVersionNumber("2017.1.1f1"); 56 | 57 | /// 58 | /// The minimum versino of Unity for which we need to edit Unity's splash-screen code. 59 | static Version MIN_UNITY_VERSION_FOR_SPLASH_SCREEN = new Version(2017, 3, 0); 60 | 61 | /// 62 | /// Set to false to disable this post-processor, so you can build proper iOS app projects 63 | /// from the same code base. 64 | /// 65 | private bool enabled = true; 66 | 67 | /// 68 | /// Path to the Xcode project. 69 | /// 70 | private string XcodeProjectPath; 71 | 72 | /// 73 | /// Path to the root directory of Xcode project. 74 | /// This should point to the directory of '${XcodeProjectName}.xcodeproj'. 75 | /// It is recommended to use relative path here. 76 | /// Current directory is the root directory of this Unity project, i.e. the directory that contains the 'Assets' folder. 77 | /// Sample value: "../xcode" 78 | /// 79 | private string XcodeProjectRoot { get { return Path.GetDirectoryName(XcodeProjectPath); } } 80 | 81 | /// 82 | /// Name of the Xcode project. 83 | /// This script looks for '${XcodeProjectName} + ".xcodeproj"' under '${XcodeProjectRoot}'. 84 | /// Sample value: "DemoApp" 85 | /// 86 | private string XcodeProjectName { get { return Path.GetFileNameWithoutExtension(XcodeProjectPath); } } 87 | 88 | 89 | /// 90 | /// The URL to the Git repository where this project originated. 91 | /// 92 | private const string PROJECT_URL = "https://github.com/jiulongw/swift-unity"; 93 | 94 | /// 95 | /// The identifier added to touched file to avoid double edits when building to existing directory without 96 | /// replace existing content. 97 | /// 98 | private const string TOUCH_MARKER = PROJECT_URL + "#v1"; 99 | 100 | /// 101 | /// A GUIStyle object for rendering links. 102 | /// 103 | private static GUIStyle LINK_STYLE; 104 | 105 | /// 106 | /// Creates a menu item in the Tools menu that opens an Editor Window 107 | /// for editing configuration values for the post build process. 108 | /// 109 | [MenuItem("Tools/SwiftUnity")] 110 | public static void ShowConfiguration() 111 | { 112 | GetWindow(); 113 | } 114 | 115 | static string[] XCODEPROJ_FILTER = { "Xcode project files", "xcodeproj" }; 116 | 117 | /// 118 | /// Builds the GUI for the custom editor window for this post process step. 119 | /// Find it under `Tools > Swift-Unity`. 120 | void OnGUI() 121 | { 122 | GUILayout.Label("Swift-Unity", EditorStyles.boldLabel); 123 | 124 | enabled = EditorGUILayout.BeginToggleGroup("Enabled", enabled); 125 | { 126 | ShowProjectDescription(); 127 | ShowSettings(); 128 | } 129 | 130 | ShowRerunButton(); 131 | EditorGUILayout.EndToggleGroup(); 132 | } 133 | 134 | private void ShowSettings() 135 | { 136 | GUILayout.Label("Settings", EditorStyles.boldLabel); 137 | 138 | // If we don't have a directory root for the xcode project, just make a wild 139 | // guess at one to give the user a starting point for navigating to the real one. 140 | if (!Directory.Exists(XcodeProjectPath)) 141 | { 142 | XcodeProjectPath = null; 143 | } 144 | 145 | if (string.IsNullOrEmpty(XcodeProjectPath)) 146 | { 147 | XcodeProjectPath = PathExt.Combine( 148 | Path.GetDirectoryName(Environment.CurrentDirectory), 149 | "Xcode-Project.xcodeproj"); 150 | } 151 | 152 | // Instead of defining the xcode project root and name separately, have the user 153 | // select the .xcodeproj file and then figure them out from there. 154 | var xcodeProjectFile = PathExt.Abs2Rel(XcodeProjectPath); 155 | xcodeProjectFile = EditorGUILayout.TextField("Xcode Project File", xcodeProjectFile); 156 | 157 | if (GUILayout.Button("Browse...")) 158 | { 159 | string userSelection = null; 160 | if (Environment.OSVersion.Platform == PlatformID.MacOSX) 161 | { 162 | userSelection = EditorUtility.OpenFilePanelWithFilters( 163 | "Select Xcode project file", 164 | Path.GetDirectoryName(XcodeProjectPath), 165 | XCODEPROJ_FILTER); 166 | } 167 | else 168 | { 169 | userSelection = EditorUtility.OpenFolderPanel( 170 | "Select Xcode project file", 171 | Path.GetDirectoryName(XcodeProjectPath), 172 | "Xcode-Project.xcodeproj"); 173 | } 174 | 175 | if (!string.IsNullOrEmpty(userSelection)) 176 | { 177 | xcodeProjectFile = PathExt.Abs2Rel(userSelection); 178 | } 179 | } 180 | 181 | XcodeProjectPath = PathExt.Rel2Abs(xcodeProjectFile); 182 | } 183 | 184 | /// 185 | /// TODO: remove this once all the bugs are worked out. This saves us a little 186 | /// time by avoiding having to run the full Unity build every time we want to 187 | /// validate the post process. 188 | /// 189 | private static void ShowRerunButton() 190 | { 191 | // Displaying the current build location serves as a reminder to the user what is going on. 192 | var currentBuildLocation = EditorUserBuildSettings.GetBuildLocation(BuildTarget.iOS); 193 | bool hasBuildLocation = !string.IsNullOrEmpty(currentBuildLocation); 194 | 195 | if (hasBuildLocation) 196 | { 197 | currentBuildLocation = PathExt.Abs2Rel(currentBuildLocation); 198 | } 199 | else 200 | { 201 | currentBuildLocation = ""; 202 | } 203 | 204 | GUILayout.Label( 205 | string.Format( 206 | "Current Build Location: {0}", 207 | currentBuildLocation)); 208 | 209 | if (hasBuildLocation && GUILayout.Button("Run post-build process")) 210 | { 211 | OnPostBuild(BuildTarget.iOS, currentBuildLocation); 212 | } 213 | else 214 | { 215 | GUILayout.Label("Please run build process for iOS."); 216 | } 217 | } 218 | 219 | private static void ShowProjectDescription() 220 | { 221 | GUILayout.Label(@"Enables Unity iOS build output to be embedded into existing Xcode Swift project. 222 | 223 | However, since this script touches Unity iOS build output, you will not be able to use Unity iOS build directly in Xcode. As a result, it is recommended to put Unity iOS build output into a temporary directory that you generally do not touch, such as '/tmp'. 224 | 225 | In order for this to work, necessary changes to the target Xcode Swift project are needed. Especially the 'AppDelegate.swift' should be modified to properly initialize Unity. For details, see:", 226 | EditorStyles.wordWrappedLabel); 227 | 228 | // Creating the GUIStyle can't be done in a normal constructor 229 | // context because of some weird Unity restriction. 230 | if (LINK_STYLE == null) 231 | { 232 | var blackTransparent = new Color(0, 0, 0, 0); 233 | var transparent = new Texture2D(4, 4, TextureFormat.ARGB32, false); 234 | for (int y = 0; y < transparent.height; ++y) 235 | { 236 | for (int x = 0; x < transparent.width; ++x) 237 | { 238 | transparent.SetPixel(x, y, blackTransparent); 239 | } 240 | } 241 | transparent.Apply(false); 242 | 243 | LINK_STYLE = new GUIStyle(GUI.skin.label); 244 | 245 | LINK_STYLE.normal.background 246 | = LINK_STYLE.onNormal.background 247 | = transparent; 248 | LINK_STYLE.normal.textColor 249 | = LINK_STYLE.onNormal.textColor 250 | = Color.Lerp(Color.blue, Color.white, 0.5f); 251 | 252 | LINK_STYLE.focused.background 253 | = LINK_STYLE.onFocused.background 254 | = LINK_STYLE.hover.background 255 | = LINK_STYLE.onHover.background 256 | = transparent; 257 | LINK_STYLE.focused.textColor 258 | = LINK_STYLE.onFocused.textColor 259 | = LINK_STYLE.hover.textColor 260 | = LINK_STYLE.onHover.textColor 261 | = Color.Lerp(Color.cyan, Color.white, 0.5f); 262 | } 263 | 264 | if (GUILayout.Button(PROJECT_URL, LINK_STYLE)) 265 | { 266 | Application.OpenURL(PROJECT_URL); 267 | } 268 | } 269 | 270 | [PostProcessBuild] 271 | public static void OnPostBuild(BuildTarget target, string pathToBuiltProject) 272 | { 273 | var build = GetWindow(); 274 | if (build.enabled && target == BuildTarget.iOS) 275 | { 276 | PatchUnityNativeCode(pathToBuiltProject); 277 | build.UpdateUnityIOSExports(pathToBuiltProject); 278 | build.UpdateUnityProjectFiles(pathToBuiltProject); 279 | } 280 | } 281 | 282 | /// 283 | /// Writes current Unity version and output path to 'Exports.xcconfig' file. 284 | /// 285 | void UpdateUnityIOSExports(string pathToBuiltProject) 286 | { 287 | var config = new StringBuilder(); 288 | config.AppendFormat("UNITY_RUNTIME_VERSION = {0};{1}", Application.unityVersion, Environment.NewLine); 289 | config.AppendFormat("UNITY_IOS_EXPORT_PATH = {0};{1}", pathToBuiltProject, Environment.NewLine); 290 | 291 | var unityDir = PathExt.Combine(XcodeProjectRoot, XcodeProjectName, "Unity"); 292 | Directory.CreateDirectory(unityDir); 293 | var ExportsConfigProjectPath = PathExt.Combine(unityDir, "Exports.xcconfig"); 294 | File.WriteAllText(ExportsConfigProjectPath, config.ToString()); 295 | } 296 | 297 | static void CopyFile(string srcPath, string destPath) 298 | { 299 | Directory.CreateDirectory(Path.GetDirectoryName(destPath)); 300 | File.Copy(srcPath, destPath, true); 301 | } 302 | 303 | /// 304 | /// Enumerates Unity output files and add necessary files into Xcode project file. 305 | /// It only add a reference entry into project.pbx file, without actually copy it. 306 | /// Xcode pre-build script will copy files into correct location. 307 | /// 308 | void UpdateUnityProjectFiles(string pathToBuiltProject) 309 | { 310 | var pbxPath = PathExt.Combine( 311 | XcodeProjectRoot, 312 | Path.ChangeExtension(XcodeProjectName, "xcodeproj"), 313 | "project.pbxproj"); 314 | var pbx = new PBXProject(); 315 | pbx.ReadFromFile(pbxPath); 316 | 317 | string classesPath = PathExt.Combine(XcodeProjectName, "Unity", "Classes"); 318 | ProcessUnityDirectory( 319 | pbx, 320 | PathExt.Combine(pathToBuiltProject, "Classes"), 321 | PathExt.Combine(XcodeProjectRoot, classesPath), 322 | classesPath); 323 | 324 | string librariesPath = PathExt.Combine(XcodeProjectName, "Unity", "Libraries"); 325 | ProcessUnityDirectory( 326 | pbx, 327 | PathExt.Combine(pathToBuiltProject, "Libraries"), 328 | PathExt.Combine(XcodeProjectRoot, librariesPath), 329 | librariesPath); 330 | 331 | pbx.WriteToFile(pbxPath); 332 | } 333 | 334 | /// 335 | /// Update pbx project file by adding src files and removing extra files that 336 | /// exists in dest but not in src any more. 337 | /// 338 | /// This method only updates the pbx project file. It does not copy or delete 339 | /// files in Swift Xcode project. The Swift Xcode project will do copy and delete 340 | /// during build, and it should copy files if contents are different, regardless 341 | /// of the file time. 342 | /// 343 | /// The pbx project. 344 | /// The directory where Unity project is built. 345 | /// The directory of the Swift Xcode project where the 346 | /// Unity project is embedded into. 347 | /// The prefix of project path in Swift Xcode 348 | /// project for Unity code files. E.g. "DempApp/Unity/Classes" for all files 349 | /// under Classes folder from Unity iOS build output. 350 | void ProcessUnityDirectory(PBXProject pbx, string src, string dest, string projectPathPrefix) 351 | { 352 | var targetGuid = pbx.TargetGuidByName(XcodeProjectName); 353 | if (string.IsNullOrEmpty(targetGuid)) 354 | { 355 | throw new Exception(string.Format("TargetGuid could not be found for '{0}'", XcodeProjectName)); 356 | } 357 | 358 | // newFiles: array of file names in build output that do not exist in project.pbx manifest. 359 | // extraFiles: array of file names in project.pbx manifest that do not exist in build output. 360 | // Build output files that already exist in project.pbx manifest will be skipped to minimize 361 | // changes to project.pbx file. 362 | string[] newFiles, extraFiles; 363 | CompareDirectories(src, dest, out newFiles, out extraFiles); 364 | 365 | foreach (var projPath in 366 | from f in newFiles 367 | where !f.EndsWith(".bak", StringComparison.OrdinalIgnoreCase) 368 | let projPath = Path.Combine(projectPathPrefix, f) 369 | where !pbx.ContainsFileByProjectPath(projPath) 370 | select projPath) 371 | { 372 | var guid = pbx.AddFile(projPath, projPath); 373 | pbx.AddFileToBuild(targetGuid, guid); 374 | 375 | Debug.LogFormat("Added file to pbx: '{0}'", projPath); 376 | } 377 | 378 | foreach (var projPath in 379 | from f in extraFiles 380 | let projPath = PathExt.Combine(projectPathPrefix, f) 381 | where pbx.ContainsFileByProjectPath(projPath) 382 | select projPath) 383 | { 384 | var guid = pbx.FindFileGuidByProjectPath(projPath); 385 | pbx.RemoveFile(guid); 386 | 387 | Debug.LogFormat("Removed file from pbx: '{0}'", projPath); 388 | } 389 | } 390 | 391 | /// 392 | /// Compares the directories. Returns files that exists in src and 393 | /// extra files that exists in dest but not in src any more. 394 | /// 395 | private static void CompareDirectories(string src, string dest, out string[] srcFiles, out string[] extraFiles) 396 | { 397 | srcFiles = GetFilesRelativePath(src); 398 | 399 | var destFiles = GetFilesRelativePath(dest); 400 | var extraFilesSet = new HashSet(destFiles); 401 | 402 | extraFilesSet.ExceptWith(srcFiles); 403 | extraFiles = extraFilesSet.ToArray(); 404 | } 405 | 406 | private static string[] GetFilesRelativePath(string directory) 407 | { 408 | var results = new List(); 409 | 410 | if (Directory.Exists(directory)) 411 | { 412 | foreach (var path in Directory.GetFiles(directory, "*", SearchOption.AllDirectories)) 413 | { 414 | results.Add(PathExt.Abs2Rel(path, directory)); 415 | } 416 | } 417 | 418 | return results.ToArray(); 419 | } 420 | 421 | /// 422 | /// Replaces the character component of Unity's version number with a period 423 | /// and the decimal ASCII value of that character, to create an ersatz revision 424 | /// number. 425 | /// 426 | /// A Version struct that can be used for range comparisons. 427 | /// Unity's version string, formatted as [YEAR].[MINOR].[PATCH][CHARACTER][REVISION]. 428 | private static Version ParseUnityVersionNumber(string versionString) 429 | { 430 | for (int i = versionString.Length - 1; i >= 0; --i) 431 | { 432 | var token = versionString[i]; 433 | if (char.IsLetter(token)) 434 | { 435 | versionString = versionString 436 | .Remove(i) 437 | .Insert(i, string.Format(".{0}", (int)token)); 438 | } 439 | } 440 | 441 | return new Version(versionString); 442 | } 443 | 444 | /// 445 | /// Make necessary changes to Unity build output that enables it to be embedded into existing Xcode project. 446 | /// 447 | private static void PatchUnityNativeCode(string pathToBuiltProject) 448 | { 449 | var unityVersion = ParseUnityVersionNumber(Application.unityVersion); 450 | 451 | EditMainMM(PathExt.Combine(pathToBuiltProject, "Classes/main.mm")); 452 | EditUnityAppControllerH(PathExt.Combine(pathToBuiltProject, "Classes/UnityAppController.h")); 453 | EditUnityAppControllerMM(PathExt.Combine(pathToBuiltProject, "Classes/UnityAppController.mm")); 454 | 455 | if (unityVersion == UNITY_VERSION_FOR_METAL_HELPER) 456 | { 457 | EditMetalHelperMM(PathExt.Combine(pathToBuiltProject, "Classes/Unity/MetalHelper.mm")); 458 | } 459 | 460 | if (unityVersion >= MIN_UNITY_VERSION_FOR_SPLASH_SCREEN) 461 | { 462 | EditSplashScreenMM(PathExt.Combine(pathToBuiltProject, "Classes/UI/SplashScreen.mm")); 463 | } 464 | } 465 | 466 | /// 467 | /// Edit 'main.mm': removes 'main' entry that would conflict with the Xcode project it embeds into. 468 | /// 469 | private static void EditMainMM(string path) 470 | { 471 | EditCodeFile(path, line => 472 | { 473 | if (line.TrimStart().StartsWith("int main", StringComparison.Ordinal)) 474 | { 475 | return line.Replace("int main", "int old_main"); 476 | } 477 | 478 | return line; 479 | }); 480 | } 481 | 482 | /// 483 | /// Edit 'UnityAppController.h': returns 'UnityAppController' from 'AppDelegate' class. 484 | /// 485 | private static void EditUnityAppControllerH(string path) 486 | { 487 | var inScope = false; 488 | var markerDetected = false; 489 | var markerAdded = false; 490 | 491 | EditCodeFile(path, line => 492 | { 493 | markerDetected |= line.Contains(TOUCH_MARKER); 494 | inScope |= line.Contains("inline UnityAppController"); 495 | 496 | if (inScope && !markerDetected) 497 | { 498 | if (line.Trim() == "}") 499 | { 500 | inScope = false; 501 | 502 | return new string[] 503 | { 504 | "// }", 505 | "", 506 | "NS_INLINE UnityAppController* GetAppController()", 507 | "{", 508 | " NSObject* delegate = [UIApplication sharedApplication].delegate;", 509 | @" UnityAppController* currentUnityController = (UnityAppController*)[delegate valueForKey: @""currentUnityController""];", 510 | " return currentUnityController;", 511 | "}", 512 | }; 513 | } 514 | 515 | if (!markerAdded) 516 | { 517 | markerAdded = true; 518 | return new string[] 519 | { 520 | "// Modified by " + TOUCH_MARKER, 521 | "// " + line, 522 | }; 523 | } 524 | 525 | return new string[] { "// " + line }; 526 | } 527 | 528 | return new string[] { line }; 529 | }); 530 | } 531 | 532 | /// 533 | /// Edit 'UnityAppController.mm': triggers 'UnityReady' notification after Unity is actually started. 534 | /// 535 | private static void EditUnityAppControllerMM(string path) 536 | { 537 | var inScope = false; 538 | var markerDetected = false; 539 | 540 | EditCodeFile(path, line => 541 | { 542 | inScope |= line.Contains("- (void)startUnity:"); 543 | markerDetected |= inScope && line.Contains(TOUCH_MARKER); 544 | 545 | if (inScope && line.Trim() == "}") 546 | { 547 | inScope = false; 548 | 549 | if (markerDetected) 550 | { 551 | return new string[] { line }; 552 | } 553 | else 554 | { 555 | return new string[] 556 | { 557 | " // Modified by " + TOUCH_MARKER, 558 | " // Post a notification so that Swift can load unity view once started.", 559 | @" [[NSNotificationCenter defaultCenter] postNotificationName: @""UnityReady"" object:self];", 560 | "}", 561 | }; 562 | } 563 | } 564 | 565 | return new string[] { line }; 566 | }); 567 | } 568 | 569 | /// 570 | /// Edit 'MetalHelper.mm': fixes a bug (only in 2017.1.1f1) that causes crash. 571 | /// 572 | private static void EditMetalHelperMM(string path) 573 | { 574 | var markerDetected = false; 575 | 576 | EditCodeFile(path, line => 577 | { 578 | markerDetected |= line.Contains(TOUCH_MARKER); 579 | 580 | if (!markerDetected && line.Trim() == "surface->stencilRB = [surface->device newTextureWithDescriptor: stencilTexDesc];") 581 | { 582 | return new string[] 583 | { 584 | "", 585 | " // Modified by " + TOUCH_MARKER, 586 | " // Default stencilTexDesc.usage has flag 1. In runtime it will cause assertion failure:", 587 | " // validateRenderPassDescriptor:589: failed assertion `Texture at stencilAttachment has usage (0x01) which doesn't specify MTLTextureUsageRenderTarget (0x04)'", 588 | " // Adding MTLTextureUsageRenderTarget seems to fix this issue.", 589 | " stencilTexDesc.usage |= MTLTextureUsageRenderTarget;", 590 | line, 591 | }; 592 | } 593 | 594 | return new string[] { line }; 595 | }); 596 | } 597 | 598 | /// 599 | /// Edit 'SplashScreen.mm': Unity introduces its own 'LaunchScreen.storyboard' since 2017.3.0f3. 600 | /// Disable it here and use Swift project's launch screen instead. 601 | /// 602 | private static void EditSplashScreenMM(string path) 603 | { 604 | var markerDetected = false; 605 | var markerAdded = false; 606 | var inScope = false; 607 | var level = 0; 608 | 609 | EditCodeFile(path, line => 610 | { 611 | inScope |= line.Trim() == "void ShowSplashScreen(UIWindow* window)"; 612 | markerDetected |= line.Contains(TOUCH_MARKER); 613 | 614 | if (inScope && !markerDetected) 615 | { 616 | if (line.Trim() == "{") 617 | { 618 | level++; 619 | } 620 | else if (line.Trim() == "}") 621 | { 622 | level--; 623 | } 624 | 625 | if (line.Trim() == "}" && level == 0) 626 | { 627 | inScope = false; 628 | } 629 | 630 | if (level > 0 && line.Trim().StartsWith("bool hasStoryboard", StringComparison.Ordinal)) 631 | { 632 | return new string[] 633 | { 634 | " // " + line, 635 | " bool hasStoryboard = false;", 636 | }; 637 | } 638 | 639 | if (!markerAdded) 640 | { 641 | markerAdded = true; 642 | return new string[] 643 | { 644 | "// Modified by " + TOUCH_MARKER, 645 | line, 646 | }; 647 | } 648 | } 649 | 650 | return new string[] { line }; 651 | }); 652 | } 653 | 654 | private static void EditCodeFile(string path, Func lineHandler) 655 | { 656 | EditCodeFile(path, line => 657 | { 658 | return new string[] { lineHandler(line) }; 659 | }); 660 | } 661 | 662 | private static void EditCodeFile(string path, Func> lineHandler) 663 | { 664 | var bakPath = path + ".bak"; 665 | File.Copy(path, bakPath, true); 666 | 667 | using (var reader = File.OpenText(bakPath)) 668 | using (var stream = File.Create(path)) 669 | using (var writer = new StreamWriter(stream)) 670 | { 671 | string line; 672 | while ((line = reader.ReadLine()) != null) 673 | { 674 | var outputs = lineHandler(line); 675 | foreach (var o in outputs) 676 | { 677 | writer.WriteLine(o); 678 | } 679 | } 680 | } 681 | } 682 | } 683 | 684 | /// 685 | /// A static class containing a few functions that the normal System.IO.Path class does not contain. 686 | /// 687 | public static class PathExt 688 | { 689 | /// 690 | /// Creates a path-like value for the current system, given a variable number of path parts. 691 | /// Path parts may be directories or files. The path parts are not validated against the file 692 | /// system. 693 | /// 694 | /// The parts array, encoded into a single string, with System.IO.Path.DirectorySeparatorChar 695 | /// separating individual parts 696 | /// 697 | /// .NET 3.5 does not have a Path.Combine function that takes a variadric 698 | /// array of path parts as a parameter. On Unity projects using the .NET 699 | /// 3.5 runtime, we have to wrap it up and implement our own version. 700 | /// 701 | /// The path parts to combine into a path value. 702 | public static string Combine(params string[] parts) 703 | { 704 | #if NET_2_0 || NET_2_0_SUBSET 705 | if (parts == null || parts.Length == 0) 706 | { 707 | return null; 708 | } 709 | else 710 | { 711 | return string.Join(Path.DirectorySeparatorChar.ToString(), parts); 712 | } 713 | #else 714 | return Path.Combine(parts); 715 | #endif 716 | } 717 | 718 | /// 719 | /// Creates a file path that is relative to the currently-edited demo path. 720 | /// 721 | /// The relative path. 722 | /// Full path. 723 | /// The directory from which to consider the relative path. If no value 724 | /// is provided (i.e. `null` or empty string), then the current working directory is used. 725 | public static string Abs2Rel(string fullPath, string directory = null) 726 | { 727 | if (!Path.IsPathRooted(fullPath)) 728 | { 729 | return fullPath; 730 | } 731 | else 732 | { 733 | if (string.IsNullOrEmpty(directory)) 734 | { 735 | directory = Environment.CurrentDirectory; 736 | } 737 | 738 | var partsA = directory.Split('/', '\\').ToList(); 739 | var partsB = fullPath.Split('/', '\\').ToList(); 740 | 741 | while (partsA.Count > 0 742 | && partsB.Count > 0 743 | && partsA[0] == partsB[0]) 744 | { 745 | partsA.RemoveAt(0); 746 | partsB.RemoveAt(0); 747 | } 748 | 749 | if (partsB.Count == 0) 750 | { 751 | return null; 752 | } 753 | else 754 | { 755 | return Combine(partsA 756 | .Select(_ => "..") 757 | .Concat(partsB) 758 | .ToArray()); 759 | } 760 | } 761 | } 762 | 763 | /// 764 | /// Resolves an absolute path from a path that is relative to the currently-edited 765 | /// demo path. 766 | /// 767 | /// The absolute path. 768 | /// Relative path. 769 | /// The directory from which to consider the relative path. If no value 770 | /// is provided (i.e. `null` or empty string), then the current working directory is used. 771 | public static string Rel2Abs(string relativePath, string directory = null) 772 | { 773 | if (Path.IsPathRooted(relativePath)) 774 | { 775 | return relativePath; 776 | } 777 | else 778 | { 779 | if (string.IsNullOrEmpty(directory)) 780 | { 781 | directory = Environment.CurrentDirectory; 782 | } 783 | 784 | var partsA = directory.Split('/', '\\').ToList(); 785 | var partsB = relativePath.Split('/', '\\').ToList(); 786 | 787 | while (partsA.Count > 0 788 | && partsB.Count > 0 789 | && partsB[0] == "..") 790 | { 791 | partsA.RemoveAt(partsA.Count - 1); 792 | partsB.RemoveAt(0); 793 | } 794 | 795 | if (partsB.Count == 0) 796 | { 797 | return null; 798 | } 799 | else 800 | { 801 | return Combine(partsA 802 | .Concat(partsB) 803 | .ToArray()); 804 | } 805 | } 806 | } 807 | } 808 | 809 | #endif 810 | -------------------------------------------------------------------------------- /demo/unity/.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Visual Studio 2015 cache directory 9 | /.vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | 26 | # Unity3D generated meta files 27 | *.pidb.meta 28 | 29 | # Unity3D Generated File On Crash Reports 30 | sysinfo.txt 31 | 32 | # Builds 33 | *.apk 34 | *.unitypackage 35 | -------------------------------------------------------------------------------- /demo/unity/Assets/Demo.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 8 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 1145127022} 41 | m_IndirectSpecularColor: {r: 0.4465785, g: 0.49641252, b: 0.574817, a: 1} 42 | --- !u!157 &3 43 | LightmapSettings: 44 | m_ObjectHideFlags: 0 45 | serializedVersion: 11 46 | m_GIWorkflowMode: 0 47 | m_GISettings: 48 | serializedVersion: 2 49 | m_BounceScale: 1 50 | m_IndirectOutputScale: 1 51 | m_AlbedoBoost: 1 52 | m_TemporalCoherenceThreshold: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 1 56 | m_LightmapEditorSettings: 57 | serializedVersion: 9 58 | m_Resolution: 2 59 | m_BakeResolution: 40 60 | m_TextureWidth: 1024 61 | m_TextureHeight: 1024 62 | m_AO: 0 63 | m_AOMaxDistance: 1 64 | m_CompAOExponent: 1 65 | m_CompAOExponentDirect: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 0 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVRFilterTypeDirect: 0 81 | m_PVRFilterTypeIndirect: 0 82 | m_PVRFilterTypeAO: 0 83 | m_PVRFilteringMode: 1 84 | m_PVRCulling: 1 85 | m_PVRFilteringGaussRadiusDirect: 1 86 | m_PVRFilteringGaussRadiusIndirect: 5 87 | m_PVRFilteringGaussRadiusAO: 2 88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 90 | m_PVRFilteringAtrousPositionSigmaAO: 1 91 | m_LightingDataAsset: {fileID: 0} 92 | m_UseShadowmask: 1 93 | --- !u!196 &4 94 | NavMeshSettings: 95 | serializedVersion: 2 96 | m_ObjectHideFlags: 0 97 | m_BuildSettings: 98 | serializedVersion: 2 99 | agentTypeID: 0 100 | agentRadius: 0.5 101 | agentHeight: 2 102 | agentSlope: 45 103 | agentClimb: 0.4 104 | ledgeDropHeight: 0 105 | maxJumpAcrossDistance: 0 106 | minRegionArea: 2 107 | manualCellSize: 0 108 | cellSize: 0.16666667 109 | manualTileSize: 0 110 | tileSize: 256 111 | accuratePlacement: 0 112 | debug: 113 | m_Flags: 0 114 | m_NavMeshData: {fileID: 0} 115 | --- !u!1 &95103270 116 | GameObject: 117 | m_ObjectHideFlags: 0 118 | m_PrefabParentObject: {fileID: 0} 119 | m_PrefabInternal: {fileID: 0} 120 | serializedVersion: 5 121 | m_Component: 122 | - component: {fileID: 95103271} 123 | - component: {fileID: 95103273} 124 | - component: {fileID: 95103272} 125 | m_Layer: 5 126 | m_Name: Label 127 | m_TagString: Untagged 128 | m_Icon: {fileID: 0} 129 | m_NavMeshLayer: 0 130 | m_StaticEditorFlags: 0 131 | m_IsActive: 1 132 | --- !u!224 &95103271 133 | RectTransform: 134 | m_ObjectHideFlags: 0 135 | m_PrefabParentObject: {fileID: 0} 136 | m_PrefabInternal: {fileID: 0} 137 | m_GameObject: {fileID: 95103270} 138 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 139 | m_LocalPosition: {x: 9, y: 6, z: 0} 140 | m_LocalScale: {x: 1, y: 1, z: 1} 141 | m_Children: [] 142 | m_Father: {fileID: 150674532} 143 | m_RootOrder: 1 144 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 145 | m_AnchorMin: {x: 0, y: 0} 146 | m_AnchorMax: {x: 1, y: 1} 147 | m_AnchoredPosition: {x: 9, y: -2} 148 | m_SizeDelta: {x: -28, y: 4} 149 | m_Pivot: {x: 0.5, y: 0.5} 150 | --- !u!114 &95103272 151 | MonoBehaviour: 152 | m_ObjectHideFlags: 0 153 | m_PrefabParentObject: {fileID: 0} 154 | m_PrefabInternal: {fileID: 0} 155 | m_GameObject: {fileID: 95103270} 156 | m_Enabled: 1 157 | m_EditorHideFlags: 0 158 | m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 159 | m_Name: 160 | m_EditorClassIdentifier: 161 | m_Material: {fileID: 0} 162 | m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} 163 | m_RaycastTarget: 1 164 | m_OnCullStateChanged: 165 | m_PersistentCalls: 166 | m_Calls: [] 167 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 168 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 169 | m_FontData: 170 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 171 | m_FontSize: 14 172 | m_FontStyle: 0 173 | m_BestFit: 1 174 | m_MinSize: 10 175 | m_MaxSize: 40 176 | m_Alignment: 4 177 | m_AlignByGeometry: 0 178 | m_RichText: 1 179 | m_HorizontalOverflow: 0 180 | m_VerticalOverflow: 0 181 | m_LineSpacing: 1 182 | m_Text: Rotate 183 | --- !u!222 &95103273 184 | CanvasRenderer: 185 | m_ObjectHideFlags: 0 186 | m_PrefabParentObject: {fileID: 0} 187 | m_PrefabInternal: {fileID: 0} 188 | m_GameObject: {fileID: 95103270} 189 | --- !u!1 &150674531 190 | GameObject: 191 | m_ObjectHideFlags: 0 192 | m_PrefabParentObject: {fileID: 0} 193 | m_PrefabInternal: {fileID: 0} 194 | serializedVersion: 5 195 | m_Component: 196 | - component: {fileID: 150674532} 197 | - component: {fileID: 150674533} 198 | m_Layer: 5 199 | m_Name: Toggle 200 | m_TagString: Untagged 201 | m_Icon: {fileID: 0} 202 | m_NavMeshLayer: 0 203 | m_StaticEditorFlags: 0 204 | m_IsActive: 1 205 | --- !u!224 &150674532 206 | RectTransform: 207 | m_ObjectHideFlags: 0 208 | m_PrefabParentObject: {fileID: 0} 209 | m_PrefabInternal: {fileID: 0} 210 | m_GameObject: {fileID: 150674531} 211 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 212 | m_LocalPosition: {x: 0, y: -120.28125, z: 0} 213 | m_LocalScale: {x: 1, y: 1, z: 1} 214 | m_Children: 215 | - {fileID: 818757406} 216 | - {fileID: 95103271} 217 | m_Father: {fileID: 1871201458} 218 | m_RootOrder: 0 219 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 220 | m_AnchorMin: {x: 0.5, y: 0} 221 | m_AnchorMax: {x: 0.5, y: 0} 222 | m_AnchoredPosition: {x: 0, y: 6} 223 | m_SizeDelta: {x: 60, y: 16} 224 | m_Pivot: {x: 0.5, y: 0} 225 | --- !u!114 &150674533 226 | MonoBehaviour: 227 | m_ObjectHideFlags: 0 228 | m_PrefabParentObject: {fileID: 0} 229 | m_PrefabInternal: {fileID: 0} 230 | m_GameObject: {fileID: 150674531} 231 | m_Enabled: 1 232 | m_EditorHideFlags: 0 233 | m_Script: {fileID: 2109663825, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 234 | m_Name: 235 | m_EditorClassIdentifier: 236 | m_Navigation: 237 | m_Mode: 3 238 | m_SelectOnUp: {fileID: 0} 239 | m_SelectOnDown: {fileID: 0} 240 | m_SelectOnLeft: {fileID: 0} 241 | m_SelectOnRight: {fileID: 0} 242 | m_Transition: 1 243 | m_Colors: 244 | m_NormalColor: {r: 1, g: 1, b: 1, a: 1} 245 | m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} 246 | m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} 247 | m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} 248 | m_ColorMultiplier: 1 249 | m_FadeDuration: 0.1 250 | m_SpriteState: 251 | m_HighlightedSprite: {fileID: 0} 252 | m_PressedSprite: {fileID: 0} 253 | m_DisabledSprite: {fileID: 0} 254 | m_AnimationTriggers: 255 | m_NormalTrigger: Normal 256 | m_HighlightedTrigger: Highlighted 257 | m_PressedTrigger: Pressed 258 | m_DisabledTrigger: Disabled 259 | m_Interactable: 1 260 | m_TargetGraphic: {fileID: 818757407} 261 | toggleTransition: 1 262 | graphic: {fileID: 942186821} 263 | m_Group: {fileID: 0} 264 | onValueChanged: 265 | m_PersistentCalls: 266 | m_Calls: 267 | - m_Target: {fileID: 1847080532} 268 | m_MethodName: OnToggleValueChanged 269 | m_Mode: 0 270 | m_Arguments: 271 | m_ObjectArgument: {fileID: 0} 272 | m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine 273 | m_IntArgument: 0 274 | m_FloatArgument: 0 275 | m_StringArgument: 276 | m_BoolArgument: 0 277 | m_CallState: 2 278 | m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, 279 | Culture=neutral, PublicKeyToken=null 280 | m_IsOn: 0 281 | --- !u!1 &175859236 282 | GameObject: 283 | m_ObjectHideFlags: 0 284 | m_PrefabParentObject: {fileID: 0} 285 | m_PrefabInternal: {fileID: 0} 286 | serializedVersion: 5 287 | m_Component: 288 | - component: {fileID: 175859239} 289 | - component: {fileID: 175859238} 290 | - component: {fileID: 175859237} 291 | m_Layer: 0 292 | m_Name: EventSystem 293 | m_TagString: Untagged 294 | m_Icon: {fileID: 0} 295 | m_NavMeshLayer: 0 296 | m_StaticEditorFlags: 0 297 | m_IsActive: 1 298 | --- !u!114 &175859237 299 | MonoBehaviour: 300 | m_ObjectHideFlags: 0 301 | m_PrefabParentObject: {fileID: 0} 302 | m_PrefabInternal: {fileID: 0} 303 | m_GameObject: {fileID: 175859236} 304 | m_Enabled: 1 305 | m_EditorHideFlags: 0 306 | m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 307 | m_Name: 308 | m_EditorClassIdentifier: 309 | m_HorizontalAxis: Horizontal 310 | m_VerticalAxis: Vertical 311 | m_SubmitButton: Submit 312 | m_CancelButton: Cancel 313 | m_InputActionsPerSecond: 10 314 | m_RepeatDelay: 0.5 315 | m_ForceModuleActive: 0 316 | --- !u!114 &175859238 317 | MonoBehaviour: 318 | m_ObjectHideFlags: 0 319 | m_PrefabParentObject: {fileID: 0} 320 | m_PrefabInternal: {fileID: 0} 321 | m_GameObject: {fileID: 175859236} 322 | m_Enabled: 1 323 | m_EditorHideFlags: 0 324 | m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 325 | m_Name: 326 | m_EditorClassIdentifier: 327 | m_FirstSelected: {fileID: 0} 328 | m_sendNavigationEvents: 1 329 | m_DragThreshold: 5 330 | --- !u!4 &175859239 331 | Transform: 332 | m_ObjectHideFlags: 0 333 | m_PrefabParentObject: {fileID: 0} 334 | m_PrefabInternal: {fileID: 0} 335 | m_GameObject: {fileID: 175859236} 336 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 337 | m_LocalPosition: {x: 0, y: 0, z: 0} 338 | m_LocalScale: {x: 1, y: 1, z: 1} 339 | m_Children: [] 340 | m_Father: {fileID: 0} 341 | m_RootOrder: 5 342 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 343 | --- !u!1 &500354549 344 | GameObject: 345 | m_ObjectHideFlags: 0 346 | m_PrefabParentObject: {fileID: 0} 347 | m_PrefabInternal: {fileID: 0} 348 | serializedVersion: 5 349 | m_Component: 350 | - component: {fileID: 500354553} 351 | - component: {fileID: 500354552} 352 | - component: {fileID: 500354551} 353 | - component: {fileID: 500354550} 354 | - component: {fileID: 500354555} 355 | - component: {fileID: 500354554} 356 | m_Layer: 0 357 | m_Name: Cube 358 | m_TagString: Untagged 359 | m_Icon: {fileID: 0} 360 | m_NavMeshLayer: 0 361 | m_StaticEditorFlags: 0 362 | m_IsActive: 1 363 | --- !u!23 &500354550 364 | MeshRenderer: 365 | m_ObjectHideFlags: 0 366 | m_PrefabParentObject: {fileID: 0} 367 | m_PrefabInternal: {fileID: 0} 368 | m_GameObject: {fileID: 500354549} 369 | m_Enabled: 1 370 | m_CastShadows: 1 371 | m_ReceiveShadows: 1 372 | m_DynamicOccludee: 1 373 | m_MotionVectors: 1 374 | m_LightProbeUsage: 1 375 | m_ReflectionProbeUsage: 1 376 | m_Materials: 377 | - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} 378 | m_StaticBatchInfo: 379 | firstSubMesh: 0 380 | subMeshCount: 0 381 | m_StaticBatchRoot: {fileID: 0} 382 | m_ProbeAnchor: {fileID: 0} 383 | m_LightProbeVolumeOverride: {fileID: 0} 384 | m_ScaleInLightmap: 1 385 | m_PreserveUVs: 1 386 | m_IgnoreNormalsForChartDetection: 0 387 | m_ImportantGI: 0 388 | m_StitchLightmapSeams: 0 389 | m_SelectedEditorRenderState: 3 390 | m_MinimumChartSize: 4 391 | m_AutoUVMaxDistance: 0.5 392 | m_AutoUVMaxAngle: 89 393 | m_LightmapParameters: {fileID: 0} 394 | m_SortingLayerID: 0 395 | m_SortingLayer: 0 396 | m_SortingOrder: 0 397 | --- !u!65 &500354551 398 | BoxCollider: 399 | m_ObjectHideFlags: 0 400 | m_PrefabParentObject: {fileID: 0} 401 | m_PrefabInternal: {fileID: 0} 402 | m_GameObject: {fileID: 500354549} 403 | m_Material: {fileID: 0} 404 | m_IsTrigger: 0 405 | m_Enabled: 1 406 | serializedVersion: 2 407 | m_Size: {x: 1, y: 1, z: 1} 408 | m_Center: {x: 0, y: 0, z: 0} 409 | --- !u!33 &500354552 410 | MeshFilter: 411 | m_ObjectHideFlags: 0 412 | m_PrefabParentObject: {fileID: 0} 413 | m_PrefabInternal: {fileID: 0} 414 | m_GameObject: {fileID: 500354549} 415 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 416 | --- !u!4 &500354553 417 | Transform: 418 | m_ObjectHideFlags: 0 419 | m_PrefabParentObject: {fileID: 0} 420 | m_PrefabInternal: {fileID: 0} 421 | m_GameObject: {fileID: 500354549} 422 | m_LocalRotation: {x: 0, y: 0.38268343, z: 0, w: 0.92387956} 423 | m_LocalPosition: {x: 0, y: 0, z: 0} 424 | m_LocalScale: {x: 2, y: 2, z: 2} 425 | m_Children: [] 426 | m_Father: {fileID: 0} 427 | m_RootOrder: 3 428 | m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0} 429 | --- !u!114 &500354554 430 | MonoBehaviour: 431 | m_ObjectHideFlags: 0 432 | m_PrefabParentObject: {fileID: 0} 433 | m_PrefabInternal: {fileID: 0} 434 | m_GameObject: {fileID: 500354549} 435 | m_Enabled: 1 436 | m_EditorHideFlags: 0 437 | m_Script: {fileID: 11500000, guid: 000c2463d03e74174affecfd67093ee1, type: 3} 438 | m_Name: 439 | m_EditorClassIdentifier: 440 | --- !u!54 &500354555 441 | Rigidbody: 442 | m_ObjectHideFlags: 0 443 | m_PrefabParentObject: {fileID: 0} 444 | m_PrefabInternal: {fileID: 0} 445 | m_GameObject: {fileID: 500354549} 446 | serializedVersion: 2 447 | m_Mass: 1 448 | m_Drag: 0 449 | m_AngularDrag: 0.05 450 | m_UseGravity: 0 451 | m_IsKinematic: 0 452 | m_Interpolate: 0 453 | m_Constraints: 0 454 | m_CollisionDetection: 0 455 | --- !u!1 &818757405 456 | GameObject: 457 | m_ObjectHideFlags: 0 458 | m_PrefabParentObject: {fileID: 0} 459 | m_PrefabInternal: {fileID: 0} 460 | serializedVersion: 5 461 | m_Component: 462 | - component: {fileID: 818757406} 463 | - component: {fileID: 818757408} 464 | - component: {fileID: 818757407} 465 | m_Layer: 5 466 | m_Name: Background 467 | m_TagString: Untagged 468 | m_Icon: {fileID: 0} 469 | m_NavMeshLayer: 0 470 | m_StaticEditorFlags: 0 471 | m_IsActive: 1 472 | --- !u!224 &818757406 473 | RectTransform: 474 | m_ObjectHideFlags: 0 475 | m_PrefabParentObject: {fileID: 0} 476 | m_PrefabInternal: {fileID: 0} 477 | m_GameObject: {fileID: 818757405} 478 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 479 | m_LocalPosition: {x: -20, y: 6, z: 0} 480 | m_LocalScale: {x: 1, y: 1, z: 1} 481 | m_Children: 482 | - {fileID: 942186820} 483 | m_Father: {fileID: 150674532} 484 | m_RootOrder: 0 485 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 486 | m_AnchorMin: {x: 0, y: 0} 487 | m_AnchorMax: {x: 1, y: 1} 488 | m_AnchoredPosition: {x: -20, y: -2} 489 | m_SizeDelta: {x: -40, y: 4} 490 | m_Pivot: {x: 0.5, y: 0.5} 491 | --- !u!114 &818757407 492 | MonoBehaviour: 493 | m_ObjectHideFlags: 0 494 | m_PrefabParentObject: {fileID: 0} 495 | m_PrefabInternal: {fileID: 0} 496 | m_GameObject: {fileID: 818757405} 497 | m_Enabled: 1 498 | m_EditorHideFlags: 0 499 | m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 500 | m_Name: 501 | m_EditorClassIdentifier: 502 | m_Material: {fileID: 0} 503 | m_Color: {r: 1, g: 1, b: 1, a: 1} 504 | m_RaycastTarget: 1 505 | m_OnCullStateChanged: 506 | m_PersistentCalls: 507 | m_Calls: [] 508 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 509 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 510 | m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} 511 | m_Type: 1 512 | m_PreserveAspect: 0 513 | m_FillCenter: 1 514 | m_FillMethod: 4 515 | m_FillAmount: 1 516 | m_FillClockwise: 1 517 | m_FillOrigin: 0 518 | --- !u!222 &818757408 519 | CanvasRenderer: 520 | m_ObjectHideFlags: 0 521 | m_PrefabParentObject: {fileID: 0} 522 | m_PrefabInternal: {fileID: 0} 523 | m_GameObject: {fileID: 818757405} 524 | --- !u!1 &942186819 525 | GameObject: 526 | m_ObjectHideFlags: 0 527 | m_PrefabParentObject: {fileID: 0} 528 | m_PrefabInternal: {fileID: 0} 529 | serializedVersion: 5 530 | m_Component: 531 | - component: {fileID: 942186820} 532 | - component: {fileID: 942186822} 533 | - component: {fileID: 942186821} 534 | m_Layer: 5 535 | m_Name: Checkmark 536 | m_TagString: Untagged 537 | m_Icon: {fileID: 0} 538 | m_NavMeshLayer: 0 539 | m_StaticEditorFlags: 0 540 | m_IsActive: 1 541 | --- !u!224 &942186820 542 | RectTransform: 543 | m_ObjectHideFlags: 0 544 | m_PrefabParentObject: {fileID: 0} 545 | m_PrefabInternal: {fileID: 0} 546 | m_GameObject: {fileID: 942186819} 547 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 548 | m_LocalPosition: {x: 0, y: 0, z: 0} 549 | m_LocalScale: {x: 1, y: 1, z: 1} 550 | m_Children: [] 551 | m_Father: {fileID: 818757406} 552 | m_RootOrder: 0 553 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 554 | m_AnchorMin: {x: 0.5, y: 0.5} 555 | m_AnchorMax: {x: 0.5, y: 0.5} 556 | m_AnchoredPosition: {x: 0, y: 0} 557 | m_SizeDelta: {x: 20, y: 20} 558 | m_Pivot: {x: 0.5, y: 0.5} 559 | --- !u!114 &942186821 560 | MonoBehaviour: 561 | m_ObjectHideFlags: 0 562 | m_PrefabParentObject: {fileID: 0} 563 | m_PrefabInternal: {fileID: 0} 564 | m_GameObject: {fileID: 942186819} 565 | m_Enabled: 1 566 | m_EditorHideFlags: 0 567 | m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 568 | m_Name: 569 | m_EditorClassIdentifier: 570 | m_Material: {fileID: 0} 571 | m_Color: {r: 1, g: 1, b: 1, a: 1} 572 | m_RaycastTarget: 1 573 | m_OnCullStateChanged: 574 | m_PersistentCalls: 575 | m_Calls: [] 576 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 577 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 578 | m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} 579 | m_Type: 0 580 | m_PreserveAspect: 0 581 | m_FillCenter: 1 582 | m_FillMethod: 4 583 | m_FillAmount: 1 584 | m_FillClockwise: 1 585 | m_FillOrigin: 0 586 | --- !u!222 &942186822 587 | CanvasRenderer: 588 | m_ObjectHideFlags: 0 589 | m_PrefabParentObject: {fileID: 0} 590 | m_PrefabInternal: {fileID: 0} 591 | m_GameObject: {fileID: 942186819} 592 | --- !u!1 &1145127021 593 | GameObject: 594 | m_ObjectHideFlags: 0 595 | m_PrefabParentObject: {fileID: 0} 596 | m_PrefabInternal: {fileID: 0} 597 | serializedVersion: 5 598 | m_Component: 599 | - component: {fileID: 1145127023} 600 | - component: {fileID: 1145127022} 601 | m_Layer: 0 602 | m_Name: Directional Light 603 | m_TagString: Untagged 604 | m_Icon: {fileID: 0} 605 | m_NavMeshLayer: 0 606 | m_StaticEditorFlags: 0 607 | m_IsActive: 1 608 | --- !u!108 &1145127022 609 | Light: 610 | m_ObjectHideFlags: 0 611 | m_PrefabParentObject: {fileID: 0} 612 | m_PrefabInternal: {fileID: 0} 613 | m_GameObject: {fileID: 1145127021} 614 | m_Enabled: 1 615 | serializedVersion: 8 616 | m_Type: 1 617 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 618 | m_Intensity: 1 619 | m_Range: 10 620 | m_SpotAngle: 30 621 | m_CookieSize: 10 622 | m_Shadows: 623 | m_Type: 2 624 | m_Resolution: -1 625 | m_CustomResolution: -1 626 | m_Strength: 1 627 | m_Bias: 0.05 628 | m_NormalBias: 0.4 629 | m_NearPlane: 0.2 630 | m_Cookie: {fileID: 0} 631 | m_DrawHalo: 0 632 | m_Flare: {fileID: 0} 633 | m_RenderMode: 0 634 | m_CullingMask: 635 | serializedVersion: 2 636 | m_Bits: 4294967295 637 | m_Lightmapping: 4 638 | m_AreaSize: {x: 1, y: 1} 639 | m_BounceIntensity: 1 640 | m_ColorTemperature: 6570 641 | m_UseColorTemperature: 0 642 | m_ShadowRadius: 0 643 | m_ShadowAngle: 0 644 | --- !u!4 &1145127023 645 | Transform: 646 | m_ObjectHideFlags: 0 647 | m_PrefabParentObject: {fileID: 0} 648 | m_PrefabInternal: {fileID: 0} 649 | m_GameObject: {fileID: 1145127021} 650 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 651 | m_LocalPosition: {x: 0, y: 3, z: 0} 652 | m_LocalScale: {x: 1, y: 1, z: 1} 653 | m_Children: [] 654 | m_Father: {fileID: 0} 655 | m_RootOrder: 2 656 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 657 | --- !u!1 &1246330093 658 | GameObject: 659 | m_ObjectHideFlags: 0 660 | m_PrefabParentObject: {fileID: 0} 661 | m_PrefabInternal: {fileID: 0} 662 | serializedVersion: 5 663 | m_Component: 664 | - component: {fileID: 1246330098} 665 | - component: {fileID: 1246330097} 666 | - component: {fileID: 1246330096} 667 | - component: {fileID: 1246330095} 668 | - component: {fileID: 1246330094} 669 | m_Layer: 0 670 | m_Name: Main Camera 671 | m_TagString: MainCamera 672 | m_Icon: {fileID: 0} 673 | m_NavMeshLayer: 0 674 | m_StaticEditorFlags: 0 675 | m_IsActive: 1 676 | --- !u!81 &1246330094 677 | AudioListener: 678 | m_ObjectHideFlags: 0 679 | m_PrefabParentObject: {fileID: 0} 680 | m_PrefabInternal: {fileID: 0} 681 | m_GameObject: {fileID: 1246330093} 682 | m_Enabled: 1 683 | --- !u!124 &1246330095 684 | Behaviour: 685 | m_ObjectHideFlags: 0 686 | m_PrefabParentObject: {fileID: 0} 687 | m_PrefabInternal: {fileID: 0} 688 | m_GameObject: {fileID: 1246330093} 689 | m_Enabled: 1 690 | --- !u!92 &1246330096 691 | Behaviour: 692 | m_ObjectHideFlags: 0 693 | m_PrefabParentObject: {fileID: 0} 694 | m_PrefabInternal: {fileID: 0} 695 | m_GameObject: {fileID: 1246330093} 696 | m_Enabled: 1 697 | --- !u!20 &1246330097 698 | Camera: 699 | m_ObjectHideFlags: 0 700 | m_PrefabParentObject: {fileID: 0} 701 | m_PrefabInternal: {fileID: 0} 702 | m_GameObject: {fileID: 1246330093} 703 | m_Enabled: 1 704 | serializedVersion: 2 705 | m_ClearFlags: 1 706 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 707 | m_NormalizedViewPortRect: 708 | serializedVersion: 2 709 | x: 0 710 | y: 0 711 | width: 1 712 | height: 1 713 | near clip plane: 0.3 714 | far clip plane: 1000 715 | field of view: 60 716 | orthographic: 0 717 | orthographic size: 5 718 | m_Depth: -1 719 | m_CullingMask: 720 | serializedVersion: 2 721 | m_Bits: 4294967295 722 | m_RenderingPath: -1 723 | m_TargetTexture: {fileID: 0} 724 | m_TargetDisplay: 0 725 | m_TargetEye: 3 726 | m_HDR: 1 727 | m_AllowMSAA: 1 728 | m_ForceIntoRT: 0 729 | m_OcclusionCulling: 1 730 | m_StereoConvergence: 10 731 | m_StereoSeparation: 0.022 732 | --- !u!4 &1246330098 733 | Transform: 734 | m_ObjectHideFlags: 0 735 | m_PrefabParentObject: {fileID: 0} 736 | m_PrefabInternal: {fileID: 0} 737 | m_GameObject: {fileID: 1246330093} 738 | m_LocalRotation: {x: 0.17364816, y: 0, z: 0, w: 0.9848078} 739 | m_LocalPosition: {x: 0, y: 5, z: -10} 740 | m_LocalScale: {x: 1, y: 1, z: 1} 741 | m_Children: [] 742 | m_Father: {fileID: 0} 743 | m_RootOrder: 1 744 | m_LocalEulerAnglesHint: {x: 20, y: 0, z: 0} 745 | --- !u!1 &1847080531 746 | GameObject: 747 | m_ObjectHideFlags: 0 748 | m_PrefabParentObject: {fileID: 0} 749 | m_PrefabInternal: {fileID: 0} 750 | serializedVersion: 5 751 | m_Component: 752 | - component: {fileID: 1847080533} 753 | - component: {fileID: 1847080532} 754 | m_Layer: 0 755 | m_Name: NATIVE_BRIDGE 756 | m_TagString: Untagged 757 | m_Icon: {fileID: 0} 758 | m_NavMeshLayer: 0 759 | m_StaticEditorFlags: 0 760 | m_IsActive: 1 761 | --- !u!114 &1847080532 762 | MonoBehaviour: 763 | m_ObjectHideFlags: 0 764 | m_PrefabParentObject: {fileID: 0} 765 | m_PrefabInternal: {fileID: 0} 766 | m_GameObject: {fileID: 1847080531} 767 | m_Enabled: 1 768 | m_EditorHideFlags: 0 769 | m_Script: {fileID: 11500000, guid: 56af77ba11fdc4c64b7cf028857d3f71, type: 3} 770 | m_Name: 771 | m_EditorClassIdentifier: 772 | toggle: {fileID: 150674533} 773 | --- !u!4 &1847080533 774 | Transform: 775 | m_ObjectHideFlags: 0 776 | m_PrefabParentObject: {fileID: 0} 777 | m_PrefabInternal: {fileID: 0} 778 | m_GameObject: {fileID: 1847080531} 779 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 780 | m_LocalPosition: {x: 0, y: 0, z: 0} 781 | m_LocalScale: {x: 1, y: 1, z: 1} 782 | m_Children: [] 783 | m_Father: {fileID: 0} 784 | m_RootOrder: 0 785 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 786 | --- !u!1 &1871201454 787 | GameObject: 788 | m_ObjectHideFlags: 0 789 | m_PrefabParentObject: {fileID: 0} 790 | m_PrefabInternal: {fileID: 0} 791 | serializedVersion: 5 792 | m_Component: 793 | - component: {fileID: 1871201458} 794 | - component: {fileID: 1871201457} 795 | - component: {fileID: 1871201456} 796 | - component: {fileID: 1871201455} 797 | m_Layer: 5 798 | m_Name: Canvas 799 | m_TagString: Untagged 800 | m_Icon: {fileID: 0} 801 | m_NavMeshLayer: 0 802 | m_StaticEditorFlags: 0 803 | m_IsActive: 1 804 | --- !u!114 &1871201455 805 | MonoBehaviour: 806 | m_ObjectHideFlags: 0 807 | m_PrefabParentObject: {fileID: 0} 808 | m_PrefabInternal: {fileID: 0} 809 | m_GameObject: {fileID: 1871201454} 810 | m_Enabled: 1 811 | m_EditorHideFlags: 0 812 | m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 813 | m_Name: 814 | m_EditorClassIdentifier: 815 | m_IgnoreReversedGraphics: 1 816 | m_BlockingObjects: 0 817 | m_BlockingMask: 818 | serializedVersion: 2 819 | m_Bits: 4294967295 820 | --- !u!114 &1871201456 821 | MonoBehaviour: 822 | m_ObjectHideFlags: 0 823 | m_PrefabParentObject: {fileID: 0} 824 | m_PrefabInternal: {fileID: 0} 825 | m_GameObject: {fileID: 1871201454} 826 | m_Enabled: 1 827 | m_EditorHideFlags: 0 828 | m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} 829 | m_Name: 830 | m_EditorClassIdentifier: 831 | m_UiScaleMode: 2 832 | m_ReferencePixelsPerUnit: 150 833 | m_ScaleFactor: 1 834 | m_ReferenceResolution: {x: 800, y: 600} 835 | m_ScreenMatchMode: 0 836 | m_MatchWidthOrHeight: 1 837 | m_PhysicalUnit: 3 838 | m_FallbackScreenDPI: 96 839 | m_DefaultSpriteDPI: 96 840 | m_DynamicPixelsPerUnit: 1 841 | --- !u!223 &1871201457 842 | Canvas: 843 | m_ObjectHideFlags: 0 844 | m_PrefabParentObject: {fileID: 0} 845 | m_PrefabInternal: {fileID: 0} 846 | m_GameObject: {fileID: 1871201454} 847 | m_Enabled: 1 848 | serializedVersion: 3 849 | m_RenderMode: 0 850 | m_Camera: {fileID: 0} 851 | m_PlaneDistance: 100 852 | m_PixelPerfect: 1 853 | m_ReceivesEvents: 1 854 | m_OverrideSorting: 0 855 | m_OverridePixelPerfect: 0 856 | m_SortingBucketNormalizedSize: 0 857 | m_AdditionalShaderChannelsFlag: 0 858 | m_SortingLayerID: 0 859 | m_SortingOrder: 0 860 | m_TargetDisplay: 0 861 | --- !u!224 &1871201458 862 | RectTransform: 863 | m_ObjectHideFlags: 0 864 | m_PrefabParentObject: {fileID: 0} 865 | m_PrefabInternal: {fileID: 0} 866 | m_GameObject: {fileID: 1871201454} 867 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 868 | m_LocalPosition: {x: 814, y: 449, z: 0} 869 | m_LocalScale: {x: 3.5555556, y: 3.5555556, z: 3.5555556} 870 | m_Children: 871 | - {fileID: 150674532} 872 | m_Father: {fileID: 0} 873 | m_RootOrder: 4 874 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 875 | m_AnchorMin: {x: 0.5, y: 0.5} 876 | m_AnchorMax: {x: 0.5, y: 0.5} 877 | m_AnchoredPosition: {x: 0, y: 0} 878 | m_SizeDelta: {x: 100, y: 100} 879 | m_Pivot: {x: 0.5, y: 0.5} 880 | -------------------------------------------------------------------------------- /demo/unity/Assets/Demo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6186caa60bfc5401ab508b7c9a00f895 3 | timeCreated: 1506464245 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77702b3aabdf549e1b191b66437644fa 3 | folderAsset: yes 4 | timeCreated: 1506464168 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/CubeController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class CubeController : MonoBehaviour 4 | { 5 | public static CubeController I { get; private set; } 6 | 7 | public bool ShouldRotate { get; set; } 8 | 9 | private Rigidbody rigibody; 10 | 11 | private float torqueTime; 12 | 13 | private Vector3 torque; 14 | 15 | private void Awake() 16 | { 17 | I = this; 18 | rigibody = GetComponent(); 19 | } 20 | 21 | private void Update() 22 | { 23 | if (ShouldRotate) 24 | { 25 | rigibody.angularDrag = 0.05f; 26 | } 27 | else 28 | { 29 | rigibody.angularDrag = 1f; 30 | } 31 | } 32 | 33 | private void FixedUpdate() 34 | { 35 | if (ShouldRotate) 36 | { 37 | UpdateTorque(); 38 | } 39 | } 40 | 41 | private void UpdateTorque() 42 | { 43 | if (torqueTime <= 0) 44 | { 45 | torqueTime = Random.Range(0.5f, 2f); 46 | torque = Random.insideUnitSphere * Random.Range(1f, 3f); 47 | } 48 | 49 | torqueTime -= Time.fixedDeltaTime; 50 | 51 | rigibody.AddTorque(torque, ForceMode.Force); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/CubeController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 000c2463d03e74174affecfd67093ee1 3 | timeCreated: 1506464465 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 809cbe0fed1844ca98169ef7c57f9b1c 3 | folderAsset: yes 4 | timeCreated: 1506464173 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/Editor/XcodePostBuild.cs: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2017 Jiulong Wang 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #if UNITY_IOS 26 | 27 | using System; 28 | using System.Linq; 29 | using System.Collections.Generic; 30 | using System.IO; 31 | using System.Text; 32 | 33 | using UnityEngine; 34 | using UnityEditor; 35 | using UnityEditor.Callbacks; 36 | using UnityEditor.iOS.Xcode; 37 | 38 | /// 39 | /// Adding this post build script to Unity project enables Unity iOS build output to be embedded 40 | /// into existing Xcode Swift project. 41 | /// 42 | /// However, since this script touches Unity iOS build output, you will not be able to use Unity 43 | /// iOS build directly in Xcode. As a result, it is recommended to put Unity iOS build output into 44 | /// a temporary directory that you generally do not touch, such as '/tmp'. 45 | /// 46 | /// In order for this to work, necessary changes to the target Xcode Swift project are needed. 47 | /// Especially the 'AppDelegate.swift' should be modified to properly initialize Unity. 48 | /// See https://github.com/jiulongw/swift-unity for details. 49 | /// 50 | public class XcodePostBuild : EditorWindow 51 | { 52 | /// 53 | /// The version of Unity for which we need to edit Unity's Metal code. 54 | /// 55 | static Version UNITY_VERSION_FOR_METAL_HELPER = ParseUnityVersionNumber("2017.1.1f1"); 56 | 57 | /// 58 | /// The minimum versino of Unity for which we need to edit Unity's splash-screen code. 59 | static Version MIN_UNITY_VERSION_FOR_SPLASH_SCREEN = new Version(2017, 3, 0); 60 | 61 | /// 62 | /// Set to false to disable this post-processor, so you can build proper iOS app projects 63 | /// from the same code base. 64 | /// 65 | private bool enabled = true; 66 | 67 | /// 68 | /// Path to the Xcode project. 69 | /// 70 | private string XcodeProjectPath; 71 | 72 | /// 73 | /// Path to the root directory of Xcode project. 74 | /// This should point to the directory of '${XcodeProjectName}.xcodeproj'. 75 | /// It is recommended to use relative path here. 76 | /// Current directory is the root directory of this Unity project, i.e. the directory that contains the 'Assets' folder. 77 | /// Sample value: "../xcode" 78 | /// 79 | private string XcodeProjectRoot { get { return Path.GetDirectoryName(XcodeProjectPath); } } 80 | 81 | /// 82 | /// Name of the Xcode project. 83 | /// This script looks for '${XcodeProjectName} + ".xcodeproj"' under '${XcodeProjectRoot}'. 84 | /// Sample value: "DemoApp" 85 | /// 86 | private string XcodeProjectName { get { return Path.GetFileNameWithoutExtension(XcodeProjectPath); } } 87 | 88 | 89 | /// 90 | /// The URL to the Git repository where this project originated. 91 | /// 92 | private const string PROJECT_URL = "https://github.com/jiulongw/swift-unity"; 93 | 94 | /// 95 | /// The identifier added to touched file to avoid double edits when building to existing directory without 96 | /// replace existing content. 97 | /// 98 | private const string TOUCH_MARKER = PROJECT_URL + "#v1"; 99 | 100 | /// 101 | /// A GUIStyle object for rendering links. 102 | /// 103 | private static GUIStyle LINK_STYLE; 104 | 105 | /// 106 | /// Creates a menu item in the Tools menu that opens an Editor Window 107 | /// for editing configuration values for the post build process. 108 | /// 109 | [MenuItem("Tools/SwiftUnity")] 110 | public static void ShowConfiguration() 111 | { 112 | GetWindow(); 113 | } 114 | 115 | static string[] XCODEPROJ_FILTER = { "Xcode project files", "xcodeproj" }; 116 | 117 | /// 118 | /// Builds the GUI for the custom editor window for this post process step. 119 | /// Find it under `Tools > Swift-Unity`. 120 | void OnGUI() 121 | { 122 | GUILayout.Label("Swift-Unity", EditorStyles.boldLabel); 123 | 124 | enabled = EditorGUILayout.BeginToggleGroup("Enabled", enabled); 125 | { 126 | ShowProjectDescription(); 127 | ShowSettings(); 128 | } 129 | 130 | ShowRerunButton(); 131 | EditorGUILayout.EndToggleGroup(); 132 | } 133 | 134 | private void ShowSettings() 135 | { 136 | GUILayout.Label("Settings", EditorStyles.boldLabel); 137 | 138 | // If we don't have a directory root for the xcode project, just make a wild 139 | // guess at one to give the user a starting point for navigating to the real one. 140 | if (!Directory.Exists(XcodeProjectPath)) 141 | { 142 | XcodeProjectPath = null; 143 | } 144 | 145 | if (string.IsNullOrEmpty(XcodeProjectPath)) 146 | { 147 | XcodeProjectPath = PathExt.Combine( 148 | Path.GetDirectoryName(Environment.CurrentDirectory), 149 | "Xcode-Project.xcodeproj"); 150 | } 151 | 152 | // Instead of defining the xcode project root and name separately, have the user 153 | // select the .xcodeproj file and then figure them out from there. 154 | var xcodeProjectFile = PathExt.Abs2Rel(XcodeProjectPath); 155 | xcodeProjectFile = EditorGUILayout.TextField("Xcode Project File", xcodeProjectFile); 156 | 157 | if (GUILayout.Button("Browse...")) 158 | { 159 | string userSelection = null; 160 | if (Environment.OSVersion.Platform == PlatformID.MacOSX) 161 | { 162 | userSelection = EditorUtility.OpenFilePanelWithFilters( 163 | "Select Xcode project file", 164 | Path.GetDirectoryName(XcodeProjectPath), 165 | XCODEPROJ_FILTER); 166 | } 167 | else 168 | { 169 | userSelection = EditorUtility.OpenFolderPanel( 170 | "Select Xcode project file", 171 | Path.GetDirectoryName(XcodeProjectPath), 172 | "Xcode-Project.xcodeproj"); 173 | } 174 | 175 | if (!string.IsNullOrEmpty(userSelection)) 176 | { 177 | xcodeProjectFile = PathExt.Abs2Rel(userSelection); 178 | } 179 | } 180 | 181 | XcodeProjectPath = PathExt.Rel2Abs(xcodeProjectFile); 182 | } 183 | 184 | /// 185 | /// TODO: remove this once all the bugs are worked out. This saves us a little 186 | /// time by avoiding having to run the full Unity build every time we want to 187 | /// validate the post process. 188 | /// 189 | private static void ShowRerunButton() 190 | { 191 | // Displaying the current build location serves as a reminder to the user what is going on. 192 | var currentBuildLocation = EditorUserBuildSettings.GetBuildLocation(BuildTarget.iOS); 193 | bool hasBuildLocation = !string.IsNullOrEmpty(currentBuildLocation); 194 | 195 | if (hasBuildLocation) 196 | { 197 | currentBuildLocation = PathExt.Abs2Rel(currentBuildLocation); 198 | } 199 | else 200 | { 201 | currentBuildLocation = ""; 202 | } 203 | 204 | GUILayout.Label( 205 | string.Format( 206 | "Current Build Location: {0}", 207 | currentBuildLocation)); 208 | 209 | if (hasBuildLocation && GUILayout.Button("Run post-build process")) 210 | { 211 | OnPostBuild(BuildTarget.iOS, currentBuildLocation); 212 | } 213 | else 214 | { 215 | GUILayout.Label("Please run build process for iOS."); 216 | } 217 | } 218 | 219 | private static void ShowProjectDescription() 220 | { 221 | GUILayout.Label(@"Enables Unity iOS build output to be embedded into existing Xcode Swift project. 222 | 223 | However, since this script touches Unity iOS build output, you will not be able to use Unity iOS build directly in Xcode. As a result, it is recommended to put Unity iOS build output into a temporary directory that you generally do not touch, such as '/tmp'. 224 | 225 | In order for this to work, necessary changes to the target Xcode Swift project are needed. Especially the 'AppDelegate.swift' should be modified to properly initialize Unity. For details, see:", 226 | EditorStyles.wordWrappedLabel); 227 | 228 | // Creating the GUIStyle can't be done in a normal constructor 229 | // context because of some weird Unity restriction. 230 | if (LINK_STYLE == null) 231 | { 232 | var blackTransparent = new Color(0, 0, 0, 0); 233 | var transparent = new Texture2D(4, 4, TextureFormat.ARGB32, false); 234 | for (int y = 0; y < transparent.height; ++y) 235 | { 236 | for (int x = 0; x < transparent.width; ++x) 237 | { 238 | transparent.SetPixel(x, y, blackTransparent); 239 | } 240 | } 241 | transparent.Apply(false); 242 | 243 | LINK_STYLE = new GUIStyle(GUI.skin.label); 244 | 245 | LINK_STYLE.normal.background 246 | = LINK_STYLE.onNormal.background 247 | = transparent; 248 | LINK_STYLE.normal.textColor 249 | = LINK_STYLE.onNormal.textColor 250 | = Color.Lerp(Color.blue, Color.white, 0.5f); 251 | 252 | LINK_STYLE.focused.background 253 | = LINK_STYLE.onFocused.background 254 | = LINK_STYLE.hover.background 255 | = LINK_STYLE.onHover.background 256 | = transparent; 257 | LINK_STYLE.focused.textColor 258 | = LINK_STYLE.onFocused.textColor 259 | = LINK_STYLE.hover.textColor 260 | = LINK_STYLE.onHover.textColor 261 | = Color.Lerp(Color.cyan, Color.white, 0.5f); 262 | } 263 | 264 | if (GUILayout.Button(PROJECT_URL, LINK_STYLE)) 265 | { 266 | Application.OpenURL(PROJECT_URL); 267 | } 268 | } 269 | 270 | [PostProcessBuild] 271 | public static void OnPostBuild(BuildTarget target, string pathToBuiltProject) 272 | { 273 | var build = GetWindow(); 274 | if (build.enabled && target == BuildTarget.iOS) 275 | { 276 | PatchUnityNativeCode(pathToBuiltProject); 277 | build.UpdateUnityIOSExports(pathToBuiltProject); 278 | build.UpdateUnityProjectFiles(pathToBuiltProject); 279 | } 280 | } 281 | 282 | /// 283 | /// Writes current Unity version and output path to 'Exports.xcconfig' file. 284 | /// 285 | void UpdateUnityIOSExports(string pathToBuiltProject) 286 | { 287 | var config = new StringBuilder(); 288 | config.AppendFormat("UNITY_RUNTIME_VERSION = {0};{1}", Application.unityVersion, Environment.NewLine); 289 | config.AppendFormat("UNITY_IOS_EXPORT_PATH = {0};{1}", pathToBuiltProject, Environment.NewLine); 290 | 291 | var unityDir = PathExt.Combine(XcodeProjectRoot, XcodeProjectName, "Unity"); 292 | Directory.CreateDirectory(unityDir); 293 | var ExportsConfigProjectPath = PathExt.Combine(unityDir, "Exports.xcconfig"); 294 | File.WriteAllText(ExportsConfigProjectPath, config.ToString()); 295 | } 296 | 297 | static void CopyFile(string srcPath, string destPath) 298 | { 299 | Directory.CreateDirectory(Path.GetDirectoryName(destPath)); 300 | File.Copy(srcPath, destPath, true); 301 | } 302 | 303 | /// 304 | /// Enumerates Unity output files and add necessary files into Xcode project file. 305 | /// It only add a reference entry into project.pbx file, without actually copy it. 306 | /// Xcode pre-build script will copy files into correct location. 307 | /// 308 | void UpdateUnityProjectFiles(string pathToBuiltProject) 309 | { 310 | var pbxPath = PathExt.Combine( 311 | XcodeProjectRoot, 312 | Path.ChangeExtension(XcodeProjectName, "xcodeproj"), 313 | "project.pbxproj"); 314 | var pbx = new PBXProject(); 315 | pbx.ReadFromFile(pbxPath); 316 | 317 | string classesPath = PathExt.Combine(XcodeProjectName, "Unity", "Classes"); 318 | ProcessUnityDirectory( 319 | pbx, 320 | PathExt.Combine(pathToBuiltProject, "Classes"), 321 | PathExt.Combine(XcodeProjectRoot, classesPath), 322 | classesPath); 323 | 324 | string librariesPath = PathExt.Combine(XcodeProjectName, "Unity", "Libraries"); 325 | ProcessUnityDirectory( 326 | pbx, 327 | PathExt.Combine(pathToBuiltProject, "Libraries"), 328 | PathExt.Combine(XcodeProjectRoot, librariesPath), 329 | librariesPath); 330 | 331 | pbx.WriteToFile(pbxPath); 332 | } 333 | 334 | /// 335 | /// Update pbx project file by adding src files and removing extra files that 336 | /// exists in dest but not in src any more. 337 | /// 338 | /// This method only updates the pbx project file. It does not copy or delete 339 | /// files in Swift Xcode project. The Swift Xcode project will do copy and delete 340 | /// during build, and it should copy files if contents are different, regardless 341 | /// of the file time. 342 | /// 343 | /// The pbx project. 344 | /// The directory where Unity project is built. 345 | /// The directory of the Swift Xcode project where the 346 | /// Unity project is embedded into. 347 | /// The prefix of project path in Swift Xcode 348 | /// project for Unity code files. E.g. "DempApp/Unity/Classes" for all files 349 | /// under Classes folder from Unity iOS build output. 350 | void ProcessUnityDirectory(PBXProject pbx, string src, string dest, string projectPathPrefix) 351 | { 352 | var targetGuid = pbx.TargetGuidByName(XcodeProjectName); 353 | if (string.IsNullOrEmpty(targetGuid)) 354 | { 355 | throw new Exception(string.Format("TargetGuid could not be found for '{0}'", XcodeProjectName)); 356 | } 357 | 358 | // newFiles: array of file names in build output that do not exist in project.pbx manifest. 359 | // extraFiles: array of file names in project.pbx manifest that do not exist in build output. 360 | // Build output files that already exist in project.pbx manifest will be skipped to minimize 361 | // changes to project.pbx file. 362 | string[] newFiles, extraFiles; 363 | CompareDirectories(src, dest, out newFiles, out extraFiles); 364 | 365 | foreach (var projPath in 366 | from f in newFiles 367 | where !f.EndsWith(".bak", StringComparison.OrdinalIgnoreCase) 368 | let projPath = Path.Combine(projectPathPrefix, f) 369 | where !pbx.ContainsFileByProjectPath(projPath) 370 | select projPath) 371 | { 372 | var guid = pbx.AddFile(projPath, projPath); 373 | pbx.AddFileToBuild(targetGuid, guid); 374 | 375 | Debug.LogFormat("Added file to pbx: '{0}'", projPath); 376 | } 377 | 378 | foreach (var projPath in 379 | from f in extraFiles 380 | let projPath = PathExt.Combine(projectPathPrefix, f) 381 | where pbx.ContainsFileByProjectPath(projPath) 382 | select projPath) 383 | { 384 | var guid = pbx.FindFileGuidByProjectPath(projPath); 385 | pbx.RemoveFile(guid); 386 | 387 | Debug.LogFormat("Removed file from pbx: '{0}'", projPath); 388 | } 389 | } 390 | 391 | /// 392 | /// Compares the directories. Returns files that exists in src and 393 | /// extra files that exists in dest but not in src any more. 394 | /// 395 | private static void CompareDirectories(string src, string dest, out string[] srcFiles, out string[] extraFiles) 396 | { 397 | srcFiles = GetFilesRelativePath(src); 398 | 399 | var destFiles = GetFilesRelativePath(dest); 400 | var extraFilesSet = new HashSet(destFiles); 401 | 402 | extraFilesSet.ExceptWith(srcFiles); 403 | extraFiles = extraFilesSet.ToArray(); 404 | } 405 | 406 | private static string[] GetFilesRelativePath(string directory) 407 | { 408 | var results = new List(); 409 | 410 | if (Directory.Exists(directory)) 411 | { 412 | foreach (var path in Directory.GetFiles(directory, "*", SearchOption.AllDirectories)) 413 | { 414 | results.Add(PathExt.Abs2Rel(path, directory)); 415 | } 416 | } 417 | 418 | return results.ToArray(); 419 | } 420 | 421 | /// 422 | /// Replaces the character component of Unity's version number with a period 423 | /// and the decimal ASCII value of that character, to create an ersatz revision 424 | /// number. 425 | /// 426 | /// A Version struct that can be used for range comparisons. 427 | /// Unity's version string, formatted as [YEAR].[MINOR].[PATCH][CHARACTER][REVISION]. 428 | private static Version ParseUnityVersionNumber(string versionString) 429 | { 430 | for (int i = versionString.Length - 1; i >= 0; --i) 431 | { 432 | var token = versionString[i]; 433 | if (char.IsLetter(token)) 434 | { 435 | versionString = versionString 436 | .Remove(i) 437 | .Insert(i, string.Format(".{0}", (int)token)); 438 | } 439 | } 440 | 441 | return new Version(versionString); 442 | } 443 | 444 | /// 445 | /// Make necessary changes to Unity build output that enables it to be embedded into existing Xcode project. 446 | /// 447 | private static void PatchUnityNativeCode(string pathToBuiltProject) 448 | { 449 | var unityVersion = ParseUnityVersionNumber(Application.unityVersion); 450 | 451 | EditMainMM(PathExt.Combine(pathToBuiltProject, "Classes/main.mm")); 452 | EditUnityAppControllerH(PathExt.Combine(pathToBuiltProject, "Classes/UnityAppController.h")); 453 | EditUnityAppControllerMM(PathExt.Combine(pathToBuiltProject, "Classes/UnityAppController.mm")); 454 | 455 | if (unityVersion == UNITY_VERSION_FOR_METAL_HELPER) 456 | { 457 | EditMetalHelperMM(PathExt.Combine(pathToBuiltProject, "Classes/Unity/MetalHelper.mm")); 458 | } 459 | 460 | if (unityVersion >= MIN_UNITY_VERSION_FOR_SPLASH_SCREEN) 461 | { 462 | EditSplashScreenMM(PathExt.Combine(pathToBuiltProject, "Classes/UI/SplashScreen.mm")); 463 | } 464 | } 465 | 466 | /// 467 | /// Edit 'main.mm': removes 'main' entry that would conflict with the Xcode project it embeds into. 468 | /// 469 | private static void EditMainMM(string path) 470 | { 471 | EditCodeFile(path, line => 472 | { 473 | if (line.TrimStart().StartsWith("int main", StringComparison.Ordinal)) 474 | { 475 | return line.Replace("int main", "int old_main"); 476 | } 477 | 478 | return line; 479 | }); 480 | } 481 | 482 | /// 483 | /// Edit 'UnityAppController.h': returns 'UnityAppController' from 'AppDelegate' class. 484 | /// 485 | private static void EditUnityAppControllerH(string path) 486 | { 487 | var inScope = false; 488 | var markerDetected = false; 489 | var markerAdded = false; 490 | 491 | EditCodeFile(path, line => 492 | { 493 | markerDetected |= line.Contains(TOUCH_MARKER); 494 | inScope |= line.Contains("inline UnityAppController"); 495 | 496 | if (inScope && !markerDetected) 497 | { 498 | if (line.Trim() == "}") 499 | { 500 | inScope = false; 501 | 502 | return new string[] 503 | { 504 | "// }", 505 | "", 506 | "NS_INLINE UnityAppController* GetAppController()", 507 | "{", 508 | " NSObject* delegate = [UIApplication sharedApplication].delegate;", 509 | @" UnityAppController* currentUnityController = (UnityAppController*)[delegate valueForKey: @""currentUnityController""];", 510 | " return currentUnityController;", 511 | "}", 512 | }; 513 | } 514 | 515 | if (!markerAdded) 516 | { 517 | markerAdded = true; 518 | return new string[] 519 | { 520 | "// Modified by " + TOUCH_MARKER, 521 | "// " + line, 522 | }; 523 | } 524 | 525 | return new string[] { "// " + line }; 526 | } 527 | 528 | return new string[] { line }; 529 | }); 530 | } 531 | 532 | /// 533 | /// Edit 'UnityAppController.mm': triggers 'UnityReady' notification after Unity is actually started. 534 | /// 535 | private static void EditUnityAppControllerMM(string path) 536 | { 537 | var inScope = false; 538 | var markerDetected = false; 539 | 540 | EditCodeFile(path, line => 541 | { 542 | inScope |= line.Contains("- (void)startUnity:"); 543 | markerDetected |= inScope && line.Contains(TOUCH_MARKER); 544 | 545 | if (inScope && line.Trim() == "}") 546 | { 547 | inScope = false; 548 | 549 | if (markerDetected) 550 | { 551 | return new string[] { line }; 552 | } 553 | else 554 | { 555 | return new string[] 556 | { 557 | " // Modified by " + TOUCH_MARKER, 558 | " // Post a notification so that Swift can load unity view once started.", 559 | @" [[NSNotificationCenter defaultCenter] postNotificationName: @""UnityReady"" object:self];", 560 | "}", 561 | }; 562 | } 563 | } 564 | 565 | return new string[] { line }; 566 | }); 567 | } 568 | 569 | /// 570 | /// Edit 'MetalHelper.mm': fixes a bug (only in 2017.1.1f1) that causes crash. 571 | /// 572 | private static void EditMetalHelperMM(string path) 573 | { 574 | var markerDetected = false; 575 | 576 | EditCodeFile(path, line => 577 | { 578 | markerDetected |= line.Contains(TOUCH_MARKER); 579 | 580 | if (!markerDetected && line.Trim() == "surface->stencilRB = [surface->device newTextureWithDescriptor: stencilTexDesc];") 581 | { 582 | return new string[] 583 | { 584 | "", 585 | " // Modified by " + TOUCH_MARKER, 586 | " // Default stencilTexDesc.usage has flag 1. In runtime it will cause assertion failure:", 587 | " // validateRenderPassDescriptor:589: failed assertion `Texture at stencilAttachment has usage (0x01) which doesn't specify MTLTextureUsageRenderTarget (0x04)'", 588 | " // Adding MTLTextureUsageRenderTarget seems to fix this issue.", 589 | " stencilTexDesc.usage |= MTLTextureUsageRenderTarget;", 590 | line, 591 | }; 592 | } 593 | 594 | return new string[] { line }; 595 | }); 596 | } 597 | 598 | /// 599 | /// Edit 'SplashScreen.mm': Unity introduces its own 'LaunchScreen.storyboard' since 2017.3.0f3. 600 | /// Disable it here and use Swift project's launch screen instead. 601 | /// 602 | private static void EditSplashScreenMM(string path) 603 | { 604 | var markerDetected = false; 605 | var markerAdded = false; 606 | var inScope = false; 607 | var level = 0; 608 | 609 | EditCodeFile(path, line => 610 | { 611 | inScope |= line.Trim() == "void ShowSplashScreen(UIWindow* window)"; 612 | markerDetected |= line.Contains(TOUCH_MARKER); 613 | 614 | if (inScope && !markerDetected) 615 | { 616 | if (line.Trim() == "{") 617 | { 618 | level++; 619 | } 620 | else if (line.Trim() == "}") 621 | { 622 | level--; 623 | } 624 | 625 | if (line.Trim() == "}" && level == 0) 626 | { 627 | inScope = false; 628 | } 629 | 630 | if (level > 0 && line.Trim().StartsWith("bool hasStoryboard", StringComparison.Ordinal)) 631 | { 632 | return new string[] 633 | { 634 | " // " + line, 635 | " bool hasStoryboard = false;", 636 | }; 637 | } 638 | 639 | if (!markerAdded) 640 | { 641 | markerAdded = true; 642 | return new string[] 643 | { 644 | "// Modified by " + TOUCH_MARKER, 645 | line, 646 | }; 647 | } 648 | } 649 | 650 | return new string[] { line }; 651 | }); 652 | } 653 | 654 | private static void EditCodeFile(string path, Func lineHandler) 655 | { 656 | EditCodeFile(path, line => 657 | { 658 | return new string[] { lineHandler(line) }; 659 | }); 660 | } 661 | 662 | private static void EditCodeFile(string path, Func> lineHandler) 663 | { 664 | var bakPath = path + ".bak"; 665 | File.Copy(path, bakPath, true); 666 | 667 | using (var reader = File.OpenText(bakPath)) 668 | using (var stream = File.Create(path)) 669 | using (var writer = new StreamWriter(stream)) 670 | { 671 | string line; 672 | while ((line = reader.ReadLine()) != null) 673 | { 674 | var outputs = lineHandler(line); 675 | foreach (var o in outputs) 676 | { 677 | writer.WriteLine(o); 678 | } 679 | } 680 | } 681 | } 682 | } 683 | 684 | /// 685 | /// A static class containing a few functions that the normal System.IO.Path class does not contain. 686 | /// 687 | public static class PathExt 688 | { 689 | /// 690 | /// Creates a path-like value for the current system, given a variable number of path parts. 691 | /// Path parts may be directories or files. The path parts are not validated against the file 692 | /// system. 693 | /// 694 | /// The parts array, encoded into a single string, with System.IO.Path.DirectorySeparatorChar 695 | /// separating individual parts 696 | /// 697 | /// .NET 3.5 does not have a Path.Combine function that takes a variadric 698 | /// array of path parts as a parameter. On Unity projects using the .NET 699 | /// 3.5 runtime, we have to wrap it up and implement our own version. 700 | /// 701 | /// The path parts to combine into a path value. 702 | public static string Combine(params string[] parts) 703 | { 704 | #if NET_2_0 || NET_2_0_SUBSET 705 | if (parts == null || parts.Length == 0) 706 | { 707 | return null; 708 | } 709 | else 710 | { 711 | return string.Join(Path.DirectorySeparatorChar.ToString(), parts); 712 | } 713 | #else 714 | return Path.Combine(parts); 715 | #endif 716 | } 717 | 718 | /// 719 | /// Creates a file path that is relative to the currently-edited demo path. 720 | /// 721 | /// The relative path. 722 | /// Full path. 723 | /// The directory from which to consider the relative path. If no value 724 | /// is provided (i.e. `null` or empty string), then the current working directory is used. 725 | public static string Abs2Rel(string fullPath, string directory = null) 726 | { 727 | if (!Path.IsPathRooted(fullPath)) 728 | { 729 | return fullPath; 730 | } 731 | else 732 | { 733 | if (string.IsNullOrEmpty(directory)) 734 | { 735 | directory = Environment.CurrentDirectory; 736 | } 737 | 738 | var partsA = directory.Split('/', '\\').ToList(); 739 | var partsB = fullPath.Split('/', '\\').ToList(); 740 | 741 | while (partsA.Count > 0 742 | && partsB.Count > 0 743 | && partsA[0] == partsB[0]) 744 | { 745 | partsA.RemoveAt(0); 746 | partsB.RemoveAt(0); 747 | } 748 | 749 | if (partsB.Count == 0) 750 | { 751 | return null; 752 | } 753 | else 754 | { 755 | return Combine(partsA 756 | .Select(_ => "..") 757 | .Concat(partsB) 758 | .ToArray()); 759 | } 760 | } 761 | } 762 | 763 | /// 764 | /// Resolves an absolute path from a path that is relative to the currently-edited 765 | /// demo path. 766 | /// 767 | /// The absolute path. 768 | /// Relative path. 769 | /// The directory from which to consider the relative path. If no value 770 | /// is provided (i.e. `null` or empty string), then the current working directory is used. 771 | public static string Rel2Abs(string relativePath, string directory = null) 772 | { 773 | if (Path.IsPathRooted(relativePath)) 774 | { 775 | return relativePath; 776 | } 777 | else 778 | { 779 | if (string.IsNullOrEmpty(directory)) 780 | { 781 | directory = Environment.CurrentDirectory; 782 | } 783 | 784 | var partsA = directory.Split('/', '\\').ToList(); 785 | var partsB = relativePath.Split('/', '\\').ToList(); 786 | 787 | while (partsA.Count > 0 788 | && partsB.Count > 0 789 | && partsB[0] == "..") 790 | { 791 | partsA.RemoveAt(partsA.Count - 1); 792 | partsB.RemoveAt(0); 793 | } 794 | 795 | if (partsB.Count == 0) 796 | { 797 | return null; 798 | } 799 | else 800 | { 801 | return Combine(partsA 802 | .Concat(partsB) 803 | .ToArray()); 804 | } 805 | } 806 | } 807 | } 808 | 809 | #endif 810 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/Editor/XcodePostBuild.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f305ff06bcc149f3b1190af05c25278 3 | timeCreated: 1506464182 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/NativeBridge.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using UnityEngine; 3 | using UnityEngine.UI; 4 | 5 | public class NativeBridge : MonoBehaviour 6 | { 7 | [SerializeField] 8 | private Toggle toggle; 9 | 10 | private bool skipToggleChangeEvent; 11 | 12 | #if UNITY_IOS && !UNITY_EDITOR 13 | [DllImport("__Internal")] 14 | private extern static void UnityToggleRotation(bool isOn); 15 | #else 16 | private void UnityToggleRotation(bool isOn) 17 | { 18 | RotateCube(isOn ? "start" : "stop"); 19 | } 20 | #endif 21 | 22 | public void OnToggleValueChanged(bool isOn) 23 | { 24 | if (!skipToggleChangeEvent) 25 | { 26 | 27 | UnityToggleRotation(isOn); 28 | 29 | } 30 | 31 | CubeController.I.ShouldRotate = isOn; 32 | } 33 | 34 | private void RotateCube(string command) 35 | { 36 | switch (command) 37 | { 38 | case "start": 39 | CubeController.I.ShouldRotate = true; 40 | break; 41 | case "stop": 42 | CubeController.I.ShouldRotate = false; 43 | break; 44 | } 45 | 46 | skipToggleChangeEvent = true; 47 | toggle.isOn = CubeController.I.ShouldRotate; 48 | skipToggleChangeEvent = false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /demo/unity/Assets/Scripts/NativeBridge.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56af77ba11fdc4c64b7cf028857d3f71 3 | timeCreated: 1506464301 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 0 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_EnablePCM: 1 18 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 19 | m_AutoSimulation: 1 20 | m_AutoSyncTransforms: 1 21 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: [] 8 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_DefaultBehaviorMode: 0 10 | m_SpritePackerMode: 0 11 | m_SpritePackerPaddingPower: 1 12 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 13 | m_ProjectGenerationRootNamespace: 14 | m_UserGeneratedProjectSuffix: 15 | m_CollabEditorSettings: 16 | inProgressEnabled: 1 17 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 39 | m_PreloadedShaders: [] 40 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 41 | type: 0} 42 | m_CustomRenderPipeline: {fileID: 0} 43 | m_TransparencySortMode: 0 44 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 45 | m_DefaultRenderingPath: 1 46 | m_DefaultMobileRenderingPath: 1 47 | m_TierSettings: [] 48 | m_LightmapStripping: 0 49 | m_FogStripping: 0 50 | m_InstancingStripping: 0 51 | m_LightmapKeepPlain: 1 52 | m_LightmapKeepDirCombined: 1 53 | m_LightmapKeepDynamicPlain: 1 54 | m_LightmapKeepDynamicDirCombined: 1 55 | m_LightmapKeepShadowMask: 1 56 | m_LightmapKeepSubtractive: 1 57 | m_FogKeepLinear: 1 58 | m_FogKeepExp: 1 59 | m_FogKeepExp2: 1 60 | m_AlbedoSwatchInfos: [] 61 | m_LightsUseLinearIntensity: 0 62 | m_LightsUseColorTemperature: 0 63 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | m_SettingNames: 89 | - Humanoid 90 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_AutoSimulation: 1 23 | m_QueriesHitTriggers: 1 24 | m_QueriesStartInColliders: 1 25 | m_ChangeStopsCallbacks: 0 26 | m_CallbacksOnDisable: 1 27 | m_AutoSyncTransforms: 1 28 | m_AlwaysShowColliders: 0 29 | m_ShowColliderSleep: 1 30 | m_ShowColliderContacts: 0 31 | m_ShowColliderAABB: 0 32 | m_ContactArrowScale: 0.2 33 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 34 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 35 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 36 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 37 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 38 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 13 7 | productGUID: bdecf391fd33e43ec9e6680a7af3b2e2 8 | AndroidProfiler: 0 9 | AndroidFilterTouchesWhenObscured: 0 10 | defaultScreenOrientation: 4 11 | targetDevice: 2 12 | useOnDemandResources: 0 13 | accelerometerFrequency: 60 14 | companyName: DefaultCompany 15 | productName: unity 16 | defaultCursor: {fileID: 0} 17 | cursorHotspot: {x: 0, y: 0} 18 | m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} 19 | m_ShowUnitySplashScreen: 1 20 | m_ShowUnitySplashLogo: 1 21 | m_SplashScreenOverlayOpacity: 1 22 | m_SplashScreenAnimation: 1 23 | m_SplashScreenLogoStyle: 1 24 | m_SplashScreenDrawMode: 0 25 | m_SplashScreenBackgroundAnimationZoom: 1 26 | m_SplashScreenLogoAnimationZoom: 1 27 | m_SplashScreenBackgroundLandscapeAspect: 1 28 | m_SplashScreenBackgroundPortraitAspect: 1 29 | m_SplashScreenBackgroundLandscapeUvs: 30 | serializedVersion: 2 31 | x: 0 32 | y: 0 33 | width: 1 34 | height: 1 35 | m_SplashScreenBackgroundPortraitUvs: 36 | serializedVersion: 2 37 | x: 0 38 | y: 0 39 | width: 1 40 | height: 1 41 | m_SplashScreenLogos: [] 42 | m_VirtualRealitySplashScreen: {fileID: 0} 43 | m_HolographicTrackingLossScreen: {fileID: 0} 44 | defaultScreenWidth: 1024 45 | defaultScreenHeight: 768 46 | defaultScreenWidthWeb: 960 47 | defaultScreenHeightWeb: 600 48 | m_StereoRenderingPath: 0 49 | m_ActiveColorSpace: 0 50 | m_MTRendering: 1 51 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 52 | iosShowActivityIndicatorOnLoading: -1 53 | androidShowActivityIndicatorOnLoading: -1 54 | tizenShowActivityIndicatorOnLoading: -1 55 | iosAppInBackgroundBehavior: 0 56 | displayResolutionDialog: 1 57 | iosAllowHTTPDownload: 1 58 | allowedAutorotateToPortrait: 1 59 | allowedAutorotateToPortraitUpsideDown: 1 60 | allowedAutorotateToLandscapeRight: 1 61 | allowedAutorotateToLandscapeLeft: 1 62 | useOSAutorotation: 1 63 | use32BitDisplayBuffer: 1 64 | disableDepthAndStencilBuffers: 0 65 | androidBlitType: 0 66 | defaultIsFullScreen: 1 67 | defaultIsNativeResolution: 1 68 | macRetinaSupport: 1 69 | runInBackground: 0 70 | captureSingleScreen: 0 71 | muteOtherAudioSources: 0 72 | Prepare IOS For Recording: 0 73 | Force IOS Speakers When Recording: 0 74 | submitAnalytics: 1 75 | usePlayerLog: 1 76 | bakeCollisionMeshes: 0 77 | forceSingleInstance: 0 78 | resizableWindow: 0 79 | useMacAppStoreValidation: 0 80 | macAppStoreCategory: public.app-category.games 81 | gpuSkinning: 0 82 | graphicsJobs: 0 83 | xboxPIXTextureCapture: 0 84 | xboxEnableAvatar: 0 85 | xboxEnableKinect: 0 86 | xboxEnableKinectAutoTracking: 0 87 | xboxEnableFitness: 0 88 | visibleInBackground: 1 89 | allowFullscreenSwitch: 1 90 | graphicsJobMode: 0 91 | macFullscreenMode: 2 92 | d3d9FullscreenMode: 1 93 | d3d11FullscreenMode: 1 94 | xboxSpeechDB: 0 95 | xboxEnableHeadOrientation: 0 96 | xboxEnableGuest: 0 97 | xboxEnablePIXSampling: 0 98 | metalFramebufferOnly: 0 99 | n3dsDisableStereoscopicView: 0 100 | n3dsEnableSharedListOpt: 1 101 | n3dsEnableVSync: 0 102 | ignoreAlphaClear: 0 103 | xboxOneResolution: 0 104 | xboxOneMonoLoggingLevel: 0 105 | xboxOneLoggingLevel: 1 106 | xboxOneDisableEsram: 0 107 | xboxOnePresentImmediateThreshold: 0 108 | videoMemoryForVertexBuffers: 0 109 | psp2PowerMode: 0 110 | psp2AcquireBGM: 1 111 | wiiUTVResolution: 0 112 | wiiUGamePadMSAA: 1 113 | wiiUSupportsNunchuk: 0 114 | wiiUSupportsClassicController: 0 115 | wiiUSupportsBalanceBoard: 0 116 | wiiUSupportsMotionPlus: 0 117 | wiiUSupportsProController: 0 118 | wiiUAllowScreenCapture: 1 119 | wiiUControllerCount: 0 120 | m_SupportedAspectRatios: 121 | 4:3: 1 122 | 5:4: 1 123 | 16:10: 1 124 | 16:9: 1 125 | Others: 1 126 | bundleVersion: 1.0 127 | preloadedAssets: [] 128 | metroInputSource: 0 129 | m_HolographicPauseOnTrackingLoss: 1 130 | xboxOneDisableKinectGpuReservation: 0 131 | xboxOneEnable7thCore: 0 132 | vrSettings: 133 | cardboard: 134 | depthFormat: 0 135 | enableTransitionView: 0 136 | daydream: 137 | depthFormat: 0 138 | useSustainedPerformanceMode: 0 139 | enableVideoLayer: 0 140 | useProtectedVideoMemory: 0 141 | hololens: 142 | depthFormat: 1 143 | protectGraphicsMemory: 0 144 | useHDRDisplay: 0 145 | m_ColorGamuts: 00000000 146 | targetPixelDensity: 0 147 | resolutionScalingMode: 0 148 | androidSupportedAspectRatio: 1 149 | androidMaxAspectRatio: 2.1 150 | applicationIdentifier: {} 151 | buildNumber: {} 152 | AndroidBundleVersionCode: 1 153 | AndroidMinSdkVersion: 16 154 | AndroidTargetSdkVersion: 0 155 | AndroidPreferredInstallLocation: 1 156 | aotOptions: 157 | stripEngineCode: 1 158 | iPhoneStrippingLevel: 0 159 | iPhoneScriptCallOptimization: 0 160 | ForceInternetPermission: 0 161 | ForceSDCardPermission: 0 162 | CreateWallpaper: 0 163 | APKExpansionFiles: 0 164 | keepLoadedShadersAlive: 0 165 | StripUnusedMeshComponents: 0 166 | VertexChannelCompressionMask: 167 | serializedVersion: 2 168 | m_Bits: 238 169 | iPhoneSdkVersion: 988 170 | iOSTargetOSVersionString: 7.0 171 | tvOSSdkVersion: 0 172 | tvOSRequireExtendedGameController: 0 173 | tvOSTargetOSVersionString: 9.0 174 | uIPrerenderedIcon: 0 175 | uIRequiresPersistentWiFi: 0 176 | uIRequiresFullScreen: 1 177 | uIStatusBarHidden: 1 178 | uIExitOnSuspend: 0 179 | uIStatusBarStyle: 0 180 | iPhoneSplashScreen: {fileID: 0} 181 | iPhoneHighResSplashScreen: {fileID: 0} 182 | iPhoneTallHighResSplashScreen: {fileID: 0} 183 | iPhone47inSplashScreen: {fileID: 0} 184 | iPhone55inPortraitSplashScreen: {fileID: 0} 185 | iPhone55inLandscapeSplashScreen: {fileID: 0} 186 | iPadPortraitSplashScreen: {fileID: 0} 187 | iPadHighResPortraitSplashScreen: {fileID: 0} 188 | iPadLandscapeSplashScreen: {fileID: 0} 189 | iPadHighResLandscapeSplashScreen: {fileID: 0} 190 | appleTVSplashScreen: {fileID: 0} 191 | tvOSSmallIconLayers: [] 192 | tvOSLargeIconLayers: [] 193 | tvOSTopShelfImageLayers: [] 194 | tvOSTopShelfImageWideLayers: [] 195 | iOSLaunchScreenType: 0 196 | iOSLaunchScreenPortrait: {fileID: 0} 197 | iOSLaunchScreenLandscape: {fileID: 0} 198 | iOSLaunchScreenBackgroundColor: 199 | serializedVersion: 2 200 | rgba: 0 201 | iOSLaunchScreenFillPct: 100 202 | iOSLaunchScreenSize: 100 203 | iOSLaunchScreenCustomXibPath: 204 | iOSLaunchScreeniPadType: 0 205 | iOSLaunchScreeniPadImage: {fileID: 0} 206 | iOSLaunchScreeniPadBackgroundColor: 207 | serializedVersion: 2 208 | rgba: 0 209 | iOSLaunchScreeniPadFillPct: 100 210 | iOSLaunchScreeniPadSize: 100 211 | iOSLaunchScreeniPadCustomXibPath: 212 | iOSDeviceRequirements: [] 213 | iOSURLSchemes: [] 214 | iOSBackgroundModes: 0 215 | iOSMetalForceHardShadows: 0 216 | metalEditorSupport: 0 217 | metalAPIValidation: 1 218 | iOSRenderExtraFrameOnPause: 0 219 | appleDeveloperTeamID: 220 | iOSManualSigningProvisioningProfileID: 221 | tvOSManualSigningProvisioningProfileID: 222 | appleEnableAutomaticSigning: 0 223 | AndroidTargetDevice: 0 224 | AndroidSplashScreenScale: 0 225 | androidSplashScreen: {fileID: 0} 226 | AndroidKeystoreName: 227 | AndroidKeyaliasName: 228 | AndroidTVCompatibility: 1 229 | AndroidIsGame: 1 230 | AndroidEnableTango: 0 231 | androidEnableBanner: 1 232 | androidUseLowAccuracyLocation: 0 233 | m_AndroidBanners: 234 | - width: 320 235 | height: 180 236 | banner: {fileID: 0} 237 | androidGamepadSupportLevel: 0 238 | resolutionDialogBanner: {fileID: 0} 239 | m_BuildTargetIcons: [] 240 | m_BuildTargetBatching: [] 241 | m_BuildTargetGraphicsAPIs: [] 242 | m_BuildTargetVRSettings: [] 243 | m_BuildTargetEnableVuforiaSettings: [] 244 | openGLRequireES31: 0 245 | openGLRequireES31AEP: 0 246 | m_TemplateCustomTags: {} 247 | mobileMTRendering: 248 | Android: 1 249 | iPhone: 1 250 | tvOS: 1 251 | wiiUTitleID: 0005000011000000 252 | wiiUGroupID: 00010000 253 | wiiUCommonSaveSize: 4096 254 | wiiUAccountSaveSize: 2048 255 | wiiUOlvAccessKey: 0 256 | wiiUTinCode: 0 257 | wiiUJoinGameId: 0 258 | wiiUJoinGameModeMask: 0000000000000000 259 | wiiUCommonBossSize: 0 260 | wiiUAccountBossSize: 0 261 | wiiUAddOnUniqueIDs: [] 262 | wiiUMainThreadStackSize: 3072 263 | wiiULoaderThreadStackSize: 1024 264 | wiiUSystemHeapSize: 128 265 | wiiUTVStartupScreen: {fileID: 0} 266 | wiiUGamePadStartupScreen: {fileID: 0} 267 | wiiUDrcBufferDisabled: 0 268 | wiiUProfilerLibPath: 269 | playModeTestRunnerEnabled: 0 270 | actionOnDotNetUnhandledException: 1 271 | enableInternalProfiler: 0 272 | logObjCUncaughtExceptions: 1 273 | enableCrashReportAPI: 0 274 | cameraUsageDescription: 275 | locationUsageDescription: 276 | microphoneUsageDescription: 277 | switchNetLibKey: 278 | switchSocketMemoryPoolSize: 6144 279 | switchSocketAllocatorPoolSize: 128 280 | switchSocketConcurrencyLimit: 14 281 | switchScreenResolutionBehavior: 2 282 | switchUseCPUProfiler: 0 283 | switchApplicationID: 0x01004b9000490000 284 | switchNSODependencies: 285 | switchTitleNames_0: 286 | switchTitleNames_1: 287 | switchTitleNames_2: 288 | switchTitleNames_3: 289 | switchTitleNames_4: 290 | switchTitleNames_5: 291 | switchTitleNames_6: 292 | switchTitleNames_7: 293 | switchTitleNames_8: 294 | switchTitleNames_9: 295 | switchTitleNames_10: 296 | switchTitleNames_11: 297 | switchPublisherNames_0: 298 | switchPublisherNames_1: 299 | switchPublisherNames_2: 300 | switchPublisherNames_3: 301 | switchPublisherNames_4: 302 | switchPublisherNames_5: 303 | switchPublisherNames_6: 304 | switchPublisherNames_7: 305 | switchPublisherNames_8: 306 | switchPublisherNames_9: 307 | switchPublisherNames_10: 308 | switchPublisherNames_11: 309 | switchIcons_0: {fileID: 0} 310 | switchIcons_1: {fileID: 0} 311 | switchIcons_2: {fileID: 0} 312 | switchIcons_3: {fileID: 0} 313 | switchIcons_4: {fileID: 0} 314 | switchIcons_5: {fileID: 0} 315 | switchIcons_6: {fileID: 0} 316 | switchIcons_7: {fileID: 0} 317 | switchIcons_8: {fileID: 0} 318 | switchIcons_9: {fileID: 0} 319 | switchIcons_10: {fileID: 0} 320 | switchIcons_11: {fileID: 0} 321 | switchSmallIcons_0: {fileID: 0} 322 | switchSmallIcons_1: {fileID: 0} 323 | switchSmallIcons_2: {fileID: 0} 324 | switchSmallIcons_3: {fileID: 0} 325 | switchSmallIcons_4: {fileID: 0} 326 | switchSmallIcons_5: {fileID: 0} 327 | switchSmallIcons_6: {fileID: 0} 328 | switchSmallIcons_7: {fileID: 0} 329 | switchSmallIcons_8: {fileID: 0} 330 | switchSmallIcons_9: {fileID: 0} 331 | switchSmallIcons_10: {fileID: 0} 332 | switchSmallIcons_11: {fileID: 0} 333 | switchManualHTML: 334 | switchAccessibleURLs: 335 | switchLegalInformation: 336 | switchMainThreadStackSize: 1048576 337 | switchPresenceGroupId: 338 | switchLogoHandling: 0 339 | switchReleaseVersion: 0 340 | switchDisplayVersion: 1.0.0 341 | switchStartupUserAccount: 0 342 | switchTouchScreenUsage: 0 343 | switchSupportedLanguagesMask: 0 344 | switchLogoType: 0 345 | switchApplicationErrorCodeCategory: 346 | switchUserAccountSaveDataSize: 0 347 | switchUserAccountSaveDataJournalSize: 0 348 | switchApplicationAttribute: 0 349 | switchCardSpecSize: -1 350 | switchCardSpecClock: -1 351 | switchRatingsMask: 0 352 | switchRatingsInt_0: 0 353 | switchRatingsInt_1: 0 354 | switchRatingsInt_2: 0 355 | switchRatingsInt_3: 0 356 | switchRatingsInt_4: 0 357 | switchRatingsInt_5: 0 358 | switchRatingsInt_6: 0 359 | switchRatingsInt_7: 0 360 | switchRatingsInt_8: 0 361 | switchRatingsInt_9: 0 362 | switchRatingsInt_10: 0 363 | switchRatingsInt_11: 0 364 | switchLocalCommunicationIds_0: 365 | switchLocalCommunicationIds_1: 366 | switchLocalCommunicationIds_2: 367 | switchLocalCommunicationIds_3: 368 | switchLocalCommunicationIds_4: 369 | switchLocalCommunicationIds_5: 370 | switchLocalCommunicationIds_6: 371 | switchLocalCommunicationIds_7: 372 | switchParentalControl: 0 373 | switchAllowsScreenshot: 1 374 | switchDataLossConfirmation: 0 375 | switchSupportedNpadStyles: 3 376 | switchSocketConfigEnabled: 0 377 | switchTcpInitialSendBufferSize: 32 378 | switchTcpInitialReceiveBufferSize: 64 379 | switchTcpAutoSendBufferSizeMax: 256 380 | switchTcpAutoReceiveBufferSizeMax: 256 381 | switchUdpSendBufferSize: 9 382 | switchUdpReceiveBufferSize: 42 383 | switchSocketBufferEfficiency: 4 384 | switchSocketInitializeEnabled: 1 385 | switchNetworkInterfaceManagerInitializeEnabled: 1 386 | switchPlayerConnectionEnabled: 1 387 | ps4NPAgeRating: 12 388 | ps4NPTitleSecret: 389 | ps4NPTrophyPackPath: 390 | ps4ParentalLevel: 11 391 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 392 | ps4Category: 0 393 | ps4MasterVersion: 01.00 394 | ps4AppVersion: 01.00 395 | ps4AppType: 0 396 | ps4ParamSfxPath: 397 | ps4VideoOutPixelFormat: 0 398 | ps4VideoOutInitialWidth: 1920 399 | ps4VideoOutBaseModeInitialWidth: 1920 400 | ps4VideoOutReprojectionRate: 120 401 | ps4PronunciationXMLPath: 402 | ps4PronunciationSIGPath: 403 | ps4BackgroundImagePath: 404 | ps4StartupImagePath: 405 | ps4SaveDataImagePath: 406 | ps4SdkOverride: 407 | ps4BGMPath: 408 | ps4ShareFilePath: 409 | ps4ShareOverlayImagePath: 410 | ps4PrivacyGuardImagePath: 411 | ps4NPtitleDatPath: 412 | ps4RemotePlayKeyAssignment: -1 413 | ps4RemotePlayKeyMappingDir: 414 | ps4PlayTogetherPlayerCount: 0 415 | ps4EnterButtonAssignment: 1 416 | ps4ApplicationParam1: 0 417 | ps4ApplicationParam2: 0 418 | ps4ApplicationParam3: 0 419 | ps4ApplicationParam4: 0 420 | ps4DownloadDataSize: 0 421 | ps4GarlicHeapSize: 2048 422 | ps4ProGarlicHeapSize: 2560 423 | ps4Passcode: mWqBlQ9wQj99nsQzldVI5ZuGXbEWRK5R 424 | ps4pnSessions: 1 425 | ps4pnPresence: 1 426 | ps4pnFriends: 1 427 | ps4pnGameCustomData: 1 428 | playerPrefsSupport: 0 429 | restrictedAudioUsageRights: 0 430 | ps4UseResolutionFallback: 0 431 | ps4ReprojectionSupport: 0 432 | ps4UseAudio3dBackend: 0 433 | ps4SocialScreenEnabled: 0 434 | ps4ScriptOptimizationLevel: 0 435 | ps4Audio3dVirtualSpeakerCount: 14 436 | ps4attribCpuUsage: 0 437 | ps4PatchPkgPath: 438 | ps4PatchLatestPkgPath: 439 | ps4PatchChangeinfoPath: 440 | ps4PatchDayOne: 0 441 | ps4attribUserManagement: 0 442 | ps4attribMoveSupport: 0 443 | ps4attrib3DSupport: 0 444 | ps4attribShareSupport: 0 445 | ps4attribExclusiveVR: 0 446 | ps4disableAutoHideSplash: 0 447 | ps4videoRecordingFeaturesUsed: 0 448 | ps4contentSearchFeaturesUsed: 0 449 | ps4attribEyeToEyeDistanceSettingVR: 0 450 | ps4IncludedModules: [] 451 | monoEnv: 452 | psp2Splashimage: {fileID: 0} 453 | psp2NPTrophyPackPath: 454 | psp2NPSupportGBMorGJP: 0 455 | psp2NPAgeRating: 12 456 | psp2NPTitleDatPath: 457 | psp2NPCommsID: 458 | psp2NPCommunicationsID: 459 | psp2NPCommsPassphrase: 460 | psp2NPCommsSig: 461 | psp2ParamSfxPath: 462 | psp2ManualPath: 463 | psp2LiveAreaGatePath: 464 | psp2LiveAreaBackroundPath: 465 | psp2LiveAreaPath: 466 | psp2LiveAreaTrialPath: 467 | psp2PatchChangeInfoPath: 468 | psp2PatchOriginalPackage: 469 | psp2PackagePassword: hRXdCdG5nG5azdNMK66MuCV6GXi5xr84 470 | psp2KeystoneFile: 471 | psp2MemoryExpansionMode: 0 472 | psp2DRMType: 0 473 | psp2StorageType: 0 474 | psp2MediaCapacity: 0 475 | psp2DLCConfigPath: 476 | psp2ThumbnailPath: 477 | psp2BackgroundPath: 478 | psp2SoundPath: 479 | psp2TrophyCommId: 480 | psp2TrophyPackagePath: 481 | psp2PackagedResourcesPath: 482 | psp2SaveDataQuota: 10240 483 | psp2ParentalLevel: 1 484 | psp2ShortTitle: Not Set 485 | psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF 486 | psp2Category: 0 487 | psp2MasterVersion: 01.00 488 | psp2AppVersion: 01.00 489 | psp2TVBootMode: 0 490 | psp2EnterButtonAssignment: 2 491 | psp2TVDisableEmu: 0 492 | psp2AllowTwitterDialog: 1 493 | psp2Upgradable: 0 494 | psp2HealthWarning: 0 495 | psp2UseLibLocation: 0 496 | psp2InfoBarOnStartup: 0 497 | psp2InfoBarColor: 0 498 | psp2ScriptOptimizationLevel: 0 499 | psmSplashimage: {fileID: 0} 500 | splashScreenBackgroundSourceLandscape: {fileID: 0} 501 | splashScreenBackgroundSourcePortrait: {fileID: 0} 502 | spritePackerPolicy: 503 | webGLMemorySize: 256 504 | webGLExceptionSupport: 1 505 | webGLNameFilesAsHashes: 0 506 | webGLDataCaching: 0 507 | webGLDebugSymbols: 0 508 | webGLEmscriptenArgs: 509 | webGLModulesDirectory: 510 | webGLTemplate: APPLICATION:Default 511 | webGLAnalyzeBuildSize: 0 512 | webGLUseEmbeddedResources: 0 513 | webGLUseWasm: 0 514 | webGLCompressionFormat: 1 515 | scriptingDefineSymbols: {} 516 | platformArchitecture: {} 517 | scriptingBackend: {} 518 | incrementalIl2cppBuild: {} 519 | additionalIl2CppArgs: 520 | scriptingRuntimeVersion: 0 521 | apiCompatibilityLevelPerPlatform: {} 522 | m_RenderingPath: 1 523 | m_MobileRenderingPath: 1 524 | metroPackageName: unity 525 | metroPackageVersion: 526 | metroCertificatePath: 527 | metroCertificatePassword: 528 | metroCertificateSubject: 529 | metroCertificateIssuer: 530 | metroCertificateNotAfter: 0000000000000000 531 | metroApplicationDescription: unity 532 | wsaImages: {} 533 | metroTileShortName: 534 | metroCommandLineArgsFile: 535 | metroTileShowName: 0 536 | metroMediumTileShowName: 0 537 | metroLargeTileShowName: 0 538 | metroWideTileShowName: 0 539 | metroDefaultTileSize: 1 540 | metroTileForegroundText: 2 541 | metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} 542 | metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, 543 | a: 1} 544 | metroSplashScreenUseBackgroundColor: 0 545 | platformCapabilities: {} 546 | metroFTAName: 547 | metroFTAFileTypes: [] 548 | metroProtocolName: 549 | metroCompilationOverrides: 1 550 | tizenProductDescription: 551 | tizenProductURL: 552 | tizenSigningProfileName: 553 | tizenGPSPermissions: 0 554 | tizenMicrophonePermissions: 0 555 | tizenDeploymentTarget: 556 | tizenDeploymentTargetType: -1 557 | tizenMinOSVersion: 1 558 | n3dsUseExtSaveData: 0 559 | n3dsCompressStaticMem: 1 560 | n3dsExtSaveDataNumber: 0x12345 561 | n3dsStackSize: 131072 562 | n3dsTargetPlatform: 2 563 | n3dsRegion: 7 564 | n3dsMediaSize: 0 565 | n3dsLogoStyle: 3 566 | n3dsTitle: GameName 567 | n3dsProductCode: 568 | n3dsApplicationId: 0xFF3FF 569 | stvDeviceAddress: 570 | stvProductDescription: 571 | stvProductAuthor: 572 | stvProductAuthorEmail: 573 | stvProductLink: 574 | stvProductCategory: 0 575 | XboxOneProductId: 576 | XboxOneUpdateKey: 577 | XboxOneSandboxId: 578 | XboxOneContentId: 579 | XboxOneTitleId: 580 | XboxOneSCId: 581 | XboxOneGameOsOverridePath: 582 | XboxOnePackagingOverridePath: 583 | XboxOneAppManifestOverridePath: 584 | XboxOnePackageEncryption: 0 585 | XboxOnePackageUpdateGranularity: 2 586 | XboxOneDescription: 587 | XboxOneLanguage: 588 | - enus 589 | XboxOneCapability: [] 590 | XboxOneGameRating: {} 591 | XboxOneIsContentPackage: 0 592 | XboxOneEnableGPUVariability: 0 593 | XboxOneSockets: {} 594 | XboxOneSplashScreen: {fileID: 0} 595 | XboxOneAllowedProductIds: [] 596 | XboxOnePersistentLocalStorageSize: 0 597 | xboxOneScriptCompiler: 0 598 | vrEditorSettings: 599 | daydream: 600 | daydreamIconForeground: {fileID: 0} 601 | daydreamIconBackground: {fileID: 0} 602 | cloudServicesEnabled: {} 603 | facebookSdkVersion: 7.9.4 604 | apiCompatibilityLevel: 2 605 | cloudProjectId: 606 | projectName: 607 | organizationId: 608 | cloudEnabled: 0 609 | enableNativePlatformBackendsForNewInputSystem: 0 610 | disableOldInputManagerSupport: 0 611 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2017.2.0f3 2 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 5 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 4 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 4 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 1 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 1 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 4 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 2 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 1 108 | antiAliasing: 0 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 1 112 | billboardsFaceCameraPosition: 1 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 4 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 2 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 70 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 2 136 | antiAliasing: 2 137 | softParticles: 1 138 | softVegetation: 1 139 | realtimeReflectionProbes: 1 140 | billboardsFaceCameraPosition: 1 141 | vSyncCount: 1 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 4 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 2 153 | shadowResolution: 2 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 2 164 | antiAliasing: 2 165 | softParticles: 1 166 | softVegetation: 1 167 | realtimeReflectionProbes: 1 168 | billboardsFaceCameraPosition: 1 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 4 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSM: 5 183 | PSP2: 2 184 | Samsung TV: 2 185 | Standalone: 5 186 | Tizen: 2 187 | Web: 5 188 | WebGL: 3 189 | WiiU: 5 190 | Windows Store Apps: 5 191 | XboxOne: 5 192 | iPhone: 2 193 | tvOS: 2 194 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.33333334 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /demo/unity/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 0 7 | m_TestMode: 0 8 | m_TestEventUrl: 9 | m_TestConfigUrl: 10 | m_TestInitMode: 0 11 | CrashReportingSettings: 12 | m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes 13 | m_Enabled: 0 14 | m_CaptureEditorExceptions: 1 15 | UnityPurchasingSettings: 16 | m_Enabled: 0 17 | m_TestMode: 0 18 | UnityAnalyticsSettings: 19 | m_Enabled: 0 20 | m_InitializeOnStartup: 1 21 | m_TestMode: 0 22 | m_TestEventUrl: 23 | m_TestConfigUrl: 24 | UnityAdsSettings: 25 | m_Enabled: 0 26 | m_InitializeOnStartup: 1 27 | m_TestMode: 0 28 | m_EnabledPlatforms: 4294967295 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /demo/unity/UnityPackageManager/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /demo/xcode/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | 70 | # This file is generated by Unity post build action 71 | DemoApp/Unity/Exports.xcconfig 72 | 73 | # Files under Libraries will be copied from Unity build during Xcode build 74 | DemoApp/Unity/Libraries/ 75 | 76 | # Files under Classes will be copied from Unity build during Xcode build 77 | DemoApp/Unity/Classes/ 78 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 164A97911F7B111F00D4DA8D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 164A97901F7B111F00D4DA8D /* AppDelegate.swift */; }; 11 | 164A97931F7B111F00D4DA8D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 164A97921F7B111F00D4DA8D /* ViewController.swift */; }; 12 | 164A97961F7B111F00D4DA8D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 164A97941F7B111F00D4DA8D /* Main.storyboard */; }; 13 | 164A97981F7B111F00D4DA8D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 164A97971F7B111F00D4DA8D /* Assets.xcassets */; }; 14 | 164A979B1F7B111F00D4DA8D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 164A97991F7B111F00D4DA8D /* LaunchScreen.storyboard */; }; 15 | 16C412841F7B132D00E32745 /* Exports.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 16C412831F7B132C00E32745 /* Exports.xcconfig */; }; 16 | 16C4157B1F7B16FB00E32745 /* rsync_exclude in Resources */ = {isa = PBXBuildFile; fileRef = 16C415781F7B16FA00E32745 /* rsync_exclude */; }; 17 | 16C4157C1F7B16FB00E32745 /* UnityUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16C415791F7B16FA00E32745 /* UnityUtils.mm */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 164A978D1F7B111F00D4DA8D /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 164A97901F7B111F00D4DA8D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 23 | 164A97921F7B111F00D4DA8D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 24 | 164A97951F7B111F00D4DA8D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 25 | 164A97971F7B111F00D4DA8D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | 164A979A1F7B111F00D4DA8D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 27 | 164A979C1F7B111F00D4DA8D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | 16817A8E1FBCCEAD00FA0093 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; 29 | 16C412831F7B132C00E32745 /* Exports.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Exports.xcconfig; sourceTree = ""; }; 30 | 16C412851F7B14B100E32745 /* Unity.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Unity.xcconfig; sourceTree = ""; }; 31 | 16C415781F7B16FA00E32745 /* rsync_exclude */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rsync_exclude; sourceTree = ""; }; 32 | 16C415791F7B16FA00E32745 /* UnityUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UnityUtils.mm; sourceTree = ""; }; 33 | 16C4157A1F7B16FA00E32745 /* UnityUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnityUtils.h; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 164A978A1F7B111F00D4DA8D /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 164A97841F7B111F00D4DA8D = { 48 | isa = PBXGroup; 49 | children = ( 50 | 164A978F1F7B111F00D4DA8D /* DemoApp */, 51 | 164A978E1F7B111F00D4DA8D /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 164A978E1F7B111F00D4DA8D /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 164A978D1F7B111F00D4DA8D /* DemoApp.app */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 164A978F1F7B111F00D4DA8D /* DemoApp */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 16C412821F7B132C00E32745 /* Unity */, 67 | 164A97901F7B111F00D4DA8D /* AppDelegate.swift */, 68 | 164A97921F7B111F00D4DA8D /* ViewController.swift */, 69 | 164A97941F7B111F00D4DA8D /* Main.storyboard */, 70 | 164A97971F7B111F00D4DA8D /* Assets.xcassets */, 71 | 164A97991F7B111F00D4DA8D /* LaunchScreen.storyboard */, 72 | 164A979C1F7B111F00D4DA8D /* Info.plist */, 73 | ); 74 | path = DemoApp; 75 | sourceTree = ""; 76 | }; 77 | 16C412821F7B132C00E32745 /* Unity */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 16817A8E1FBCCEAD00FA0093 /* Bridging-Header.h */, 81 | 16C412831F7B132C00E32745 /* Exports.xcconfig */, 82 | 16C412851F7B14B100E32745 /* Unity.xcconfig */, 83 | 16C4157A1F7B16FA00E32745 /* UnityUtils.h */, 84 | 16C415791F7B16FA00E32745 /* UnityUtils.mm */, 85 | 16C415781F7B16FA00E32745 /* rsync_exclude */, 86 | ); 87 | path = Unity; 88 | sourceTree = ""; 89 | }; 90 | /* End PBXGroup section */ 91 | 92 | /* Begin PBXNativeTarget section */ 93 | 164A978C1F7B111F00D4DA8D /* DemoApp */ = { 94 | isa = PBXNativeTarget; 95 | buildConfigurationList = 164A979F1F7B111F00D4DA8D /* Build configuration list for PBXNativeTarget "DemoApp" */; 96 | buildPhases = ( 97 | 16C4157E1F7B174C00E32745 /* ShellScript */, 98 | 164A97891F7B111F00D4DA8D /* Sources */, 99 | 164A978A1F7B111F00D4DA8D /* Frameworks */, 100 | 164A978B1F7B111F00D4DA8D /* Resources */, 101 | 16C4157F1F7B178800E32745 /* ShellScript */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = DemoApp; 108 | productName = DemoApp; 109 | productReference = 164A978D1F7B111F00D4DA8D /* DemoApp.app */; 110 | productType = "com.apple.product-type.application"; 111 | }; 112 | /* End PBXNativeTarget section */ 113 | 114 | /* Begin PBXProject section */ 115 | 164A97851F7B111F00D4DA8D /* Project object */ = { 116 | isa = PBXProject; 117 | attributes = { 118 | LastSwiftUpdateCheck = 0900; 119 | LastUpgradeCheck = 0900; 120 | TargetAttributes = { 121 | 164A978C1F7B111F00D4DA8D = { 122 | CreatedOnToolsVersion = 9.0; 123 | ProvisioningStyle = Automatic; 124 | }; 125 | }; 126 | }; 127 | buildConfigurationList = 164A97881F7B111F00D4DA8D /* Build configuration list for PBXProject "DemoApp" */; 128 | compatibilityVersion = "Xcode 8.0"; 129 | developmentRegion = en; 130 | hasScannedForEncodings = 0; 131 | knownRegions = ( 132 | en, 133 | Base, 134 | ); 135 | mainGroup = 164A97841F7B111F00D4DA8D; 136 | productRefGroup = 164A978E1F7B111F00D4DA8D /* Products */; 137 | projectDirPath = ""; 138 | projectRoot = ""; 139 | targets = ( 140 | 164A978C1F7B111F00D4DA8D /* DemoApp */, 141 | ); 142 | }; 143 | /* End PBXProject section */ 144 | 145 | /* Begin PBXResourcesBuildPhase section */ 146 | 164A978B1F7B111F00D4DA8D /* Resources */ = { 147 | isa = PBXResourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | 16C412841F7B132D00E32745 /* Exports.xcconfig in Resources */, 151 | 164A979B1F7B111F00D4DA8D /* LaunchScreen.storyboard in Resources */, 152 | 16C4157B1F7B16FB00E32745 /* rsync_exclude in Resources */, 153 | 164A97981F7B111F00D4DA8D /* Assets.xcassets in Resources */, 154 | 164A97961F7B111F00D4DA8D /* Main.storyboard in Resources */, 155 | ); 156 | runOnlyForDeploymentPostprocessing = 0; 157 | }; 158 | /* End PBXResourcesBuildPhase section */ 159 | 160 | /* Begin PBXShellScriptBuildPhase section */ 161 | 16C4157E1F7B174C00E32745 /* ShellScript */ = { 162 | isa = PBXShellScriptBuildPhase; 163 | buildActionMask = 2147483647; 164 | files = ( 165 | ); 166 | inputPaths = ( 167 | ); 168 | outputPaths = ( 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | shellPath = /bin/sh; 172 | shellScript = "echo \"Syncing code from $UNITY_IOS_EXPORT_PATH...\"\nrsync -rc --exclude-from=$PRODUCT_NAME/Unity/rsync_exclude --delete $UNITY_IOS_EXPORT_PATH/Classes/ $PRODUCT_NAME/Unity/Classes/\nrsync -rc --exclude-from=$PRODUCT_NAME/Unity/rsync_exclude --delete $UNITY_IOS_EXPORT_PATH/Libraries/ $PRODUCT_NAME/Unity/Libraries/\n"; 173 | }; 174 | 16C4157F1F7B178800E32745 /* ShellScript */ = { 175 | isa = PBXShellScriptBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | ); 179 | inputPaths = ( 180 | ); 181 | outputPaths = ( 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | shellPath = /bin/sh; 185 | shellScript = "echo \"Syncing data from $UNITY_IOS_EXPORT_PATH...\"\nrm -rf \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Data\"\ncp -Rf \"$UNITY_IOS_EXPORT_PATH/Data\" \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Data\""; 186 | }; 187 | /* End PBXShellScriptBuildPhase section */ 188 | 189 | /* Begin PBXSourcesBuildPhase section */ 190 | 164A97891F7B111F00D4DA8D /* Sources */ = { 191 | isa = PBXSourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | 164A97931F7B111F00D4DA8D /* ViewController.swift in Sources */, 195 | 164A97911F7B111F00D4DA8D /* AppDelegate.swift in Sources */, 196 | 16C4157C1F7B16FB00E32745 /* UnityUtils.mm in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin PBXVariantGroup section */ 203 | 164A97941F7B111F00D4DA8D /* Main.storyboard */ = { 204 | isa = PBXVariantGroup; 205 | children = ( 206 | 164A97951F7B111F00D4DA8D /* Base */, 207 | ); 208 | name = Main.storyboard; 209 | sourceTree = ""; 210 | }; 211 | 164A97991F7B111F00D4DA8D /* LaunchScreen.storyboard */ = { 212 | isa = PBXVariantGroup; 213 | children = ( 214 | 164A979A1F7B111F00D4DA8D /* Base */, 215 | ); 216 | name = LaunchScreen.storyboard; 217 | sourceTree = ""; 218 | }; 219 | /* End PBXVariantGroup section */ 220 | 221 | /* Begin XCBuildConfiguration section */ 222 | 164A979D1F7B111F00D4DA8D /* Debug */ = { 223 | isa = XCBuildConfiguration; 224 | baseConfigurationReference = 16C412851F7B14B100E32745 /* Unity.xcconfig */; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | CLANG_ANALYZER_NONNULL = YES; 228 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 230 | CLANG_CXX_LIBRARY = "libc++"; 231 | CLANG_ENABLE_MODULES = YES; 232 | CLANG_ENABLE_OBJC_ARC = YES; 233 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_COMMA = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 238 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INFINITE_RECURSION = YES; 242 | CLANG_WARN_INT_CONVERSION = YES; 243 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 244 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 246 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 247 | CLANG_WARN_STRICT_PROTOTYPES = YES; 248 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 249 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 250 | CLANG_WARN_UNREACHABLE_CODE = YES; 251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 252 | CODE_SIGN_IDENTITY = "iPhone Developer"; 253 | COPY_PHASE_STRIP = NO; 254 | DEBUG_INFORMATION_FORMAT = dwarf; 255 | ENABLE_STRICT_OBJC_MSGSEND = YES; 256 | ENABLE_TESTABILITY = YES; 257 | GCC_C_LANGUAGE_STANDARD = gnu11; 258 | GCC_DYNAMIC_NO_PIC = NO; 259 | GCC_NO_COMMON_BLOCKS = YES; 260 | GCC_OPTIMIZATION_LEVEL = 0; 261 | GCC_PREPROCESSOR_DEFINITIONS = ( 262 | "DEBUG=1", 263 | "$(inherited)", 264 | ); 265 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 266 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 267 | GCC_WARN_UNDECLARED_SELECTOR = YES; 268 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 269 | GCC_WARN_UNUSED_FUNCTION = YES; 270 | GCC_WARN_UNUSED_VARIABLE = YES; 271 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 272 | MTL_ENABLE_DEBUG_INFO = YES; 273 | ONLY_ACTIVE_ARCH = YES; 274 | SDKROOT = iphoneos; 275 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 276 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 277 | }; 278 | name = Debug; 279 | }; 280 | 164A979E1F7B111F00D4DA8D /* Release */ = { 281 | isa = XCBuildConfiguration; 282 | baseConfigurationReference = 16C412851F7B14B100E32745 /* Unity.xcconfig */; 283 | buildSettings = { 284 | ALWAYS_SEARCH_USER_PATHS = NO; 285 | CLANG_ANALYZER_NONNULL = YES; 286 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 287 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 288 | CLANG_CXX_LIBRARY = "libc++"; 289 | CLANG_ENABLE_MODULES = YES; 290 | CLANG_ENABLE_OBJC_ARC = YES; 291 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 292 | CLANG_WARN_BOOL_CONVERSION = YES; 293 | CLANG_WARN_COMMA = YES; 294 | CLANG_WARN_CONSTANT_CONVERSION = YES; 295 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 296 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 297 | CLANG_WARN_EMPTY_BODY = YES; 298 | CLANG_WARN_ENUM_CONVERSION = YES; 299 | CLANG_WARN_INFINITE_RECURSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 302 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 303 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 304 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 305 | CLANG_WARN_STRICT_PROTOTYPES = YES; 306 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 307 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 308 | CLANG_WARN_UNREACHABLE_CODE = YES; 309 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 310 | CODE_SIGN_IDENTITY = "iPhone Developer"; 311 | COPY_PHASE_STRIP = NO; 312 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 313 | ENABLE_NS_ASSERTIONS = NO; 314 | ENABLE_STRICT_OBJC_MSGSEND = YES; 315 | GCC_C_LANGUAGE_STANDARD = gnu11; 316 | GCC_NO_COMMON_BLOCKS = YES; 317 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 318 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 319 | GCC_WARN_UNDECLARED_SELECTOR = YES; 320 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 321 | GCC_WARN_UNUSED_FUNCTION = YES; 322 | GCC_WARN_UNUSED_VARIABLE = YES; 323 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 324 | MTL_ENABLE_DEBUG_INFO = NO; 325 | SDKROOT = iphoneos; 326 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 327 | VALIDATE_PRODUCT = YES; 328 | }; 329 | name = Release; 330 | }; 331 | 164A97A01F7B111F00D4DA8D /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 335 | CODE_SIGN_STYLE = Automatic; 336 | DEVELOPMENT_TEAM = M5G4WTT787; 337 | INFOPLIST_FILE = DemoApp/Info.plist; 338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 339 | LIBRARY_SEARCH_PATHS = ( 340 | "$(inherited)", 341 | "$(PROJECT_DIR)/DemoApp/Unity/Libraries", 342 | ); 343 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-unity.DemoApp"; 344 | PRODUCT_NAME = "$(TARGET_NAME)"; 345 | SWIFT_VERSION = 4.0; 346 | TARGETED_DEVICE_FAMILY = "1,2"; 347 | }; 348 | name = Debug; 349 | }; 350 | 164A97A11F7B111F00D4DA8D /* Release */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | CODE_SIGN_STYLE = Automatic; 355 | DEVELOPMENT_TEAM = M5G4WTT787; 356 | INFOPLIST_FILE = DemoApp/Info.plist; 357 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 358 | LIBRARY_SEARCH_PATHS = ( 359 | "$(inherited)", 360 | "$(PROJECT_DIR)/DemoApp/Unity/Libraries", 361 | ); 362 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-unity.DemoApp"; 363 | PRODUCT_NAME = "$(TARGET_NAME)"; 364 | SWIFT_VERSION = 4.0; 365 | TARGETED_DEVICE_FAMILY = "1,2"; 366 | }; 367 | name = Release; 368 | }; 369 | /* End XCBuildConfiguration section */ 370 | 371 | /* Begin XCConfigurationList section */ 372 | 164A97881F7B111F00D4DA8D /* Build configuration list for PBXProject "DemoApp" */ = { 373 | isa = XCConfigurationList; 374 | buildConfigurations = ( 375 | 164A979D1F7B111F00D4DA8D /* Debug */, 376 | 164A979E1F7B111F00D4DA8D /* Release */, 377 | ); 378 | defaultConfigurationIsVisible = 0; 379 | defaultConfigurationName = Release; 380 | }; 381 | 164A979F1F7B111F00D4DA8D /* Build configuration list for PBXNativeTarget "DemoApp" */ = { 382 | isa = XCConfigurationList; 383 | buildConfigurations = ( 384 | 164A97A01F7B111F00D4DA8D /* Debug */, 385 | 164A97A11F7B111F00D4DA8D /* Release */, 386 | ); 387 | defaultConfigurationIsVisible = 0; 388 | defaultConfigurationName = Release; 389 | }; 390 | /* End XCConfigurationList section */ 391 | }; 392 | rootObject = 164A97851F7B111F00D4DA8D /* Project object */; 393 | } 394 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DemoApp 4 | // 5 | // Created by Jiulong Wang on 9/26/17. 6 | // 7 | 8 | import UIKit 9 | 10 | @UIApplicationMain 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | var application: UIApplication? 16 | 17 | @objc var currentUnityController: UnityAppController! 18 | 19 | var isUnityRunning = false 20 | 21 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 22 | // Override point for customization after application launch. 23 | 24 | self.application = application 25 | unity_init(CommandLine.argc, CommandLine.unsafeArgv) 26 | 27 | currentUnityController = UnityAppController() 28 | currentUnityController.application(application, didFinishLaunchingWithOptions: launchOptions) 29 | 30 | // first call to startUnity will do some init stuff, so just call it here and directly stop it again 31 | startUnity() 32 | stopUnity() 33 | 34 | return true 35 | } 36 | 37 | func applicationWillResignActive(_ application: UIApplication) { 38 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 39 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 40 | 41 | if isUnityRunning { 42 | currentUnityController.applicationWillResignActive(application) 43 | } 44 | } 45 | 46 | func applicationDidEnterBackground(_ application: UIApplication) { 47 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 48 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 49 | 50 | if isUnityRunning { 51 | currentUnityController.applicationDidEnterBackground(application) 52 | } 53 | } 54 | 55 | func applicationWillEnterForeground(_ application: UIApplication) { 56 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 57 | 58 | if isUnityRunning { 59 | currentUnityController.applicationWillEnterForeground(application) 60 | } 61 | } 62 | 63 | func applicationDidBecomeActive(_ application: UIApplication) { 64 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 65 | 66 | if isUnityRunning { 67 | currentUnityController.applicationDidBecomeActive(application) 68 | } 69 | } 70 | 71 | func applicationWillTerminate(_ application: UIApplication) { 72 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 73 | 74 | if isUnityRunning { 75 | currentUnityController.applicationWillTerminate(application) 76 | } 77 | } 78 | 79 | func startUnity() { 80 | if !isUnityRunning { 81 | isUnityRunning = true 82 | currentUnityController.applicationDidBecomeActive(application!) 83 | } 84 | } 85 | 86 | func stopUnity() { 87 | if isUnityRunning { 88 | currentUnityController.applicationWillResignActive(application!) 89 | isUnityRunning = false 90 | } 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Unity/Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #ifndef BRIDGING_HEADER 6 | #define BRIDGING_HEADER 7 | 8 | #import 9 | #import "UnityUtils.h" 10 | #import "UnityAppController.h" 11 | #import "UnityInterface.h" 12 | 13 | #endif /* BRIDGING_HEADER */ 14 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Unity/Unity.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Exports.xcconfig" 2 | 3 | UNITY_SCRIPTING_BACKEND = il2cpp; 4 | GCC_PREFIX_HEADER = $(PRODUCT_NAME)/Unity/Classes/Prefix.pch; 5 | 6 | HEADER_SEARCH_PATHS = $(inherited) "$(PRODUCT_NAME)/Unity/Classes" "$(PRODUCT_NAME)/Unity/Classes/Unity" "$(PRODUCT_NAME)/Unity/Classes/Native" "$(PRODUCT_NAME)/Unity/Libraries" "$(PRODUCT_NAME)/Unity/Libraries/libil2cpp/include" ${PODS_HEADER_PATHS}; 7 | 8 | LIBRARY_SEARCH_PATHS = $(inherited) "$(PRODUCT_NAME)/Unity/Libraries" "$(PRODUCT_NAME)/Unity/Libraries/libil2cpp/include" ${PODS_LIBRARY_PATHS}; 9 | 10 | // If using .net 4.0 in Unity, append -DNET_4_0 to OTHER_CFLAGS 11 | OTHER_CFLAGS = $(inherited) -DINIT_SCRIPTING_BACKEND=1 -fno-strict-overflow -DRUNTIME_IL2CPP=1; 12 | 13 | OTHER_LDFLAGS = $(inherited) -weak-lSystem -weak_framework CoreMotion -weak_framework GameKit -weak_framework iAd -framework AVFoundation -framework AudioToolbox -framework CFNetwork -framework CoreGraphics -framework CoreLocation -framework CoreMedia -framework CoreVideo -framework Foundation -framework MediaPlayer -framework MediaToolbox -framework Metal -framework OpenAL -framework OpenGLES -framework QuartzCore -framework SystemConfiguration -framework UIKit -liconv.2 -liPhone-lib -lil2cpp ${PODS_LIBRARIES}; 14 | 15 | SWIFT_OBJC_BRIDGING_HEADER = $(PRODUCT_NAME)/Unity/Bridging-Header.h; 16 | SWIFT_PRECOMPILE_BRIDGING_HEADER = YES; 17 | 18 | // If your Unity project contains depencencies that uses cocoapod (e.g. GVR SDK), follow steps below. 19 | // 1. Open Unity generated Xcode project file (remember to open workspace instead of project so the pod 20 | // projects will be built), and build everything. 21 | // 2. Find extra header search paths. Usually Unity will generate it in xcconfig files 22 | // (e.g. .../unity_gvr_xcode/Pods/Target Support Files/Pods-Unity-iPhone/Pods-Unity-iPhone.release.xcconfig), 23 | // and apply it here. Take GVR SDK for example: 24 | // PODS_ROOT = ${UNITY_IOS_EXPORT_PATH}/Pods 25 | // PODS_HEADER_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GVRSDK" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac"; 26 | 27 | // 3. Find pods output file and copy them to this project. Xcode built them into temporary folders you can find them 28 | // under Xcode tree Pods. For example, copy these three files for GVR SDK (your path may vary) 29 | // cp ~/Library/Developer/Xcode/DerivedData/Unity-iPhone-bsgkfmaurmsxvgeqxqqbphqzgobq/Build/Products/Release-iphoneos/GoogleToolboxForMac/libGoogleToolboxForMac.a ${SRCROOT}/GVRSDK/libGoogleToolboxForMac.a 30 | // cp ~/Library/Developer/Xcode/DerivedData/Unity-iPhone-bsgkfmaurmsxvgeqxqqbphqzgobq/Build/Products/Release-iphoneos/GTMSessionFetcher/libGTMSessionFetcher.a ${SRCROOT}/GVRSDK/libGTMSessionFetcher.a 31 | // cp ${PODS_ROOT}/GVRSDK/Libraries/libGVRSDK.a ${SRCROOT}/GVRSDK/libGVRSDK.a 32 | // Once copied you can add GVRSDK to LIBRARY_SEARCH_PATHS 33 | // PODS_LIBRARY_PATHS = GVRSDK $(PRODUCT_NAME)/Unity/Libraries/GoogleVR/Plugins/iOS 34 | 35 | // 4. Add dependency libraries to OTHER_LDFLAGS via PODS_LIBRARIES 36 | // PODS_LIBRARIES = -framework GLKit -ObjC -lGVRSDK -lGTMSessionFetcher -lGoogleToolboxForMac 37 | 38 | // 5. Add dependency bundle resources to Swift project. For GVR SDK, add Pods/GVRSDK/Resources/*.bundle from Unity genderated 39 | // to Swift project and add them into build target. 40 | 41 | // 6. Build and run. 42 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Unity/UnityUtils.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #ifndef UnityUtils_h 4 | #define UnityUtils_h 5 | 6 | void unity_init(int argc, char* argv[]); 7 | 8 | void UnityPostMessage(NSString* gameObject, NSString* methodName, NSString* message); 9 | 10 | #endif /* UnityUtils_h */ 11 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Unity/UnityUtils.mm: -------------------------------------------------------------------------------- 1 | #include "RegisterMonoModules.h" 2 | #include "RegisterFeatures.h" 3 | #include 4 | 5 | // Hack to work around iOS SDK 4.3 linker problem 6 | // we need at least one __TEXT, __const section entry in main application .o files 7 | // to get this section emitted at right time and so avoid LC_ENCRYPTION_INFO size miscalculation 8 | static const int constsection = 0; 9 | 10 | void UnityInitTrampoline(); 11 | 12 | extern "C" void unity_init(int argc, char* argv[]) 13 | { 14 | @autoreleasepool 15 | { 16 | UnityInitTrampoline(); 17 | UnityInitRuntime(argc, argv); 18 | 19 | RegisterMonoModules(); 20 | NSLog(@"-> registered mono modules %p\n", &constsection); 21 | RegisterFeatures(); 22 | 23 | // iOS terminates open sockets when an application enters background mode. 24 | // The next write to any of such socket causes SIGPIPE signal being raised, 25 | // even if the request has been done from scripting side. This disables the 26 | // signal and allows Mono to throw a proper C# exception. 27 | std::signal(SIGPIPE, SIG_IGN); 28 | } 29 | } 30 | 31 | extern "C" void UnityPostMessage(NSString* gameObject, NSString* methodName, NSString* message) 32 | { 33 | UnitySendMessage([gameObject UTF8String], [methodName UTF8String], [message UTF8String]); 34 | } 35 | 36 | // The following functions are for demo purpose only. 37 | // You don't need them if your Unity code does not invoke them. 38 | extern "C" void UnityToggleRotation(bool isOn) 39 | { 40 | NSDictionary* dict = @{ @"isOn": @(isOn) }; 41 | [[NSNotificationCenter defaultCenter] postNotificationName: @"UnityToggleRotation" object:nil userInfo:dict]; 42 | } 43 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/Unity/rsync_exclude: -------------------------------------------------------------------------------- 1 | *.bak 2 | -------------------------------------------------------------------------------- /demo/xcode/DemoApp/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // DemoApp 4 | // 5 | // Created by Jiulong Wang on 9/26/17. 6 | // 7 | 8 | import UIKit 9 | 10 | class ViewController: UIViewController { 11 | @IBOutlet var rotateSwitch: UISwitch! 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | if let appDelegate = UIApplication.shared.delegate as? AppDelegate { 16 | appDelegate.startUnity() 17 | 18 | NotificationCenter.default.addObserver(self, selector: #selector(handleUnityReady), name: NSNotification.Name("UnityReady"), object: nil) 19 | NotificationCenter.default.addObserver(self, selector: #selector(handleUnityToggleRotation(_:)), name: NSNotification.Name("UnityToggleRotation"), object: nil) 20 | } 21 | } 22 | 23 | @objc func handleUnityReady() { 24 | showUnitySubView() 25 | } 26 | 27 | @objc func handleUnityToggleRotation(_ n: NSNotification) { 28 | if let isOn = n.userInfo?["isOn"] as? NSNumber { 29 | rotateSwitch.isOn = isOn.boolValue 30 | } 31 | } 32 | 33 | @IBAction func handleSwitchValueChanged(sender: UISwitch) { 34 | UnityPostMessage("NATIVE_BRIDGE", "RotateCube", sender.isOn ? "start" : "stop") 35 | } 36 | 37 | func showUnitySubView() { 38 | if let unityView = UnityGetGLView() { 39 | // insert subview at index 0 ensures unity view is behind current UI view 40 | view?.insertSubview(unityView, at: 0) 41 | 42 | unityView.translatesAutoresizingMaskIntoConstraints = false 43 | let views = ["view": unityView] 44 | let w = NSLayoutConstraint.constraints(withVisualFormat: "|-0-[view]-0-|", options: [], metrics: nil, views: views) 45 | let h = NSLayoutConstraint.constraints(withVisualFormat: "V:|-75-[view]-0-|", options: [], metrics: nil, views: views) 46 | view.addConstraints(w + h) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiulongw/swift-unity/fb2484db0a6518d06a3abadf5cd4bc8d998794be/images/demo.gif -------------------------------------------------------------------------------- /images/unity_configuration_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiulongw/swift-unity/fb2484db0a6518d06a3abadf5cd4bc8d998794be/images/unity_configuration_file.png -------------------------------------------------------------------------------- /images/xcode_build_script_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiulongw/swift-unity/fb2484db0a6518d06a3abadf5cd4bc8d998794be/images/xcode_build_script_1.png -------------------------------------------------------------------------------- /images/xcode_build_script_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiulongw/swift-unity/fb2484db0a6518d06a3abadf5cd4bc8d998794be/images/xcode_build_script_2.png -------------------------------------------------------------------------------- /images/xcode_source_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiulongw/swift-unity/fb2484db0a6518d06a3abadf5cd4bc8d998794be/images/xcode_source_tree.png --------------------------------------------------------------------------------