├── .gitignore ├── Assets ├── AssetBundlePatch.meta ├── AssetBundlePatch │ ├── AssetBundlePatch.cs │ └── AssetBundlePatch.cs.meta ├── Level1.unity ├── Level1.unity.meta ├── Level2.unity ├── Level2.unity.meta ├── Plane1.mat ├── Plane1.mat.meta ├── Plane2.mat ├── Plane2.mat.meta ├── Plugins.meta ├── Plugins │ ├── Android.meta │ ├── Android │ │ ├── libAssetBundleParser.so │ │ └── libAssetBundleParser.so.meta │ ├── AssetBundleParser.bundle.meta │ ├── AssetBundleParser.bundle │ │ ├── Contents.meta │ │ └── Contents │ │ │ ├── Info.plist │ │ │ ├── Info.plist.meta │ │ │ ├── MacOS.meta │ │ │ ├── MacOS │ │ │ ├── AssetBundleParser │ │ │ └── AssetBundleParser.meta │ │ │ ├── Resources.meta │ │ │ └── Resources │ │ │ ├── en.lproj.meta │ │ │ └── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── InfoPlist.strings.meta │ ├── iOS.meta │ ├── iOS │ │ ├── libAssetBundleParser.a │ │ └── libAssetBundleParser.a.meta │ ├── x86.meta │ ├── x86 │ │ ├── AssetBundleParser.dll │ │ └── AssetBundleParser.dll.meta │ ├── x86_64.meta │ └── x86_64 │ │ ├── AssetBundleParser.dll │ │ └── AssetBundleParser.dll.meta ├── Standard Assets.meta ├── Standard Assets │ ├── Character Controllers.meta │ └── Character Controllers │ │ ├── 3rd Person Controller.prefab │ │ ├── 3rd Person Controller.prefab.meta │ │ ├── First Person Controller.prefab │ │ ├── First Person Controller.prefab.meta │ │ ├── Sources.meta │ │ └── Sources │ │ ├── PrototypeCharacter.meta │ │ ├── PrototypeCharacter │ │ ├── Constructor.FBX │ │ ├── Constructor.FBX.meta │ │ ├── Materials.meta │ │ ├── Materials │ │ │ ├── constructor_done.mat │ │ │ └── constructor_done.mat.meta │ │ ├── Textures.meta │ │ └── Textures │ │ │ ├── constructor_diffuse.png │ │ │ ├── constructor_diffuse.png.meta │ │ │ ├── constructor_normals.png │ │ │ └── constructor_normals.png.meta │ │ ├── Scripts.meta │ │ └── Scripts │ │ ├── CharacterMotor.js │ │ ├── CharacterMotor.js.meta │ │ ├── FPSInputController.js │ │ ├── FPSInputController.js.meta │ │ ├── MouseLook.cs │ │ ├── MouseLook.cs.meta │ │ ├── PlatformInputController.js │ │ ├── PlatformInputController.js.meta │ │ ├── ThirdPersonCamera.js │ │ ├── ThirdPersonCamera.js.meta │ │ ├── ThirdPersonController.js │ │ └── ThirdPersonController.js.meta ├── StreamingAssets.meta ├── StreamingAssets │ ├── diff.rtttl │ └── diff.rtttl.meta ├── Test.meta ├── Test │ ├── Editor.meta │ ├── Editor │ │ ├── OneBuilderEditor.cs │ │ └── OneBuilderEditor.cs.meta │ ├── Progress.cs │ ├── Progress.cs.meta │ ├── UnzipProgress.cs │ ├── UnzipProgress.cs.meta │ ├── Updater.cs │ ├── Updater.cs.meta │ ├── ZipFile.cs │ └── ZipFile.cs.meta ├── Thirdparty.meta └── Thirdparty │ ├── SharpZip.dll │ ├── SharpZip.dll.meta │ ├── UnityUtils.meta │ └── UnityUtils │ ├── AndroidAssetStream.cs │ ├── AndroidAssetStream.cs.meta │ ├── DynamicObject.cs │ ├── DynamicObject.cs.meta │ ├── Editor.meta │ ├── Editor │ ├── AssetDatabase.cs │ ├── AssetDatabase.cs.meta │ ├── CodeFormat.cs │ ├── CodeFormat.cs.meta │ ├── CommandLine.cs │ ├── CommandLine.cs.meta │ ├── EditorGUITools.cs │ ├── EditorGUITools.cs.meta │ ├── UIAdapterEditor.cs │ └── UIAdapterEditor.cs.meta │ ├── EventHelper.cs │ ├── EventHelper.cs.meta │ ├── IO.cs │ ├── IO.cs.meta │ ├── Log.cs │ ├── Log.cs.meta │ ├── README.md │ ├── README.md.meta │ ├── SimpleJson.cs │ ├── SimpleJson.cs.meta │ ├── Util.cs │ └── Util.cs.meta ├── LICENSE ├── ProjectSettings ├── AudioManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshLayers.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── QualitySettings.asset ├── TagManager.asset └── TimeManager.asset └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Temp/ 2 | Library 3 | *.csproj 4 | -------------------------------------------------------------------------------- /Assets/AssetBundlePatch.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 45baf8a5af6e9433eb867191405a1e53 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/AssetBundlePatch/AssetBundlePatch.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Runtime.InteropServices; 4 | using System; 5 | using System.IO; 6 | 7 | namespace dpull 8 | { 9 | public enum AssetBundlePatchResult 10 | { 11 | Failed = -1, 12 | Succeed = 0, 13 | 14 | FromAssetBundleLoadFailed, 15 | DiffFileSaveFailed, 16 | DiffFileLoadFailed, 17 | ToAssetBundleSaveFailed, 18 | } 19 | 20 | public class AssetBundlePatch 21 | { 22 | public static bool IsSupport(string file) 23 | { 24 | var bundle = assetbundle_load(file); 25 | if (bundle == IntPtr.Zero) 26 | return false; 27 | 28 | var ret = assetbundle_check(bundle); 29 | assetbundle_destroy(bundle); 30 | return ret; 31 | } 32 | 33 | public static AssetBundlePatchResult Diff(string appDataDir, string fromAssetbundle, string toAssetbundle, string diff) 34 | { 35 | if (string.IsNullOrEmpty(appDataDir)) 36 | appDataDir = null; 37 | 38 | if (string.IsNullOrEmpty(fromAssetbundle)) 39 | fromAssetbundle = null; 40 | 41 | if (string.IsNullOrEmpty(toAssetbundle)) 42 | throw new System.ArgumentNullException("toAssetbundle"); 43 | 44 | if (string.IsNullOrEmpty(diff)) 45 | throw new System.ArgumentNullException("diff"); 46 | 47 | return (AssetBundlePatchResult)assetbundle_diff(appDataDir, fromAssetbundle, toAssetbundle, diff); 48 | } 49 | 50 | public static AssetBundlePatchResult Merge(string appDataDir, string fromAssetbundle, string toAssetbundle, string diff) 51 | { 52 | if (string.IsNullOrEmpty(appDataDir)) 53 | appDataDir = string.Empty; 54 | 55 | if (string.IsNullOrEmpty(fromAssetbundle)) 56 | fromAssetbundle = null; 57 | 58 | if (string.IsNullOrEmpty(toAssetbundle)) 59 | throw new System.ArgumentNullException("toAssetbundle"); 60 | 61 | if (string.IsNullOrEmpty(diff)) 62 | throw new System.ArgumentNullException("diff"); 63 | 64 | AppDataDir = appDataDir; 65 | return (AssetBundlePatchResult)assetbundle_merge(ReadFile, IntPtr.Zero, fromAssetbundle, toAssetbundle, diff); 66 | } 67 | 68 | public static void Print(string diff, string output) 69 | { 70 | if (string.IsNullOrEmpty(diff)) 71 | throw new System.ArgumentNullException("diff"); 72 | 73 | if (string.IsNullOrEmpty(output)) 74 | output = null; 75 | 76 | assetbundle_diff_print(diff, output); 77 | } 78 | 79 | public static bool SetFileSize(string file, uint length) 80 | { 81 | return filemapping_truncate(file, length); 82 | } 83 | 84 | public static string GetAppDataDir() 85 | { 86 | switch (Application.platform) 87 | { 88 | case RuntimePlatform.IPhonePlayer: 89 | return Directory.GetParent(Application.streamingAssetsPath).FullName; 90 | 91 | case RuntimePlatform.Android: 92 | return Path.Combine(Application.streamingAssetsPath, "bin/Data"); 93 | 94 | default: 95 | throw new UnityException("Not support:" + Application.platform.ToString()); 96 | } 97 | } 98 | 99 | #if UNITY_EDITOR 100 | public static string GetEditorAppDataDir(string clientPath, UnityEditor.BuildTarget target) 101 | { 102 | switch (target) 103 | { 104 | case UnityEditor.BuildTarget.iPhone: 105 | return Path.Combine(clientPath, "Payload/hero.app/Data"); 106 | 107 | case UnityEditor.BuildTarget.Android: 108 | return Path.Combine(clientPath, "assets/bin/Data"); 109 | 110 | default: 111 | throw new UnityException("Not support:" + Application.platform.ToString()); 112 | } 113 | } 114 | #endif 115 | 116 | static bool TrySplitPath(string fullPath, ref string splitFileName, ref int splitIndex) 117 | { 118 | var match = ".split"; 119 | var findIndex = fullPath.LastIndexOf(match); 120 | if (findIndex == -1) 121 | return false; 122 | 123 | var subPath = fullPath.Substring(0, findIndex); 124 | var indexStr = fullPath.Substring(findIndex + match.Length); 125 | var index = 0; 126 | if (!int.TryParse(indexStr, out index)) 127 | return false; 128 | 129 | splitFileName = subPath; 130 | splitIndex = index; 131 | return true; 132 | } 133 | 134 | static string GetNextSplitPath(string splitFileName, ref int splitIndex) 135 | { 136 | splitIndex++; 137 | return string.Format("{0}.split{1}", splitFileName, splitIndex); 138 | } 139 | 140 | [AOT.MonoPInvokeCallback(typeof(ReadFileCallback))] 141 | static bool ReadFile(IntPtr buffer, string fileName, uint fileOffset, uint length, IntPtr userdata) 142 | { 143 | try 144 | { 145 | var fullPath = Path.Combine(AppDataDir, fileName); 146 | var offset = (int)fileOffset; 147 | var left = (int)length; 148 | var data = new byte[length]; 149 | var splitFileName = string.Empty; 150 | var splitIndex = 0; 151 | 152 | while (left > 0) 153 | { 154 | Debug.Log("Merge from file:" + fullPath); 155 | 156 | using (var stream = FileEx.OpenRead(fullPath)) 157 | { 158 | if (stream == null) 159 | { 160 | Debug.LogError("File not exist:" + fullPath); 161 | return false; 162 | } 163 | 164 | stream.Seek(offset, SeekOrigin.Begin); 165 | while (left > 0) 166 | { 167 | var ret = stream.Read(data, (int)length - left, left); 168 | if (ret <= 0) 169 | { 170 | if (string.IsNullOrEmpty(splitFileName)) 171 | TrySplitPath(fullPath, ref splitFileName, ref splitIndex); 172 | 173 | if (string.IsNullOrEmpty(splitFileName)) 174 | { 175 | Debug.LogError(string.Format("stream read failed. {0}, offset:{1}, length{2}, left:{3}", fileName, offset, length, left)); 176 | return false; 177 | } 178 | 179 | fullPath = GetNextSplitPath(splitFileName, ref splitIndex); 180 | offset = 0; 181 | break; 182 | } 183 | left -= ret; 184 | } 185 | } 186 | } 187 | 188 | Marshal.Copy(data, 0, buffer, data.Length); 189 | return true; 190 | } 191 | catch(System.Exception e) 192 | { 193 | Debug.LogException(e); 194 | return false; 195 | } 196 | } 197 | 198 | static string AppDataDir; 199 | 200 | #if UNITY_IPHONE 201 | internal const string LIBNAME = "__Internal"; 202 | #else 203 | internal const string LIBNAME = "AssetBundleParser"; 204 | #endif 205 | 206 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "assetbundle_load")] 207 | static extern IntPtr assetbundle_load(string file); 208 | 209 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, EntryPoint = "assetbundle_check")] 210 | static extern bool assetbundle_check(IntPtr bundle); 211 | 212 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, EntryPoint = "assetbundle_destroy")] 213 | static extern void assetbundle_destroy(IntPtr bundle); 214 | 215 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "assetbundle_diff")] 216 | static extern int assetbundle_diff(string appDataDir, string fromAssetbundle, string toAssetbundle, string diff); 217 | 218 | delegate bool ReadFileCallback(IntPtr buffer, string fileName, uint offset, uint length, IntPtr userdata); 219 | 220 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "assetbundle_merge")] 221 | static extern int assetbundle_merge(ReadFileCallback callback, IntPtr userdata, string fromAssetbundle, string toAssetbundle, string diff); 222 | 223 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "assetbundle_diff_print")] 224 | static extern void assetbundle_diff_print(string filename, string output); 225 | 226 | [DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "filemapping_truncate")] 227 | static extern bool filemapping_truncate(string filename, uint length); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /Assets/AssetBundlePatch/AssetBundlePatch.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c50e787b870c049c5a87ee1725e6a2f5 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Level1.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Level1.unity -------------------------------------------------------------------------------- /Assets/Level1.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 300cc774bd455470cba1303ae216b9eb 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Level2.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Level2.unity -------------------------------------------------------------------------------- /Assets/Level2.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5459faf1402e842269af21598972ff1c 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plane1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plane1.mat -------------------------------------------------------------------------------- /Assets/Plane1.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee5e25bacf97945bdb67cfd82c0d967c 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plane2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plane2.mat -------------------------------------------------------------------------------- /Assets/Plane2.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e1f8588e459140acaac309e88fcfd42 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c92a22cd038ab412d9d114f27240a1ae 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Android.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0004c0a5ad641d4468ebb65779ee48b2 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Android/libAssetBundleParser.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plugins/Android/libAssetBundleParser.so -------------------------------------------------------------------------------- /Assets/Plugins/Android/libAssetBundleParser.so.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c88edaa3cfee4c4fa904ff79c3c7e8f 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6214b14be0029470a9fe9105b6013267 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 42a37ca4118c14c29855fcbd2d06384e 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14C109 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | AssetBundleParser 11 | CFBundleIdentifier 12 | lua.dpull.com 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | AssetBundleParser 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | CFPlugInDynamicRegisterFunction 26 | 27 | CFPlugInDynamicRegistration 28 | NO 29 | CFPlugInFactories 30 | 31 | 00000000-0000-0000-0000-000000000000 32 | MyFactoryFunction 33 | 34 | CFPlugInTypes 35 | 36 | 00000000-0000-0000-0000-000000000000 37 | 38 | 00000000-0000-0000-0000-000000000000 39 | 40 | 41 | CFPlugInUnloadFunction 42 | 43 | DTCompiler 44 | com.apple.compilers.llvm.clang.1_0 45 | DTPlatformBuild 46 | 6C131e 47 | DTPlatformVersion 48 | GM 49 | DTSDKBuild 50 | 14A383 51 | DTSDKName 52 | macosx10.10 53 | DTXcode 54 | 0620 55 | DTXcodeBuild 56 | 6C131e 57 | NSHumanReadableCopyright 58 | Copyright © 2014年 dpull. All rights reserved. 59 | 60 | 61 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/Info.plist.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 89753a4000ee5452d8cd76eb79dce4bb 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/MacOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82f2dc4a1a58342579676d8ced5f81de 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/MacOS/AssetBundleParser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plugins/AssetBundleParser.bundle/Contents/MacOS/AssetBundleParser -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/MacOS/AssetBundleParser.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 98f718bc01ad24cc6aa047a0f5714796 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4276ad4fbe4e64229b0f89ad138d2bb0 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/Resources/en.lproj.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bedaf6fb2711f4254a4abc5de0e94e1c 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plugins/AssetBundleParser.bundle/Contents/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Assets/Plugins/AssetBundleParser.bundle/Contents/Resources/en.lproj/InfoPlist.strings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c66eb7b89cddf4b0f992fe56e53ecfd3 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/iOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3fe8320f4ef77a6419bcdffeb8a68556 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/iOS/libAssetBundleParser.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plugins/iOS/libAssetBundleParser.a -------------------------------------------------------------------------------- /Assets/Plugins/iOS/libAssetBundleParser.a.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 964d63d0d926b4c0784052ae105470a6 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/x86.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b0b0c4ffe67d2f4292c5211de91e55f 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/x86/AssetBundleParser.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plugins/x86/AssetBundleParser.dll -------------------------------------------------------------------------------- /Assets/Plugins/x86/AssetBundleParser.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8035ebec9c8dd48eb912ec05d7973cb7 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/x86_64.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ea0a8e1f899b1148badb9e92b431566 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/x86_64/AssetBundleParser.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Plugins/x86_64/AssetBundleParser.dll -------------------------------------------------------------------------------- /Assets/Plugins/x86_64/AssetBundleParser.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43482e9e733214852adb6206de5ef9d6 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Standard Assets.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 28a81280068924e63b40ae4748ddb321 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54216e9ed42974e30967824b7f0b2806 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/3rd Person Controller.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Standard Assets/Character Controllers/3rd Person Controller.prefab -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/3rd Person Controller.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2314ce3a3eecf4816bad3c9eca4de2e1 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/First Person Controller.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Standard Assets/Character Controllers/First Person Controller.prefab -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/First Person Controller.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d4133d5d30b644bd87802a347eaccbe 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e0b0a994d8934541a387e092630b5db 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c81df2918c80c054ca3d436e62090893 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Constructor.FBX: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Constructor.FBX -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Constructor.FBX.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 449b48f7eb5d87a4baaa5fb73f875a59 3 | ModelImporter: 4 | serializedVersion: 16 5 | fileIDToRecycleName: 6 | 100000: Bip001 R Finger1 7 | 100002: Bip001 R Finger21 8 | 100004: Bip001 R Finger11 9 | 100006: Bip001 R Finger02 10 | 100010: Bip001 R Finger12 11 | 100012: Bip001 R Finger41 12 | 100014: Bip001 R Finger4 13 | 100018: Bip001 R Finger32 14 | 100020: Bip001 R Finger31 15 | 100022: Bip001 R Finger3 16 | 100026: hip_adjustment_bone_right 17 | 100028: Bip001 R Finger42 18 | 100032: hip_adjustment_bone_left 19 | 100034: Bip001 R Finger2 20 | 100036: Bip001 R Finger22 21 | 100040: Bip001 R UpperArm 22 | 100042: Bip001 R Forearm 23 | 100044: Bip001 R Finger0 24 | 100046: Bip001 R Finger01 25 | 100052: //RootNode 26 | 100054: Bip001 R Clavicle 27 | 100058: Bip001 L Finger3 28 | 100060: Bip001 L Finger31 29 | 100062: Bip001 L Finger32 30 | 100066: Bip001 L Finger4 31 | 100068: Bip001 L Finger41 32 | 100070: Bip001 L Finger42 33 | 100074: Bip001 L Finger22 34 | 100076: Bip001 L Finger02 35 | 100080: Bip001 L Finger1 36 | 100082: Bip001 L Finger11 37 | 100084: Bip001 L Finger12 38 | 100088: Bip001 L Finger2 39 | 100090: Bip001 L Finger21 40 | 100092: Bip001 L Finger0 41 | 100094: Bip001 L Finger01 42 | 100096: Bip001 L Forearm 43 | 100098: Bip001 L UpperArm 44 | 100100: Bip001 L Clavicle 45 | 100102: construction_worker 46 | 100104: Bip001 R Toe0 47 | 100106: Bip001 R Foot 48 | 100108: Bip001 R Calf 49 | 100110: Bip001 R Thigh 50 | 100112: Bip001 L Toe0 51 | 100114: Bip001 L Foot 52 | 100116: Bip001 L Calf 53 | 100118: Bip001 L Thigh 54 | 100120: helmet_bone 55 | 100124: Bip001 Head 56 | 100126: wrench 57 | 100128: Bip001 R Hand 58 | 100130: Bip001 L Hand 59 | 100132: Bip001 Neck 60 | 100134: Bip001 Spine1 61 | 100136: Bip001 Spine 62 | 100138: Bip001 Pelvis 63 | 100140: Bip001 64 | 400000: Bip001 R Finger1 65 | 400002: Bip001 R Finger21 66 | 400004: Bip001 R Finger11 67 | 400006: Bip001 R Finger02 68 | 400010: Bip001 R Finger12 69 | 400012: Bip001 R Finger41 70 | 400014: Bip001 R Finger4 71 | 400018: Bip001 R Finger32 72 | 400020: Bip001 R Finger31 73 | 400022: Bip001 R Finger3 74 | 400026: hip_adjustment_bone_right 75 | 400028: Bip001 R Finger42 76 | 400032: hip_adjustment_bone_left 77 | 400034: Bip001 R Finger2 78 | 400036: Bip001 R Finger22 79 | 400040: Bip001 R UpperArm 80 | 400042: Bip001 R Forearm 81 | 400044: Bip001 R Finger0 82 | 400046: Bip001 R Finger01 83 | 400052: //RootNode 84 | 400054: Bip001 R Clavicle 85 | 400058: Bip001 L Finger3 86 | 400060: Bip001 L Finger31 87 | 400062: Bip001 L Finger32 88 | 400066: Bip001 L Finger4 89 | 400068: Bip001 L Finger41 90 | 400070: Bip001 L Finger42 91 | 400074: Bip001 L Finger22 92 | 400076: Bip001 L Finger02 93 | 400080: Bip001 L Finger1 94 | 400082: Bip001 L Finger11 95 | 400084: Bip001 L Finger12 96 | 400088: Bip001 L Finger2 97 | 400090: Bip001 L Finger21 98 | 400092: Bip001 L Finger0 99 | 400094: Bip001 L Finger01 100 | 400096: Bip001 L Forearm 101 | 400098: Bip001 L UpperArm 102 | 400100: Bip001 L Clavicle 103 | 400102: construction_worker 104 | 400104: Bip001 R Toe0 105 | 400106: Bip001 R Foot 106 | 400108: Bip001 R Calf 107 | 400110: Bip001 R Thigh 108 | 400112: Bip001 L Toe0 109 | 400114: Bip001 L Foot 110 | 400116: Bip001 L Calf 111 | 400118: Bip001 L Thigh 112 | 400120: helmet_bone 113 | 400124: Bip001 Head 114 | 400126: wrench 115 | 400128: Bip001 R Hand 116 | 400130: Bip001 L Hand 117 | 400132: Bip001 Neck 118 | 400134: Bip001 Spine1 119 | 400136: Bip001 Spine 120 | 400138: Bip001 Pelvis 121 | 400140: Bip001 122 | 2300000: wrench 123 | 3300000: wrench 124 | 4300000: construction_worker 125 | 4300002: wrench 126 | 7400012: idle 127 | 7400014: run 128 | 7400016: walk 129 | 7400018: jump_pose 130 | 11100000: //RootNode 131 | 13700000: Bip001 Pelvis 132 | materials: 133 | importMaterials: 1 134 | materialName: 3 135 | materialSearch: 1 136 | animations: 137 | legacyGenerateAnimations: 3 138 | bakeSimulation: 0 139 | optimizeGameObjects: 0 140 | motionNodeName: 141 | animationCompression: 0 142 | animationRotationError: .5 143 | animationPositionError: .5 144 | animationScaleError: .5 145 | animationWrapMode: 0 146 | extraExposedTransformPaths: [] 147 | clipAnimations: 148 | - serializedVersion: 16 149 | name: idle 150 | takeName: 151 | firstFrame: 2 152 | lastFrame: 62 153 | wrapMode: 2 154 | orientationOffsetY: 0 155 | level: 0 156 | cycleOffset: 0 157 | loop: 0 158 | loopTime: 0 159 | loopBlend: 0 160 | loopBlendOrientation: 0 161 | loopBlendPositionY: 0 162 | loopBlendPositionXZ: 0 163 | keepOriginalOrientation: 0 164 | keepOriginalPositionY: 1 165 | keepOriginalPositionXZ: 0 166 | heightFromFeet: 0 167 | mirror: 0 168 | bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 169 | curves: [] 170 | events: [] 171 | transformMask: [] 172 | maskType: 0 173 | maskSource: {instanceID: 0} 174 | - serializedVersion: 16 175 | name: run 176 | takeName: 177 | firstFrame: 65 178 | lastFrame: 81 179 | wrapMode: 2 180 | orientationOffsetY: 0 181 | level: 0 182 | cycleOffset: 0 183 | loop: 0 184 | loopTime: 0 185 | loopBlend: 0 186 | loopBlendOrientation: 0 187 | loopBlendPositionY: 0 188 | loopBlendPositionXZ: 0 189 | keepOriginalOrientation: 0 190 | keepOriginalPositionY: 1 191 | keepOriginalPositionXZ: 0 192 | heightFromFeet: 0 193 | mirror: 0 194 | bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 195 | curves: [] 196 | events: [] 197 | transformMask: [] 198 | maskType: 0 199 | maskSource: {instanceID: 0} 200 | - serializedVersion: 16 201 | name: walk 202 | takeName: 203 | firstFrame: 84 204 | lastFrame: 116 205 | wrapMode: 2 206 | orientationOffsetY: 0 207 | level: 0 208 | cycleOffset: 0 209 | loop: 0 210 | loopTime: 0 211 | loopBlend: 0 212 | loopBlendOrientation: 0 213 | loopBlendPositionY: 0 214 | loopBlendPositionXZ: 0 215 | keepOriginalOrientation: 0 216 | keepOriginalPositionY: 1 217 | keepOriginalPositionXZ: 0 218 | heightFromFeet: 0 219 | mirror: 0 220 | bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 221 | curves: [] 222 | events: [] 223 | transformMask: [] 224 | maskType: 0 225 | maskSource: {instanceID: 0} 226 | - serializedVersion: 16 227 | name: jump_pose 228 | takeName: 229 | firstFrame: 118 230 | lastFrame: 123 231 | wrapMode: 0 232 | orientationOffsetY: 0 233 | level: 0 234 | cycleOffset: 0 235 | loop: 0 236 | loopTime: 0 237 | loopBlend: 0 238 | loopBlendOrientation: 0 239 | loopBlendPositionY: 0 240 | loopBlendPositionXZ: 0 241 | keepOriginalOrientation: 0 242 | keepOriginalPositionY: 1 243 | keepOriginalPositionXZ: 0 244 | heightFromFeet: 0 245 | mirror: 0 246 | bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 247 | curves: [] 248 | events: [] 249 | transformMask: [] 250 | maskType: 0 251 | maskSource: {instanceID: 0} 252 | isReadable: 1 253 | meshes: 254 | lODScreenPercentages: [] 255 | globalScale: .00999999978 256 | meshCompression: 0 257 | addColliders: 0 258 | importBlendShapes: 1 259 | swapUVChannels: 0 260 | generateSecondaryUV: 0 261 | useFileUnits: 1 262 | optimizeMeshForGPU: 1 263 | weldVertices: 1 264 | secondaryUVAngleDistortion: 8 265 | secondaryUVAreaDistortion: 15.000001 266 | secondaryUVHardAngle: 88 267 | secondaryUVPackMargin: 4 268 | tangentSpace: 269 | normalSmoothAngle: 60 270 | splitTangentsAcrossUV: 1 271 | normalImportMode: 0 272 | tangentImportMode: 1 273 | importAnimation: 1 274 | copyAvatar: 0 275 | humanDescription: 276 | human: [] 277 | skeleton: [] 278 | armTwist: .5 279 | foreArmTwist: .5 280 | upperLegTwist: .5 281 | legTwist: .5 282 | armStretch: .0500000007 283 | legStretch: .0500000007 284 | feetSpacing: 0 285 | rootMotionBoneName: 286 | lastHumanDescriptionAvatarSource: {instanceID: 0} 287 | animationType: 1 288 | additionalBone: 0 289 | userData: 290 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e53c8c3dcc4ff59438bc9e86cb45c3f6 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Materials/constructor_done.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Materials/constructor_done.mat -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Materials/constructor_done.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca49380a71a2bb64c830d06bd421b9d1 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b365e6042890d4b1987423ed6bb8a08c 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures/constructor_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures/constructor_diffuse.png -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures/constructor_diffuse.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 97b050d43ac7c4d2b9f6cbb587650761 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: -1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 0 42 | textureType: -1 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures/constructor_normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures/constructor_normals.png -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter/Textures/constructor_normals.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 531c14f8d5cdc4e5baa83ee6e16f783a 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 1 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 1 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: 1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 0 42 | textureType: 1 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f781c091d1c8647c380d5230adfaee54 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/CharacterMotor.js: -------------------------------------------------------------------------------- 1 | #pragma strict 2 | #pragma implicit 3 | #pragma downcast 4 | 5 | // Does this script currently respond to input? 6 | var canControl : boolean = true; 7 | 8 | var useFixedUpdate : boolean = true; 9 | 10 | // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view. 11 | // Very handy for organization! 12 | 13 | // The current global direction we want the character to move in. 14 | @System.NonSerialized 15 | var inputMoveDirection : Vector3 = Vector3.zero; 16 | 17 | // Is the jump button held down? We use this interface instead of checking 18 | // for the jump button directly so this script can also be used by AIs. 19 | @System.NonSerialized 20 | var inputJump : boolean = false; 21 | 22 | class CharacterMotorMovement { 23 | // The maximum horizontal speed when moving 24 | var maxForwardSpeed : float = 10.0; 25 | var maxSidewaysSpeed : float = 10.0; 26 | var maxBackwardsSpeed : float = 10.0; 27 | 28 | // Curve for multiplying speed based on slope (negative = downwards) 29 | var slopeSpeedMultiplier : AnimationCurve = AnimationCurve(Keyframe(-90, 1), Keyframe(0, 1), Keyframe(90, 0)); 30 | 31 | // How fast does the character change speeds? Higher is faster. 32 | var maxGroundAcceleration : float = 30.0; 33 | var maxAirAcceleration : float = 20.0; 34 | 35 | // The gravity for the character 36 | var gravity : float = 10.0; 37 | var maxFallSpeed : float = 20.0; 38 | 39 | // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view. 40 | // Very handy for organization! 41 | 42 | // The last collision flags returned from controller.Move 43 | @System.NonSerialized 44 | var collisionFlags : CollisionFlags; 45 | 46 | // We will keep track of the character's current velocity, 47 | @System.NonSerialized 48 | var velocity : Vector3; 49 | 50 | // This keeps track of our current velocity while we're not grounded 51 | @System.NonSerialized 52 | var frameVelocity : Vector3 = Vector3.zero; 53 | 54 | @System.NonSerialized 55 | var hitPoint : Vector3 = Vector3.zero; 56 | 57 | @System.NonSerialized 58 | var lastHitPoint : Vector3 = Vector3(Mathf.Infinity, 0, 0); 59 | } 60 | 61 | var movement : CharacterMotorMovement = CharacterMotorMovement(); 62 | 63 | enum MovementTransferOnJump { 64 | None, // The jump is not affected by velocity of floor at all. 65 | InitTransfer, // Jump gets its initial velocity from the floor, then gradualy comes to a stop. 66 | PermaTransfer, // Jump gets its initial velocity from the floor, and keeps that velocity until landing. 67 | PermaLocked // Jump is relative to the movement of the last touched floor and will move together with that floor. 68 | } 69 | 70 | // We will contain all the jumping related variables in one helper class for clarity. 71 | class CharacterMotorJumping { 72 | // Can the character jump? 73 | var enabled : boolean = true; 74 | 75 | // How high do we jump when pressing jump and letting go immediately 76 | var baseHeight : float = 1.0; 77 | 78 | // We add extraHeight units (meters) on top when holding the button down longer while jumping 79 | var extraHeight : float = 4.1; 80 | 81 | // How much does the character jump out perpendicular to the surface on walkable surfaces? 82 | // 0 means a fully vertical jump and 1 means fully perpendicular. 83 | var perpAmount : float = 0.0; 84 | 85 | // How much does the character jump out perpendicular to the surface on too steep surfaces? 86 | // 0 means a fully vertical jump and 1 means fully perpendicular. 87 | var steepPerpAmount : float = 0.5; 88 | 89 | // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view. 90 | // Very handy for organization! 91 | 92 | // Are we jumping? (Initiated with jump button and not grounded yet) 93 | // To see if we are just in the air (initiated by jumping OR falling) see the grounded variable. 94 | @System.NonSerialized 95 | var jumping : boolean = false; 96 | 97 | @System.NonSerialized 98 | var holdingJumpButton : boolean = false; 99 | 100 | // the time we jumped at (Used to determine for how long to apply extra jump power after jumping.) 101 | @System.NonSerialized 102 | var lastStartTime : float = 0.0; 103 | 104 | @System.NonSerialized 105 | var lastButtonDownTime : float = -100; 106 | 107 | @System.NonSerialized 108 | var jumpDir : Vector3 = Vector3.up; 109 | } 110 | 111 | var jumping : CharacterMotorJumping = CharacterMotorJumping(); 112 | 113 | class CharacterMotorMovingPlatform { 114 | var enabled : boolean = true; 115 | 116 | var movementTransfer : MovementTransferOnJump = MovementTransferOnJump.PermaTransfer; 117 | 118 | @System.NonSerialized 119 | var hitPlatform : Transform; 120 | 121 | @System.NonSerialized 122 | var activePlatform : Transform; 123 | 124 | @System.NonSerialized 125 | var activeLocalPoint : Vector3; 126 | 127 | @System.NonSerialized 128 | var activeGlobalPoint : Vector3; 129 | 130 | @System.NonSerialized 131 | var activeLocalRotation : Quaternion; 132 | 133 | @System.NonSerialized 134 | var activeGlobalRotation : Quaternion; 135 | 136 | @System.NonSerialized 137 | var lastMatrix : Matrix4x4; 138 | 139 | @System.NonSerialized 140 | var platformVelocity : Vector3; 141 | 142 | @System.NonSerialized 143 | var newPlatform : boolean; 144 | } 145 | 146 | var movingPlatform : CharacterMotorMovingPlatform = CharacterMotorMovingPlatform(); 147 | 148 | class CharacterMotorSliding { 149 | // Does the character slide on too steep surfaces? 150 | var enabled : boolean = true; 151 | 152 | // How fast does the character slide on steep surfaces? 153 | var slidingSpeed : float = 15; 154 | 155 | // How much can the player control the sliding direction? 156 | // If the value is 0.5 the player can slide sideways with half the speed of the downwards sliding speed. 157 | var sidewaysControl : float = 1.0; 158 | 159 | // How much can the player influence the sliding speed? 160 | // If the value is 0.5 the player can speed the sliding up to 150% or slow it down to 50%. 161 | var speedControl : float = 0.4; 162 | } 163 | 164 | var sliding : CharacterMotorSliding = CharacterMotorSliding(); 165 | 166 | @System.NonSerialized 167 | var grounded : boolean = true; 168 | 169 | @System.NonSerialized 170 | var groundNormal : Vector3 = Vector3.zero; 171 | 172 | private var lastGroundNormal : Vector3 = Vector3.zero; 173 | 174 | private var tr : Transform; 175 | 176 | private var controller : CharacterController; 177 | 178 | function Awake () { 179 | controller = GetComponent (CharacterController); 180 | tr = transform; 181 | } 182 | 183 | private function UpdateFunction () { 184 | // We copy the actual velocity into a temporary variable that we can manipulate. 185 | var velocity : Vector3 = movement.velocity; 186 | 187 | // Update velocity based on input 188 | velocity = ApplyInputVelocityChange(velocity); 189 | 190 | // Apply gravity and jumping force 191 | velocity = ApplyGravityAndJumping (velocity); 192 | 193 | // Moving platform support 194 | var moveDistance : Vector3 = Vector3.zero; 195 | if (MoveWithPlatform()) { 196 | var newGlobalPoint : Vector3 = movingPlatform.activePlatform.TransformPoint(movingPlatform.activeLocalPoint); 197 | moveDistance = (newGlobalPoint - movingPlatform.activeGlobalPoint); 198 | if (moveDistance != Vector3.zero) 199 | controller.Move(moveDistance); 200 | 201 | // Support moving platform rotation as well: 202 | var newGlobalRotation : Quaternion = movingPlatform.activePlatform.rotation * movingPlatform.activeLocalRotation; 203 | var rotationDiff : Quaternion = newGlobalRotation * Quaternion.Inverse(movingPlatform.activeGlobalRotation); 204 | 205 | var yRotation = rotationDiff.eulerAngles.y; 206 | if (yRotation != 0) { 207 | // Prevent rotation of the local up vector 208 | tr.Rotate(0, yRotation, 0); 209 | } 210 | } 211 | 212 | // Save lastPosition for velocity calculation. 213 | var lastPosition : Vector3 = tr.position; 214 | 215 | // We always want the movement to be framerate independent. Multiplying by Time.deltaTime does this. 216 | var currentMovementOffset : Vector3 = velocity * Time.deltaTime; 217 | 218 | // Find out how much we need to push towards the ground to avoid loosing grouning 219 | // when walking down a step or over a sharp change in slope. 220 | var pushDownOffset : float = Mathf.Max(controller.stepOffset, Vector3(currentMovementOffset.x, 0, currentMovementOffset.z).magnitude); 221 | if (grounded) 222 | currentMovementOffset -= pushDownOffset * Vector3.up; 223 | 224 | // Reset variables that will be set by collision function 225 | movingPlatform.hitPlatform = null; 226 | groundNormal = Vector3.zero; 227 | 228 | // Move our character! 229 | movement.collisionFlags = controller.Move (currentMovementOffset); 230 | 231 | movement.lastHitPoint = movement.hitPoint; 232 | lastGroundNormal = groundNormal; 233 | 234 | if (movingPlatform.enabled && movingPlatform.activePlatform != movingPlatform.hitPlatform) { 235 | if (movingPlatform.hitPlatform != null) { 236 | movingPlatform.activePlatform = movingPlatform.hitPlatform; 237 | movingPlatform.lastMatrix = movingPlatform.hitPlatform.localToWorldMatrix; 238 | movingPlatform.newPlatform = true; 239 | } 240 | } 241 | 242 | // Calculate the velocity based on the current and previous position. 243 | // This means our velocity will only be the amount the character actually moved as a result of collisions. 244 | var oldHVelocity : Vector3 = new Vector3(velocity.x, 0, velocity.z); 245 | movement.velocity = (tr.position - lastPosition) / Time.deltaTime; 246 | var newHVelocity : Vector3 = new Vector3(movement.velocity.x, 0, movement.velocity.z); 247 | 248 | // The CharacterController can be moved in unwanted directions when colliding with things. 249 | // We want to prevent this from influencing the recorded velocity. 250 | if (oldHVelocity == Vector3.zero) { 251 | movement.velocity = new Vector3(0, movement.velocity.y, 0); 252 | } 253 | else { 254 | var projectedNewVelocity : float = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude; 255 | movement.velocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + movement.velocity.y * Vector3.up; 256 | } 257 | 258 | if (movement.velocity.y < velocity.y - 0.001) { 259 | if (movement.velocity.y < 0) { 260 | // Something is forcing the CharacterController down faster than it should. 261 | // Ignore this 262 | movement.velocity.y = velocity.y; 263 | } 264 | else { 265 | // The upwards movement of the CharacterController has been blocked. 266 | // This is treated like a ceiling collision - stop further jumping here. 267 | jumping.holdingJumpButton = false; 268 | } 269 | } 270 | 271 | // We were grounded but just loosed grounding 272 | if (grounded && !IsGroundedTest()) { 273 | grounded = false; 274 | 275 | // Apply inertia from platform 276 | if (movingPlatform.enabled && 277 | (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer || 278 | movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) 279 | ) { 280 | movement.frameVelocity = movingPlatform.platformVelocity; 281 | movement.velocity += movingPlatform.platformVelocity; 282 | } 283 | 284 | SendMessage("OnFall", SendMessageOptions.DontRequireReceiver); 285 | // We pushed the character down to ensure it would stay on the ground if there was any. 286 | // But there wasn't so now we cancel the downwards offset to make the fall smoother. 287 | tr.position += pushDownOffset * Vector3.up; 288 | } 289 | // We were not grounded but just landed on something 290 | else if (!grounded && IsGroundedTest()) { 291 | grounded = true; 292 | jumping.jumping = false; 293 | SubtractNewPlatformVelocity(); 294 | 295 | SendMessage("OnLand", SendMessageOptions.DontRequireReceiver); 296 | } 297 | 298 | // Moving platforms support 299 | if (MoveWithPlatform()) { 300 | // Use the center of the lower half sphere of the capsule as reference point. 301 | // This works best when the character is standing on moving tilting platforms. 302 | movingPlatform.activeGlobalPoint = tr.position + Vector3.up * (controller.center.y - controller.height*0.5 + controller.radius); 303 | movingPlatform.activeLocalPoint = movingPlatform.activePlatform.InverseTransformPoint(movingPlatform.activeGlobalPoint); 304 | 305 | // Support moving platform rotation as well: 306 | movingPlatform.activeGlobalRotation = tr.rotation; 307 | movingPlatform.activeLocalRotation = Quaternion.Inverse(movingPlatform.activePlatform.rotation) * movingPlatform.activeGlobalRotation; 308 | } 309 | } 310 | 311 | function FixedUpdate () { 312 | if (movingPlatform.enabled) { 313 | if (movingPlatform.activePlatform != null) { 314 | if (!movingPlatform.newPlatform) { 315 | var lastVelocity : Vector3 = movingPlatform.platformVelocity; 316 | 317 | movingPlatform.platformVelocity = ( 318 | movingPlatform.activePlatform.localToWorldMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint) 319 | - movingPlatform.lastMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint) 320 | ) / Time.deltaTime; 321 | } 322 | movingPlatform.lastMatrix = movingPlatform.activePlatform.localToWorldMatrix; 323 | movingPlatform.newPlatform = false; 324 | } 325 | else { 326 | movingPlatform.platformVelocity = Vector3.zero; 327 | } 328 | } 329 | 330 | if (useFixedUpdate) 331 | UpdateFunction(); 332 | } 333 | 334 | function Update () { 335 | if (!useFixedUpdate) 336 | UpdateFunction(); 337 | } 338 | 339 | private function ApplyInputVelocityChange (velocity : Vector3) { 340 | if (!canControl) 341 | inputMoveDirection = Vector3.zero; 342 | 343 | // Find desired velocity 344 | var desiredVelocity : Vector3; 345 | if (grounded && TooSteep()) { 346 | // The direction we're sliding in 347 | desiredVelocity = Vector3(groundNormal.x, 0, groundNormal.z).normalized; 348 | // Find the input movement direction projected onto the sliding direction 349 | var projectedMoveDir = Vector3.Project(inputMoveDirection, desiredVelocity); 350 | // Add the sliding direction, the spped control, and the sideways control vectors 351 | desiredVelocity = desiredVelocity + projectedMoveDir * sliding.speedControl + (inputMoveDirection - projectedMoveDir) * sliding.sidewaysControl; 352 | // Multiply with the sliding speed 353 | desiredVelocity *= sliding.slidingSpeed; 354 | } 355 | else 356 | desiredVelocity = GetDesiredHorizontalVelocity(); 357 | 358 | if (movingPlatform.enabled && movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) { 359 | desiredVelocity += movement.frameVelocity; 360 | desiredVelocity.y = 0; 361 | } 362 | 363 | if (grounded) 364 | desiredVelocity = AdjustGroundVelocityToNormal(desiredVelocity, groundNormal); 365 | else 366 | velocity.y = 0; 367 | 368 | // Enforce max velocity change 369 | var maxVelocityChange : float = GetMaxAcceleration(grounded) * Time.deltaTime; 370 | var velocityChangeVector : Vector3 = (desiredVelocity - velocity); 371 | if (velocityChangeVector.sqrMagnitude > maxVelocityChange * maxVelocityChange) { 372 | velocityChangeVector = velocityChangeVector.normalized * maxVelocityChange; 373 | } 374 | // If we're in the air and don't have control, don't apply any velocity change at all. 375 | // If we're on the ground and don't have control we do apply it - it will correspond to friction. 376 | if (grounded || canControl) 377 | velocity += velocityChangeVector; 378 | 379 | if (grounded) { 380 | // When going uphill, the CharacterController will automatically move up by the needed amount. 381 | // Not moving it upwards manually prevent risk of lifting off from the ground. 382 | // When going downhill, DO move down manually, as gravity is not enough on steep hills. 383 | velocity.y = Mathf.Min(velocity.y, 0); 384 | } 385 | 386 | return velocity; 387 | } 388 | 389 | private function ApplyGravityAndJumping (velocity : Vector3) { 390 | 391 | if (!inputJump || !canControl) { 392 | jumping.holdingJumpButton = false; 393 | jumping.lastButtonDownTime = -100; 394 | } 395 | 396 | if (inputJump && jumping.lastButtonDownTime < 0 && canControl) 397 | jumping.lastButtonDownTime = Time.time; 398 | 399 | if (grounded) 400 | velocity.y = Mathf.Min(0, velocity.y) - movement.gravity * Time.deltaTime; 401 | else { 402 | velocity.y = movement.velocity.y - movement.gravity * Time.deltaTime; 403 | 404 | // When jumping up we don't apply gravity for some time when the user is holding the jump button. 405 | // This gives more control over jump height by pressing the button longer. 406 | if (jumping.jumping && jumping.holdingJumpButton) { 407 | // Calculate the duration that the extra jump force should have effect. 408 | // If we're still less than that duration after the jumping time, apply the force. 409 | if (Time.time < jumping.lastStartTime + jumping.extraHeight / CalculateJumpVerticalSpeed(jumping.baseHeight)) { 410 | // Negate the gravity we just applied, except we push in jumpDir rather than jump upwards. 411 | velocity += jumping.jumpDir * movement.gravity * Time.deltaTime; 412 | } 413 | } 414 | 415 | // Make sure we don't fall any faster than maxFallSpeed. This gives our character a terminal velocity. 416 | velocity.y = Mathf.Max (velocity.y, -movement.maxFallSpeed); 417 | } 418 | 419 | if (grounded) { 420 | // Jump only if the jump button was pressed down in the last 0.2 seconds. 421 | // We use this check instead of checking if it's pressed down right now 422 | // because players will often try to jump in the exact moment when hitting the ground after a jump 423 | // and if they hit the button a fraction of a second too soon and no new jump happens as a consequence, 424 | // it's confusing and it feels like the game is buggy. 425 | if (jumping.enabled && canControl && (Time.time - jumping.lastButtonDownTime < 0.2)) { 426 | grounded = false; 427 | jumping.jumping = true; 428 | jumping.lastStartTime = Time.time; 429 | jumping.lastButtonDownTime = -100; 430 | jumping.holdingJumpButton = true; 431 | 432 | // Calculate the jumping direction 433 | if (TooSteep()) 434 | jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.steepPerpAmount); 435 | else 436 | jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.perpAmount); 437 | 438 | // Apply the jumping force to the velocity. Cancel any vertical velocity first. 439 | velocity.y = 0; 440 | velocity += jumping.jumpDir * CalculateJumpVerticalSpeed (jumping.baseHeight); 441 | 442 | // Apply inertia from platform 443 | if (movingPlatform.enabled && 444 | (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer || 445 | movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) 446 | ) { 447 | movement.frameVelocity = movingPlatform.platformVelocity; 448 | velocity += movingPlatform.platformVelocity; 449 | } 450 | 451 | SendMessage("OnJump", SendMessageOptions.DontRequireReceiver); 452 | } 453 | else { 454 | jumping.holdingJumpButton = false; 455 | } 456 | } 457 | 458 | return velocity; 459 | } 460 | 461 | function OnControllerColliderHit (hit : ControllerColliderHit) { 462 | if (hit.normal.y > 0 && hit.normal.y > groundNormal.y && hit.moveDirection.y < 0) { 463 | if ((hit.point - movement.lastHitPoint).sqrMagnitude > 0.001 || lastGroundNormal == Vector3.zero) 464 | groundNormal = hit.normal; 465 | else 466 | groundNormal = lastGroundNormal; 467 | 468 | movingPlatform.hitPlatform = hit.collider.transform; 469 | movement.hitPoint = hit.point; 470 | movement.frameVelocity = Vector3.zero; 471 | } 472 | } 473 | 474 | private function SubtractNewPlatformVelocity () { 475 | // When landing, subtract the velocity of the new ground from the character's velocity 476 | // since movement in ground is relative to the movement of the ground. 477 | if (movingPlatform.enabled && 478 | (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer || 479 | movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) 480 | ) { 481 | // If we landed on a new platform, we have to wait for two FixedUpdates 482 | // before we know the velocity of the platform under the character 483 | if (movingPlatform.newPlatform) { 484 | var platform : Transform = movingPlatform.activePlatform; 485 | yield WaitForFixedUpdate(); 486 | yield WaitForFixedUpdate(); 487 | if (grounded && platform == movingPlatform.activePlatform) 488 | yield 1; 489 | } 490 | movement.velocity -= movingPlatform.platformVelocity; 491 | } 492 | } 493 | 494 | private function MoveWithPlatform () : boolean { 495 | return ( 496 | movingPlatform.enabled 497 | && (grounded || movingPlatform.movementTransfer == MovementTransferOnJump.PermaLocked) 498 | && movingPlatform.activePlatform != null 499 | ); 500 | } 501 | 502 | private function GetDesiredHorizontalVelocity () { 503 | // Find desired velocity 504 | var desiredLocalDirection : Vector3 = tr.InverseTransformDirection(inputMoveDirection); 505 | var maxSpeed : float = MaxSpeedInDirection(desiredLocalDirection); 506 | if (grounded) { 507 | // Modify max speed on slopes based on slope speed multiplier curve 508 | var movementSlopeAngle = Mathf.Asin(movement.velocity.normalized.y) * Mathf.Rad2Deg; 509 | maxSpeed *= movement.slopeSpeedMultiplier.Evaluate(movementSlopeAngle); 510 | } 511 | return tr.TransformDirection(desiredLocalDirection * maxSpeed); 512 | } 513 | 514 | private function AdjustGroundVelocityToNormal (hVelocity : Vector3, groundNormal : Vector3) : Vector3 { 515 | var sideways : Vector3 = Vector3.Cross(Vector3.up, hVelocity); 516 | return Vector3.Cross(sideways, groundNormal).normalized * hVelocity.magnitude; 517 | } 518 | 519 | private function IsGroundedTest () { 520 | return (groundNormal.y > 0.01); 521 | } 522 | 523 | function GetMaxAcceleration (grounded : boolean) : float { 524 | // Maximum acceleration on ground and in air 525 | if (grounded) 526 | return movement.maxGroundAcceleration; 527 | else 528 | return movement.maxAirAcceleration; 529 | } 530 | 531 | function CalculateJumpVerticalSpeed (targetJumpHeight : float) { 532 | // From the jump height and gravity we deduce the upwards speed 533 | // for the character to reach at the apex. 534 | return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity); 535 | } 536 | 537 | function IsJumping () { 538 | return jumping.jumping; 539 | } 540 | 541 | function IsSliding () { 542 | return (grounded && sliding.enabled && TooSteep()); 543 | } 544 | 545 | function IsTouchingCeiling () { 546 | return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0; 547 | } 548 | 549 | function IsGrounded () { 550 | return grounded; 551 | } 552 | 553 | function TooSteep () { 554 | return (groundNormal.y <= Mathf.Cos(controller.slopeLimit * Mathf.Deg2Rad)); 555 | } 556 | 557 | function GetDirection () { 558 | return inputMoveDirection; 559 | } 560 | 561 | function SetControllable (controllable : boolean) { 562 | canControl = controllable; 563 | } 564 | 565 | // Project a direction onto elliptical quater segments based on forward, sideways, and backwards speed. 566 | // The function returns the length of the resulting vector. 567 | function MaxSpeedInDirection (desiredMovementDirection : Vector3) : float { 568 | if (desiredMovementDirection == Vector3.zero) 569 | return 0; 570 | else { 571 | var zAxisEllipseMultiplier : float = (desiredMovementDirection.z > 0 ? movement.maxForwardSpeed : movement.maxBackwardsSpeed) / movement.maxSidewaysSpeed; 572 | var temp : Vector3 = new Vector3(desiredMovementDirection.x, 0, desiredMovementDirection.z / zAxisEllipseMultiplier).normalized; 573 | var length : float = new Vector3(temp.x, 0, temp.z * zAxisEllipseMultiplier).magnitude * movement.maxSidewaysSpeed; 574 | return length; 575 | } 576 | } 577 | 578 | function SetVelocity (velocity : Vector3) { 579 | grounded = false; 580 | movement.velocity = velocity; 581 | movement.frameVelocity = Vector3.zero; 582 | SendMessage("OnExternalVelocity"); 583 | } 584 | 585 | // Require a character controller to be attached to the same game object 586 | @script RequireComponent (CharacterController) 587 | @script AddComponentMenu ("Character/Character Motor") 588 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/CharacterMotor.js.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ab79d7f243824f5d9826bd83522c8df 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/FPSInputController.js: -------------------------------------------------------------------------------- 1 | private var motor : CharacterMotor; 2 | 3 | // Use this for initialization 4 | function Awake () { 5 | motor = GetComponent(CharacterMotor); 6 | } 7 | 8 | // Update is called once per frame 9 | function Update () { 10 | // Get the input vector from keyboard or analog stick 11 | var directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); 12 | 13 | if (directionVector != Vector3.zero) { 14 | // Get the length of the directon vector and then normalize it 15 | // Dividing by the length is cheaper than normalizing when we already have the length anyway 16 | var directionLength = directionVector.magnitude; 17 | directionVector = directionVector / directionLength; 18 | 19 | // Make sure the length is no bigger than 1 20 | directionLength = Mathf.Min(1, directionLength); 21 | 22 | // Make the input vector more sensitive towards the extremes and less sensitive in the middle 23 | // This makes it easier to control slow speeds when using analog sticks 24 | directionLength = directionLength * directionLength; 25 | 26 | // Multiply the normalized direction vector by the modified length 27 | directionVector = directionVector * directionLength; 28 | } 29 | 30 | // Apply the direction to the CharacterMotor 31 | motor.inputMoveDirection = transform.rotation * directionVector; 32 | motor.inputJump = Input.GetButton("Jump"); 33 | } 34 | 35 | // Require a character controller to be attached to the same game object 36 | @script RequireComponent (CharacterMotor) 37 | @script AddComponentMenu ("Character/FPS Input Controller") 38 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/FPSInputController.js.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 60bca8f58a0b8478e946e6e86658cb29 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/MouseLook.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | /// MouseLook rotates the transform based on the mouse delta. 5 | /// Minimum and Maximum values can be used to constrain the possible rotation 6 | 7 | /// To make an FPS style character: 8 | /// - Create a capsule. 9 | /// - Add the MouseLook script to the capsule. 10 | /// -> Set the mouse look to use LookX. (You want to only turn character but not tilt it) 11 | /// - Add FPSInputController script to the capsule 12 | /// -> A CharacterMotor and a CharacterController component will be automatically added. 13 | 14 | /// - Create a camera. Make the camera a child of the capsule. Reset it's transform. 15 | /// - Add a MouseLook script to the camera. 16 | /// -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.) 17 | [AddComponentMenu("Camera-Control/Mouse Look")] 18 | public class MouseLook : MonoBehaviour { 19 | 20 | public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 } 21 | public RotationAxes axes = RotationAxes.MouseXAndY; 22 | public float sensitivityX = 15F; 23 | public float sensitivityY = 15F; 24 | 25 | public float minimumX = -360F; 26 | public float maximumX = 360F; 27 | 28 | public float minimumY = -60F; 29 | public float maximumY = 60F; 30 | 31 | float rotationY = 0F; 32 | 33 | void Update () 34 | { 35 | if (axes == RotationAxes.MouseXAndY) 36 | { 37 | float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX; 38 | 39 | rotationY += Input.GetAxis("Mouse Y") * sensitivityY; 40 | rotationY = Mathf.Clamp (rotationY, minimumY, maximumY); 41 | 42 | transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0); 43 | } 44 | else if (axes == RotationAxes.MouseX) 45 | { 46 | transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0); 47 | } 48 | else 49 | { 50 | rotationY += Input.GetAxis("Mouse Y") * sensitivityY; 51 | rotationY = Mathf.Clamp (rotationY, minimumY, maximumY); 52 | 53 | transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0); 54 | } 55 | } 56 | 57 | void Start () 58 | { 59 | // Make the rigid body not change rotation 60 | if (GetComponent()) 61 | GetComponent().freezeRotation = true; 62 | } 63 | } -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/MouseLook.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68ec2fe99d1108b9d0006a298d76c639 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/PlatformInputController.js: -------------------------------------------------------------------------------- 1 | // This makes the character turn to face the current movement speed per default. 2 | var autoRotate : boolean = true; 3 | var maxRotationSpeed : float = 360; 4 | 5 | private var motor : CharacterMotor; 6 | 7 | // Use this for initialization 8 | function Awake () { 9 | motor = GetComponent(CharacterMotor); 10 | } 11 | 12 | // Update is called once per frame 13 | function Update () { 14 | // Get the input vector from keyboard or analog stick 15 | var directionVector = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0); 16 | 17 | if (directionVector != Vector3.zero) { 18 | // Get the length of the directon vector and then normalize it 19 | // Dividing by the length is cheaper than normalizing when we already have the length anyway 20 | var directionLength = directionVector.magnitude; 21 | directionVector = directionVector / directionLength; 22 | 23 | // Make sure the length is no bigger than 1 24 | directionLength = Mathf.Min(1, directionLength); 25 | 26 | // Make the input vector more sensitive towards the extremes and less sensitive in the middle 27 | // This makes it easier to control slow speeds when using analog sticks 28 | directionLength = directionLength * directionLength; 29 | 30 | // Multiply the normalized direction vector by the modified length 31 | directionVector = directionVector * directionLength; 32 | } 33 | 34 | // Rotate the input vector into camera space so up is camera's up and right is camera's right 35 | directionVector = Camera.main.transform.rotation * directionVector; 36 | 37 | // Rotate input vector to be perpendicular to character's up vector 38 | var camToCharacterSpace = Quaternion.FromToRotation(-Camera.main.transform.forward, transform.up); 39 | directionVector = (camToCharacterSpace * directionVector); 40 | 41 | // Apply the direction to the CharacterMotor 42 | motor.inputMoveDirection = directionVector; 43 | motor.inputJump = Input.GetButton("Jump"); 44 | 45 | // Set rotation to the move direction 46 | if (autoRotate && directionVector.sqrMagnitude > 0.01) { 47 | var newForward : Vector3 = ConstantSlerp( 48 | transform.forward, 49 | directionVector, 50 | maxRotationSpeed * Time.deltaTime 51 | ); 52 | newForward = ProjectOntoPlane(newForward, transform.up); 53 | transform.rotation = Quaternion.LookRotation(newForward, transform.up); 54 | } 55 | } 56 | 57 | function ProjectOntoPlane (v : Vector3, normal : Vector3) { 58 | return v - Vector3.Project(v, normal); 59 | } 60 | 61 | function ConstantSlerp (from : Vector3, to : Vector3, angle : float) { 62 | var value : float = Mathf.Min(1, angle / Vector3.Angle(from, to)); 63 | return Vector3.Slerp(from, to, value); 64 | } 65 | 66 | // Require a character controller to be attached to the same game object 67 | @script RequireComponent (CharacterMotor) 68 | @script AddComponentMenu ("Character/Platform Input Controller") 69 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/PlatformInputController.js.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da93ddd6928094e24bb1f3f665f143d3 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/ThirdPersonCamera.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var cameraTransform : Transform; 4 | private var _target : Transform; 5 | 6 | // The distance in the x-z plane to the target 7 | 8 | var distance = 7.0; 9 | 10 | // the height we want the camera to be above the target 11 | var height = 3.0; 12 | 13 | var angularSmoothLag = 0.3; 14 | var angularMaxSpeed = 15.0; 15 | 16 | var heightSmoothLag = 0.3; 17 | 18 | var snapSmoothLag = 0.2; 19 | var snapMaxSpeed = 720.0; 20 | 21 | var clampHeadPositionScreenSpace = 0.75; 22 | 23 | var lockCameraTimeout = 0.2; 24 | 25 | private var headOffset = Vector3.zero; 26 | private var centerOffset = Vector3.zero; 27 | 28 | private var heightVelocity = 0.0; 29 | private var angleVelocity = 0.0; 30 | private var snap = false; 31 | private var controller : ThirdPersonController; 32 | private var targetHeight = 100000.0; 33 | 34 | function Awake () 35 | { 36 | if(!cameraTransform && Camera.main) 37 | cameraTransform = Camera.main.transform; 38 | if(!cameraTransform) { 39 | Debug.Log("Please assign a camera to the ThirdPersonCamera script."); 40 | enabled = false; 41 | } 42 | 43 | 44 | _target = transform; 45 | if (_target) 46 | { 47 | controller = _target.GetComponent(ThirdPersonController); 48 | } 49 | 50 | if (controller) 51 | { 52 | var characterController : CharacterController = _target.GetComponent.(); 53 | centerOffset = characterController.bounds.center - _target.position; 54 | headOffset = centerOffset; 55 | headOffset.y = characterController.bounds.max.y - _target.position.y; 56 | } 57 | else 58 | Debug.Log("Please assign a target to the camera that has a ThirdPersonController script attached."); 59 | 60 | 61 | Cut(_target, centerOffset); 62 | } 63 | 64 | function DebugDrawStuff () 65 | { 66 | Debug.DrawLine(_target.position, _target.position + headOffset); 67 | 68 | } 69 | 70 | function AngleDistance (a : float, b : float) 71 | { 72 | a = Mathf.Repeat(a, 360); 73 | b = Mathf.Repeat(b, 360); 74 | 75 | return Mathf.Abs(b - a); 76 | } 77 | 78 | function Apply (dummyTarget : Transform, dummyCenter : Vector3) 79 | { 80 | // Early out if we don't have a target 81 | if (!controller) 82 | return; 83 | 84 | var targetCenter = _target.position + centerOffset; 85 | var targetHead = _target.position + headOffset; 86 | 87 | // DebugDrawStuff(); 88 | 89 | // Calculate the current & target rotation angles 90 | var originalTargetAngle = _target.eulerAngles.y; 91 | var currentAngle = cameraTransform.eulerAngles.y; 92 | 93 | // Adjust real target angle when camera is locked 94 | var targetAngle = originalTargetAngle; 95 | 96 | // When pressing Fire2 (alt) the camera will snap to the target direction real quick. 97 | // It will stop snapping when it reaches the target 98 | if (Input.GetButton("Fire2")) 99 | snap = true; 100 | 101 | if (snap) 102 | { 103 | // We are close to the target, so we can stop snapping now! 104 | if (AngleDistance (currentAngle, originalTargetAngle) < 3.0) 105 | snap = false; 106 | 107 | currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, snapSmoothLag, snapMaxSpeed); 108 | } 109 | // Normal camera motion 110 | else 111 | { 112 | if (controller.GetLockCameraTimer () < lockCameraTimeout) 113 | { 114 | targetAngle = currentAngle; 115 | } 116 | 117 | // Lock the camera when moving backwards! 118 | // * It is really confusing to do 180 degree spins when turning around. 119 | if (AngleDistance (currentAngle, targetAngle) > 160 && controller.IsMovingBackwards ()) 120 | targetAngle += 180; 121 | 122 | currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, angularSmoothLag, angularMaxSpeed); 123 | } 124 | 125 | 126 | // When jumping don't move camera upwards but only down! 127 | if (controller.IsJumping ()) 128 | { 129 | // We'd be moving the camera upwards, do that only if it's really high 130 | var newTargetHeight = targetCenter.y + height; 131 | if (newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5) 132 | targetHeight = targetCenter.y + height; 133 | } 134 | // When walking always update the target height 135 | else 136 | { 137 | targetHeight = targetCenter.y + height; 138 | } 139 | 140 | // Damp the height 141 | var currentHeight = cameraTransform.position.y; 142 | currentHeight = Mathf.SmoothDamp (currentHeight, targetHeight, heightVelocity, heightSmoothLag); 143 | 144 | // Convert the angle into a rotation, by which we then reposition the camera 145 | var currentRotation = Quaternion.Euler (0, currentAngle, 0); 146 | 147 | // Set the position of the camera on the x-z plane to: 148 | // distance meters behind the target 149 | cameraTransform.position = targetCenter; 150 | cameraTransform.position += currentRotation * Vector3.back * distance; 151 | 152 | // Set the height of the camera 153 | cameraTransform.position.y = currentHeight; 154 | 155 | // Always look at the target 156 | SetUpRotation(targetCenter, targetHead); 157 | } 158 | 159 | function LateUpdate () { 160 | Apply (transform, Vector3.zero); 161 | } 162 | 163 | function Cut (dummyTarget : Transform, dummyCenter : Vector3) 164 | { 165 | var oldHeightSmooth = heightSmoothLag; 166 | var oldSnapMaxSpeed = snapMaxSpeed; 167 | var oldSnapSmooth = snapSmoothLag; 168 | 169 | snapMaxSpeed = 10000; 170 | snapSmoothLag = 0.001; 171 | heightSmoothLag = 0.001; 172 | 173 | snap = true; 174 | Apply (transform, Vector3.zero); 175 | 176 | heightSmoothLag = oldHeightSmooth; 177 | snapMaxSpeed = oldSnapMaxSpeed; 178 | snapSmoothLag = oldSnapSmooth; 179 | } 180 | 181 | function SetUpRotation (centerPos : Vector3, headPos : Vector3) 182 | { 183 | // Now it's getting hairy. The devil is in the details here, the big issue is jumping of course. 184 | // * When jumping up and down we don't want to center the guy in screen space. 185 | // This is important to give a feel for how high you jump and avoiding large camera movements. 186 | // 187 | // * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth. 188 | // 189 | // So here is what we will do: 190 | // 191 | // 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis 192 | // 2. When grounded we make him be centered 193 | // 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold 194 | // 4. When landing we smoothly interpolate towards centering him on screen 195 | var cameraPos = cameraTransform.position; 196 | var offsetToCenter = centerPos - cameraPos; 197 | 198 | // Generate base rotation only around y-axis 199 | var yRotation = Quaternion.LookRotation(Vector3(offsetToCenter.x, 0, offsetToCenter.z)); 200 | 201 | var relativeOffset = Vector3.forward * distance + Vector3.down * height; 202 | cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset); 203 | 204 | // Calculate the projected center position and top position in world space 205 | var centerRay = cameraTransform.GetComponent.().ViewportPointToRay(Vector3(.5, 0.5, 1)); 206 | var topRay = cameraTransform.GetComponent.().ViewportPointToRay(Vector3(.5, clampHeadPositionScreenSpace, 1)); 207 | 208 | var centerRayPos = centerRay.GetPoint(distance); 209 | var topRayPos = topRay.GetPoint(distance); 210 | 211 | var centerToTopAngle = Vector3.Angle(centerRay.direction, topRay.direction); 212 | 213 | var heightToAngle = centerToTopAngle / (centerRayPos.y - topRayPos.y); 214 | 215 | var extraLookAngle = heightToAngle * (centerRayPos.y - centerPos.y); 216 | if (extraLookAngle < centerToTopAngle) 217 | { 218 | extraLookAngle = 0; 219 | } 220 | else 221 | { 222 | extraLookAngle = extraLookAngle - centerToTopAngle; 223 | cameraTransform.rotation *= Quaternion.Euler(-extraLookAngle, 0, 0); 224 | } 225 | } 226 | 227 | function GetCenterOffset () 228 | { 229 | return centerOffset; 230 | } 231 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/ThirdPersonCamera.js.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b167d00b3108411a8a963cba5ddde1b 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/ThirdPersonController.js: -------------------------------------------------------------------------------- 1 | 2 | // Require a character controller to be attached to the same game object 3 | @script RequireComponent(CharacterController) 4 | 5 | public var idleAnimation : AnimationClip; 6 | public var walkAnimation : AnimationClip; 7 | public var runAnimation : AnimationClip; 8 | public var jumpPoseAnimation : AnimationClip; 9 | 10 | public var walkMaxAnimationSpeed : float = 0.75; 11 | public var trotMaxAnimationSpeed : float = 1.0; 12 | public var runMaxAnimationSpeed : float = 1.0; 13 | public var jumpAnimationSpeed : float = 1.15; 14 | public var landAnimationSpeed : float = 1.0; 15 | 16 | private var _animation : Animation; 17 | 18 | enum CharacterState { 19 | Idle = 0, 20 | Walking = 1, 21 | Trotting = 2, 22 | Running = 3, 23 | Jumping = 4, 24 | } 25 | 26 | private var _characterState : CharacterState; 27 | 28 | // The speed when walking 29 | var walkSpeed = 2.0; 30 | // after trotAfterSeconds of walking we trot with trotSpeed 31 | var trotSpeed = 4.0; 32 | // when pressing "Fire3" button (cmd) we start running 33 | var runSpeed = 6.0; 34 | 35 | var inAirControlAcceleration = 3.0; 36 | 37 | // How high do we jump when pressing jump and letting go immediately 38 | var jumpHeight = 0.5; 39 | 40 | // The gravity for the character 41 | var gravity = 20.0; 42 | // The gravity in controlled descent mode 43 | var speedSmoothing = 10.0; 44 | var rotateSpeed = 500.0; 45 | var trotAfterSeconds = 3.0; 46 | 47 | var canJump = true; 48 | 49 | private var jumpRepeatTime = 0.05; 50 | private var jumpTimeout = 0.15; 51 | private var groundedTimeout = 0.25; 52 | 53 | // The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around. 54 | private var lockCameraTimer = 0.0; 55 | 56 | // The current move direction in x-z 57 | private var moveDirection = Vector3.zero; 58 | // The current vertical speed 59 | private var verticalSpeed = 0.0; 60 | // The current x-z move speed 61 | private var moveSpeed = 0.0; 62 | 63 | // The last collision flags returned from controller.Move 64 | private var collisionFlags : CollisionFlags; 65 | 66 | // Are we jumping? (Initiated with jump button and not grounded yet) 67 | private var jumping = false; 68 | private var jumpingReachedApex = false; 69 | 70 | // Are we moving backwards (This locks the camera to not do a 180 degree spin) 71 | private var movingBack = false; 72 | // Is the user pressing any keys? 73 | private var isMoving = false; 74 | // When did the user start walking (Used for going into trot after a while) 75 | private var walkTimeStart = 0.0; 76 | // Last time the jump button was clicked down 77 | private var lastJumpButtonTime = -10.0; 78 | // Last time we performed a jump 79 | private var lastJumpTime = -1.0; 80 | 81 | 82 | // the height we jumped from (Used to determine for how long to apply extra jump power after jumping.) 83 | private var lastJumpStartHeight = 0.0; 84 | 85 | 86 | private var inAirVelocity = Vector3.zero; 87 | 88 | private var lastGroundedTime = 0.0; 89 | 90 | 91 | private var isControllable = true; 92 | 93 | function Awake () 94 | { 95 | moveDirection = transform.TransformDirection(Vector3.forward); 96 | 97 | _animation = GetComponent(Animation); 98 | if(!_animation) 99 | Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird."); 100 | 101 | /* 102 | public var idleAnimation : AnimationClip; 103 | public var walkAnimation : AnimationClip; 104 | public var runAnimation : AnimationClip; 105 | public var jumpPoseAnimation : AnimationClip; 106 | */ 107 | if(!idleAnimation) { 108 | _animation = null; 109 | Debug.Log("No idle animation found. Turning off animations."); 110 | } 111 | if(!walkAnimation) { 112 | _animation = null; 113 | Debug.Log("No walk animation found. Turning off animations."); 114 | } 115 | if(!runAnimation) { 116 | _animation = null; 117 | Debug.Log("No run animation found. Turning off animations."); 118 | } 119 | if(!jumpPoseAnimation && canJump) { 120 | _animation = null; 121 | Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations."); 122 | } 123 | 124 | } 125 | 126 | 127 | function UpdateSmoothedMovementDirection () 128 | { 129 | var cameraTransform = Camera.main.transform; 130 | var grounded = IsGrounded(); 131 | 132 | // Forward vector relative to the camera along the x-z plane 133 | var forward = cameraTransform.TransformDirection(Vector3.forward); 134 | forward.y = 0; 135 | forward = forward.normalized; 136 | 137 | // Right vector relative to the camera 138 | // Always orthogonal to the forward vector 139 | var right = Vector3(forward.z, 0, -forward.x); 140 | 141 | var v = Input.GetAxisRaw("Vertical"); 142 | var h = Input.GetAxisRaw("Horizontal"); 143 | 144 | // Are we moving backwards or looking backwards 145 | if (v < -0.2) 146 | movingBack = true; 147 | else 148 | movingBack = false; 149 | 150 | var wasMoving = isMoving; 151 | isMoving = Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1; 152 | 153 | // Target direction relative to the camera 154 | var targetDirection = h * right + v * forward; 155 | 156 | // Grounded controls 157 | if (grounded) 158 | { 159 | // Lock camera for short period when transitioning moving & standing still 160 | lockCameraTimer += Time.deltaTime; 161 | if (isMoving != wasMoving) 162 | lockCameraTimer = 0.0; 163 | 164 | // We store speed and direction seperately, 165 | // so that when the character stands still we still have a valid forward direction 166 | // moveDirection is always normalized, and we only update it if there is user input. 167 | if (targetDirection != Vector3.zero) 168 | { 169 | // If we are really slow, just snap to the target direction 170 | if (moveSpeed < walkSpeed * 0.9 && grounded) 171 | { 172 | moveDirection = targetDirection.normalized; 173 | } 174 | // Otherwise smoothly turn towards it 175 | else 176 | { 177 | moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000); 178 | 179 | moveDirection = moveDirection.normalized; 180 | } 181 | } 182 | 183 | // Smooth the speed based on the current target direction 184 | var curSmooth = speedSmoothing * Time.deltaTime; 185 | 186 | // Choose target speed 187 | //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways 188 | var targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0); 189 | 190 | _characterState = CharacterState.Idle; 191 | 192 | // Pick speed modifier 193 | if (Input.GetKey (KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift)) 194 | { 195 | targetSpeed *= runSpeed; 196 | _characterState = CharacterState.Running; 197 | } 198 | else if (Time.time - trotAfterSeconds > walkTimeStart) 199 | { 200 | targetSpeed *= trotSpeed; 201 | _characterState = CharacterState.Trotting; 202 | } 203 | else 204 | { 205 | targetSpeed *= walkSpeed; 206 | _characterState = CharacterState.Walking; 207 | } 208 | 209 | moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth); 210 | 211 | // Reset walk time start when we slow down 212 | if (moveSpeed < walkSpeed * 0.3) 213 | walkTimeStart = Time.time; 214 | } 215 | // In air controls 216 | else 217 | { 218 | // Lock camera while in air 219 | if (jumping) 220 | lockCameraTimer = 0.0; 221 | 222 | if (isMoving) 223 | inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration; 224 | } 225 | 226 | 227 | 228 | } 229 | 230 | 231 | function ApplyJumping () 232 | { 233 | // Prevent jumping too fast after each other 234 | if (lastJumpTime + jumpRepeatTime > Time.time) 235 | return; 236 | 237 | if (IsGrounded()) { 238 | // Jump 239 | // - Only when pressing the button down 240 | // - With a timeout so you can press the button slightly before landing 241 | if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) { 242 | verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight); 243 | SendMessage("DidJump", SendMessageOptions.DontRequireReceiver); 244 | } 245 | } 246 | } 247 | 248 | 249 | function ApplyGravity () 250 | { 251 | if (isControllable) // don't move player at all if not controllable. 252 | { 253 | // Apply gravity 254 | var jumpButton = Input.GetButton("Jump"); 255 | 256 | 257 | // When we reach the apex of the jump we send out a message 258 | if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0) 259 | { 260 | jumpingReachedApex = true; 261 | SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver); 262 | } 263 | 264 | if (IsGrounded ()) 265 | verticalSpeed = 0.0; 266 | else 267 | verticalSpeed -= gravity * Time.deltaTime; 268 | } 269 | } 270 | 271 | function CalculateJumpVerticalSpeed (targetJumpHeight : float) 272 | { 273 | // From the jump height and gravity we deduce the upwards speed 274 | // for the character to reach at the apex. 275 | return Mathf.Sqrt(2 * targetJumpHeight * gravity); 276 | } 277 | 278 | function DidJump () 279 | { 280 | jumping = true; 281 | jumpingReachedApex = false; 282 | lastJumpTime = Time.time; 283 | lastJumpStartHeight = transform.position.y; 284 | lastJumpButtonTime = -10; 285 | 286 | _characterState = CharacterState.Jumping; 287 | } 288 | 289 | function Update() { 290 | 291 | if (!isControllable) 292 | { 293 | // kill all inputs if not controllable. 294 | Input.ResetInputAxes(); 295 | } 296 | 297 | if (Input.GetButtonDown ("Jump")) 298 | { 299 | lastJumpButtonTime = Time.time; 300 | } 301 | 302 | UpdateSmoothedMovementDirection(); 303 | 304 | // Apply gravity 305 | // - extra power jump modifies gravity 306 | // - controlledDescent mode modifies gravity 307 | ApplyGravity (); 308 | 309 | // Apply jumping logic 310 | ApplyJumping (); 311 | 312 | // Calculate actual motion 313 | var movement = moveDirection * moveSpeed + Vector3 (0, verticalSpeed, 0) + inAirVelocity; 314 | movement *= Time.deltaTime; 315 | 316 | // Move the controller 317 | var controller : CharacterController = GetComponent(CharacterController); 318 | collisionFlags = controller.Move(movement); 319 | 320 | // ANIMATION sector 321 | if(_animation) { 322 | if(_characterState == CharacterState.Jumping) 323 | { 324 | if(!jumpingReachedApex) { 325 | _animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed; 326 | _animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever; 327 | _animation.CrossFade(jumpPoseAnimation.name); 328 | } else { 329 | _animation[jumpPoseAnimation.name].speed = -landAnimationSpeed; 330 | _animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever; 331 | _animation.CrossFade(jumpPoseAnimation.name); 332 | } 333 | } 334 | else 335 | { 336 | if(controller.velocity.sqrMagnitude < 0.1) { 337 | _animation.CrossFade(idleAnimation.name); 338 | } 339 | else 340 | { 341 | if(_characterState == CharacterState.Running) { 342 | _animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, runMaxAnimationSpeed); 343 | _animation.CrossFade(runAnimation.name); 344 | } 345 | else if(_characterState == CharacterState.Trotting) { 346 | _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, trotMaxAnimationSpeed); 347 | _animation.CrossFade(walkAnimation.name); 348 | } 349 | else if(_characterState == CharacterState.Walking) { 350 | _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, walkMaxAnimationSpeed); 351 | _animation.CrossFade(walkAnimation.name); 352 | } 353 | 354 | } 355 | } 356 | } 357 | // ANIMATION sector 358 | 359 | // Set rotation to the move direction 360 | if (IsGrounded()) 361 | { 362 | 363 | transform.rotation = Quaternion.LookRotation(moveDirection); 364 | 365 | } 366 | else 367 | { 368 | var xzMove = movement; 369 | xzMove.y = 0; 370 | if (xzMove.sqrMagnitude > 0.001) 371 | { 372 | transform.rotation = Quaternion.LookRotation(xzMove); 373 | } 374 | } 375 | 376 | // We are in jump mode but just became grounded 377 | if (IsGrounded()) 378 | { 379 | lastGroundedTime = Time.time; 380 | inAirVelocity = Vector3.zero; 381 | if (jumping) 382 | { 383 | jumping = false; 384 | SendMessage("DidLand", SendMessageOptions.DontRequireReceiver); 385 | } 386 | } 387 | } 388 | 389 | function OnControllerColliderHit (hit : ControllerColliderHit ) 390 | { 391 | // Debug.DrawRay(hit.point, hit.normal); 392 | if (hit.moveDirection.y > 0.01) 393 | return; 394 | } 395 | 396 | function GetSpeed () { 397 | return moveSpeed; 398 | } 399 | 400 | function IsJumping () { 401 | return jumping; 402 | } 403 | 404 | function IsGrounded () { 405 | return (collisionFlags & CollisionFlags.CollidedBelow) != 0; 406 | } 407 | 408 | function GetDirection () { 409 | return moveDirection; 410 | } 411 | 412 | function IsMovingBackwards () { 413 | return movingBack; 414 | } 415 | 416 | function GetLockCameraTimer () 417 | { 418 | return lockCameraTimer; 419 | } 420 | 421 | function IsMoving () : boolean 422 | { 423 | return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5; 424 | } 425 | 426 | function HasJumpReachedApex () 427 | { 428 | return jumpingReachedApex; 429 | } 430 | 431 | function IsGroundedWithTimeout () 432 | { 433 | return lastGroundedTime + groundedTimeout > Time.time; 434 | } 435 | 436 | function Reset () 437 | { 438 | gameObject.tag = "Player"; 439 | } 440 | 441 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Character Controllers/Sources/Scripts/ThirdPersonController.js.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d5ac211a643e447ca78c2d794a16381 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/StreamingAssets.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7b334c0ce61b4a1e86c3578e5bbaab4 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/StreamingAssets/diff.rtttl: -------------------------------------------------------------------------------- 1 | 占位文件 -------------------------------------------------------------------------------- /Assets/StreamingAssets/diff.rtttl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 95895ab8633f34cbab2f1ecabd540a24 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Test.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 881edbad5bca045f6808956b043c71fe 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Test/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b5a2b499130d4073b5d9dc2c3d008f3 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Test/Editor/OneBuilderEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Text; 7 | 8 | namespace dpull 9 | { 10 | class OneBuilderEditor : EditorWindow 11 | { 12 | string OutputDir = Path.Combine(Application.dataPath, "../Bin"); 13 | string DebugInfo; 14 | 15 | [MenuItem("XStudio/Tools/One Builder")] 16 | public static void UIAdapter() 17 | { 18 | EditorWindow.GetWindow(false, "One Builder", true).Show(); 19 | } 20 | 21 | string BuildPlayer(BuildTarget target, BuildOptions options, params string[] levels) 22 | { 23 | var output = Path.Combine(OutputDir, target.ToString()); 24 | DirectoryEx.DeleteDirectory(output); 25 | 26 | BuildPipeline.BuildPlayer(levels, output, target, options); 27 | return output; 28 | } 29 | 30 | string BuildStreamedSceneAssetBundle(BuildTarget target, params string[] levels) 31 | { 32 | var output = Path.Combine(OutputDir, target.ToString() + ".asset"); 33 | BuildPipeline.BuildStreamedSceneAssetBundle(levels, output, target, BuildOptions.UncompressedAssetBundle); 34 | return output; 35 | } 36 | 37 | long GetFileSize(string path) 38 | { 39 | var info = new FileInfo(path); 40 | return info.Length; 41 | } 42 | 43 | string GetFileSizeString(string path) 44 | { 45 | var units = new string[]{"B", "KB", "MB", "GB"}; 46 | var size = (double)GetFileSize(path); 47 | foreach (var unit in units) 48 | { 49 | if (size < 1024d) 50 | return string.Format("{0:F}{1}", size, unit); 51 | size /= 1024; 52 | } 53 | return string.Format("{0:F}{1}", size, units[units.Length - 1]); 54 | } 55 | 56 | BuildTarget GetIOSBuildTarget() 57 | { 58 | #if UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 59 | return BuildTarget.iPhone; 60 | #else 61 | return BuildTarget.iOS; 62 | #endif 63 | } 64 | 65 | void BuildiOS() 66 | { 67 | var oldTarget = EditorUserBuildSettings.activeBuildTarget; 68 | DirectoryEx.CreateDirectory(OutputDir); 69 | 70 | var app = BuildPlayer(GetIOSBuildTarget(), BuildOptions.None, "Assets/Level1.unity"); 71 | 72 | var appDataDir = Path.Combine(app, "Data"); 73 | var assetbundle = BuildStreamedSceneAssetBundle(GetIOSBuildTarget(), "Assets/Level2.unity"); 74 | 75 | if (!AssetBundlePatch.IsSupport(assetbundle)) 76 | { 77 | Debug.LogError("AssetBundlePatch.IsSupport failed!!!!"); 78 | return; 79 | } 80 | 81 | EditorUserBuildSettings.SwitchActiveBuildTarget(oldTarget); 82 | 83 | var diff = Path.Combine(OutputDir, Updater.Diff); 84 | var ret = AssetBundlePatch.Diff(appDataDir, null, assetbundle, diff); 85 | if (ret != AssetBundlePatchResult.Succeed) 86 | { 87 | Debug.LogError("AssetBundlePatch.Diff failed!!!!"); 88 | return; 89 | } 90 | 91 | // Real environment, you need to place this file on http server 92 | var diffZip = Path.Combine(appDataDir, "Raw"); 93 | diffZip = Path.Combine(diffZip, Updater.DiffZip); 94 | 95 | ZipFile.CreateFromDirectory(new string[]{diff}, diffZip); 96 | 97 | var sb = new StringBuilder(); 98 | sb.AppendLine(DateTime.Now.ToString()); 99 | sb.AppendLine(string.Format("Assetbundle size:{0}", GetFileSizeString(assetbundle))); 100 | sb.AppendLine(string.Format("Diff size:{0}", GetFileSizeString(diff))); 101 | sb.AppendLine(string.Format("Diff zip size:{0}", GetFileSizeString(diffZip))); 102 | DebugInfo = sb.ToString(); 103 | } 104 | 105 | void BuildAndroid() 106 | { 107 | var oldTarget = EditorUserBuildSettings.activeBuildTarget; 108 | DirectoryEx.CreateDirectory(OutputDir); 109 | 110 | var app = BuildPlayer(BuildTarget.Android, BuildOptions.AcceptExternalModificationsToPlayer, "Assets/Level1.unity"); 111 | var appDataDir = Path.Combine(app, "OneBuilder/assets/bin/Data"); 112 | var assetbundle = BuildStreamedSceneAssetBundle(BuildTarget.Android, "Assets/Level2.unity"); 113 | 114 | if (!AssetBundlePatch.IsSupport(assetbundle)) 115 | { 116 | Debug.LogError("AssetBundlePatch.IsSupport failed!!!!"); 117 | return; 118 | } 119 | 120 | EditorUserBuildSettings.SwitchActiveBuildTarget(oldTarget); 121 | 122 | var diff = Path.Combine(OutputDir, Updater.Diff); 123 | var ret = AssetBundlePatch.Diff(appDataDir, null, assetbundle, diff); 124 | if (ret != AssetBundlePatchResult.Succeed) 125 | { 126 | Debug.LogError("AssetBundlePatch.Diff failed!!!!"); 127 | return; 128 | } 129 | 130 | // Real environment, you need to place this file on http server 131 | var diffZip = Path.Combine(app, "OneBuilder/assets"); 132 | diffZip = Path.Combine(diffZip, Updater.DiffZip); 133 | 134 | ZipFile.CreateFromDirectory(new string[]{diff}, diffZip); 135 | 136 | var sb = new StringBuilder(); 137 | sb.AppendLine(DateTime.Now.ToString()); 138 | sb.AppendLine(string.Format("Assetbundle size:{0}", GetFileSizeString(assetbundle))); 139 | sb.AppendLine(string.Format("Diff size:{0}", GetFileSizeString(diff))); 140 | sb.AppendLine(string.Format("Diff zip size:{0}", GetFileSizeString(diffZip))); 141 | DebugInfo = sb.ToString(); 142 | } 143 | 144 | void OnGUI() 145 | { 146 | if (!string.IsNullOrEmpty(DebugInfo)) 147 | GUILayout.TextArea(DebugInfo); 148 | 149 | GUILayout.Space(10); 150 | 151 | if (GUILayout.Button("Test iPhone")) 152 | BuildiOS(); 153 | 154 | if (GUILayout.Button("Test Android")) 155 | BuildAndroid(); 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /Assets/Test/Editor/OneBuilderEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1a56eee7356ec4719bf4fa3e45a1592a 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Test/Progress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using ICSharpCode.SharpZipLib.Zip; 4 | using UnityEngine; 5 | using System.Net; 6 | 7 | namespace dpull 8 | { 9 | abstract class Progress 10 | { 11 | public enum State 12 | { 13 | Uncompleted, 14 | Succeed, 15 | Failed, 16 | } 17 | 18 | public State CurState = State.Uncompleted; 19 | public long ProgressCurValue = 0; 20 | public long ProgressTotalValue = 1; 21 | 22 | public virtual void Update() 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | 27 | public virtual string GetDebug() 28 | { 29 | return string.Empty; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Assets/Test/Progress.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80af05e65a0804ab793cc860b57993e0 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Test/UnzipProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using ICSharpCode.SharpZipLib.Zip; 4 | using UnityEngine; 5 | using System.Net; 6 | 7 | namespace dpull 8 | { 9 | class UnzipProgress : Progress 10 | { 11 | Stream SourceArchiveFile; 12 | ZipInputStream ZipStream; 13 | string DestinationDirectoryName; 14 | byte[] Buffer = new byte[ZipFile.BufferSize]; 15 | Stream WriteFileStream; 16 | 17 | System.Diagnostics.Stopwatch ReaderCost = new System.Diagnostics.Stopwatch(); 18 | System.Diagnostics.Stopwatch WriterCost = new System.Diagnostics.Stopwatch(); 19 | 20 | public UnzipProgress(string sourceArchiveFileName, string destinationDirectoryName) 21 | { 22 | SourceArchiveFile = FileEx.OpenRead(sourceArchiveFileName); 23 | ZipStream = new ZipInputStream(SourceArchiveFile); 24 | DestinationDirectoryName = destinationDirectoryName; 25 | } 26 | 27 | public override void Update() 28 | { 29 | for (int i = 0; i < 8; ++i) 30 | { 31 | if (Process()) 32 | break; 33 | } 34 | } 35 | 36 | public override string GetDebug() 37 | { 38 | return string.Format("Unzip:{0}, Write:{1}", ReaderCost.ElapsedMilliseconds, WriterCost.ElapsedMilliseconds); 39 | } 40 | 41 | bool Process() 42 | { 43 | try 44 | { 45 | if (WriteFileStream == null) 46 | { 47 | ProcessNextEntry(); 48 | if (CurState != State.Uncompleted) 49 | return true; 50 | } 51 | 52 | ProcessFile(); 53 | return false; 54 | } 55 | catch(Exception e) 56 | { 57 | CurState = State.Failed; 58 | Debug.LogException(e); 59 | return true; 60 | } 61 | } 62 | 63 | void ProcessNextEntry() 64 | { 65 | while (true) 66 | { 67 | var theEntry = ZipStream.GetNextEntry(); 68 | if (theEntry == null) 69 | { 70 | CurState = State.Succeed; 71 | return; 72 | } 73 | 74 | var fileName = Path.GetFileName(theEntry.Name); 75 | if (string.IsNullOrEmpty(fileName)) 76 | continue; 77 | 78 | string file = Path.Combine(DestinationDirectoryName, theEntry.Name); 79 | DirectoryEx.CreateDirectory(Directory.GetParent(file)); 80 | 81 | WriteFileStream = File.OpenWrite(file); 82 | return; 83 | } 84 | } 85 | 86 | void ProcessFile() 87 | { 88 | ReaderCost.Start(); 89 | var size = ZipStream.Read(Buffer, 0, Buffer.Length); 90 | ReaderCost.Stop(); 91 | 92 | if (size <= 0) 93 | { 94 | WriteFileStream.Close(); 95 | WriteFileStream = null; 96 | return; 97 | } 98 | 99 | ProgressCurValue = SourceArchiveFile.Position; 100 | ProgressTotalValue = SourceArchiveFile.Length; 101 | 102 | WriterCost.Start(); 103 | WriteFileStream.Write(Buffer, 0, size); 104 | WriterCost.Stop(); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /Assets/Test/UnzipProgress.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 92c479a8d744c4573a855271fd4f0e47 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Test/Updater.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System; 6 | 7 | namespace dpull 8 | { 9 | public class Updater : MonoBehaviour 10 | { 11 | public const string Diff = "diff.asset"; 12 | public const string DiffZip = "diff.rtttl"; // for Android http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/ 13 | private string DebugMessage = string.Empty; 14 | private string ProgressMessage = string.Empty; 15 | private Progress CurProgress = null; 16 | private Rect WindowRect = new Rect(Screen.width / 4, Screen.height / 4, Screen.width / 2, Screen.height / 2); 17 | private bool UpdateSucess; 18 | 19 | string GetAppDataDir() 20 | { 21 | switch (Application.platform) 22 | { 23 | case RuntimePlatform.IPhonePlayer: 24 | return Directory.GetParent(Application.streamingAssetsPath).FullName; 25 | 26 | case RuntimePlatform.Android: 27 | return Path.Combine(Application.streamingAssetsPath, "bin/Data"); 28 | 29 | default: 30 | throw new UnityException("Not support:" + Application.platform.ToString()); 31 | } 32 | } 33 | 34 | IEnumerator Start() 35 | { 36 | if (Application.platform != RuntimePlatform.Android && Application.platform != RuntimePlatform.IPhonePlayer) 37 | yield break; 38 | 39 | UpdateSucess = false; 40 | 41 | // Real environment, you need to download this file 42 | var diffZip = Path.Combine(Application.streamingAssetsPath, DiffZip); 43 | Debug.Log("DiffZip:" + diffZip); 44 | 45 | CurProgress = new UnzipProgress(diffZip, Application.persistentDataPath); 46 | yield return StartCoroutine(ProcessProgress(CurProgress)); 47 | 48 | if (CurProgress.CurState != Progress.State.Succeed) 49 | { 50 | DebugMessage = "Unzip failed." + CurProgress.GetDebug(); 51 | yield break; 52 | } 53 | 54 | var diff = Path.Combine(Application.persistentDataPath, Diff); 55 | Debug.Log("Diff:" + diff); 56 | 57 | var appDataDir = GetAppDataDir(); 58 | Debug.Log("AppDataDir:" + appDataDir); 59 | 60 | var update = Path.Combine(Application.persistentDataPath, "update.asset"); 61 | var ret = AssetBundlePatch.Merge(appDataDir, null, update, diff); 62 | if (ret != AssetBundlePatchResult.Succeed) 63 | { 64 | DebugMessage = "Merge failed."; 65 | yield break; 66 | } 67 | 68 | AssetBundle.CreateFromFile(update); 69 | UpdateSucess = true; 70 | } 71 | 72 | void OnGUI() 73 | { 74 | if (UpdateSucess) 75 | { 76 | if (GUILayout.Button("Enter Level 2")) 77 | { 78 | Application.LoadLevel("Level2"); 79 | } 80 | return; 81 | } 82 | 83 | WindowRect = GUILayout.Window(0, WindowRect, (windowId)=>{ 84 | GUILayout.Label(ProgressMessage); 85 | 86 | if (CurProgress != null) 87 | { 88 | var progress = 100 * CurProgress.ProgressCurValue / CurProgress.ProgressTotalValue; 89 | GUILayout.HorizontalScrollbar((float)progress, 0f, 0f, 100f); 90 | GUILayout.Label(progress.ToString() + "%"); 91 | GUILayout.Label(CurProgress.CurState.ToString()); 92 | } 93 | GUILayout.Label(DebugMessage); 94 | }, "Updater"); 95 | } 96 | 97 | IEnumerator ProcessProgress(Progress curProgress) 98 | { 99 | while (true) 100 | { 101 | curProgress.Update(); 102 | if (curProgress.CurState != Progress.State.Uncompleted) 103 | yield break; 104 | yield return null; 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Assets/Test/Updater.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c0ef8eebd93774d88a6436a5d212fd92 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Test/ZipFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using ICSharpCode.SharpZipLib.Zip; // https://github.com/icsharpcode/SharpZipLib 4 | using System.Collections; 5 | using UnityEngine; 6 | 7 | namespace dpull 8 | { 9 | public class ZipFile 10 | { 11 | public static int BufferSize = 1024 * 1024; 12 | 13 | public static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName) 14 | { 15 | string[] filenames = Directory.GetFiles(sourceDirectoryName); 16 | var inDirStrLen = sourceDirectoryName.Length; 17 | 18 | if (!PathEx.EndWithDirectorySeparatorChar(sourceDirectoryName)) 19 | inDirStrLen++; 20 | 21 | using (ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationArchiveFileName))) 22 | { 23 | byte[] buffer = new byte[BufferSize]; 24 | 25 | zipStream.SetLevel(9); 26 | 27 | foreach (string file in filenames) 28 | { 29 | var entryName = file.Substring(inDirStrLen); 30 | var fileInfo = new FileInfo(file); 31 | 32 | ZipEntry entry = new ZipEntry(entryName); 33 | entry.DateTime = fileInfo.LastWriteTime; 34 | zipStream.PutNextEntry(entry); 35 | 36 | using (FileStream fileStream = File.OpenRead(file)) 37 | { 38 | while (true) 39 | { 40 | int size = fileStream.Read(buffer, 0, buffer.Length); 41 | if (size <= 0) 42 | break; 43 | 44 | zipStream.Write(buffer, 0, size); 45 | } 46 | } 47 | } 48 | 49 | zipStream.Finish(); 50 | zipStream.Close(); 51 | } 52 | } 53 | 54 | public static void CreateFromDirectory(string[] sourceFileNames, string destinationArchiveFileName) 55 | { 56 | using (ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationArchiveFileName))) 57 | { 58 | byte[] buffer = new byte[BufferSize]; 59 | 60 | zipStream.SetLevel(9); 61 | 62 | foreach (string file in sourceFileNames) 63 | { 64 | var entryName = Path.GetFileName(file); 65 | var fileInfo = new FileInfo(file); 66 | 67 | ZipEntry entry = new ZipEntry(entryName); 68 | entry.DateTime = fileInfo.LastWriteTime; 69 | zipStream.PutNextEntry(entry); 70 | 71 | using (FileStream fileStream = File.OpenRead(file)) 72 | { 73 | while (true) 74 | { 75 | int size = fileStream.Read(buffer, 0, buffer.Length); 76 | if (size <= 0) 77 | break; 78 | 79 | zipStream.Write(buffer, 0, size); 80 | } 81 | } 82 | } 83 | 84 | zipStream.Finish(); 85 | zipStream.Close(); 86 | } 87 | } 88 | 89 | public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName) 90 | { 91 | using (var zipStream = new ZipInputStream(FileEx.OpenRead(sourceArchiveFileName))) 92 | { 93 | ZipEntry theEntry; 94 | byte[] data = new byte[BufferSize]; 95 | 96 | while ((theEntry = zipStream.GetNextEntry()) != null) 97 | { 98 | var fileName = Path.GetFileName(theEntry.Name); 99 | if (string.IsNullOrEmpty(fileName)) 100 | continue; 101 | 102 | string file = Path.Combine(destinationDirectoryName, theEntry.Name); 103 | DirectoryEx.CreateDirectory(Directory.GetParent(file)); 104 | 105 | using (FileStream fileStream = File.Create(file)) 106 | { 107 | while (true) 108 | { 109 | var size = zipStream.Read(data, 0, data.Length); 110 | if (size <= 0) 111 | break; 112 | 113 | fileStream.Write(data, 0, size); 114 | } 115 | } 116 | } 117 | } 118 | } 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Assets/Test/ZipFile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 396d11133c39e4381b6a06bc511c932e 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d20f1187c7994084920ffd7627be776 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Thirdparty/SharpZip.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/Assets/Thirdparty/SharpZip.dll -------------------------------------------------------------------------------- /Assets/Thirdparty/SharpZip.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4cd05255fa1854c74ae3997b549dd9f0 3 | MonoAssemblyImporter: 4 | serializedVersion: 1 5 | iconMap: {} 6 | executionOrder: {} 7 | userData: 8 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ffc3b1e438684d16b46da4a0ed8d78c 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/AndroidAssetStream.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | #if UNITY_ANDROID 5 | namespace dpull 6 | { 7 | public class AndroidAssetStream : System.IO.Stream 8 | { 9 | AndroidJavaObject AndroidInputStream; 10 | long AndroidInputStreamLength = long.MaxValue; 11 | long AndroidInputStreamPostion = 0; 12 | 13 | public AndroidAssetStream(string fileName) 14 | { 15 | var noCompressExt = new string[]{ 16 | ".jpg", ".jpeg", ".png", ".gif", 17 | ".wav", ".mp2", ".mp3", ".ogg", ".aac", 18 | ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", 19 | ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", 20 | ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", 21 | ".amr", ".awb", ".wma", ".wmv" 22 | }; 23 | 24 | var ext = System.IO.Path.GetExtension(fileName); 25 | 26 | using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) 27 | { 28 | using (var activity = unityPlayer.GetStatic("currentActivity")) 29 | { 30 | using (var assetManager = activity.Call("getAssets")) //android.content.res.AssetManager 31 | { 32 | if (Array.Exists(noCompressExt, (obj)=>{ return obj == ext; })) 33 | { 34 | using (var assetFileDescriptor = assetManager.Call("openFd", fileName)) //assets/ //android.content.res.AssetFileDescriptor 35 | { 36 | AndroidInputStreamLength = assetFileDescriptor.Call("getLength"); 37 | } 38 | } 39 | AndroidInputStream = assetManager.Call("open", fileName); 40 | } 41 | } 42 | } 43 | 44 | if (AndroidInputStream == null) 45 | throw new System.IO.FileNotFoundException("getAssets failed", fileName); 46 | } 47 | 48 | public override void Flush () 49 | { 50 | throw new NotImplementedException(); 51 | } 52 | 53 | public override int Read(byte[] buffer, int offset, int count) 54 | { 55 | var ret = Read(AndroidInputStream, buffer, offset, count); 56 | if (ret > 0) 57 | AndroidInputStreamPostion += ret; 58 | return ret; 59 | } 60 | 61 | public override long Seek(long offset, System.IO.SeekOrigin origin) 62 | { 63 | if (offset - AndroidInputStreamPostion < 0) 64 | throw new NotImplementedException(); 65 | 66 | long skip; 67 | switch (origin) 68 | { 69 | case System.IO.SeekOrigin.Begin: 70 | skip = AndroidInputStream.Call("skip", offset - AndroidInputStreamPostion); 71 | AndroidInputStreamPostion += skip; 72 | break; 73 | 74 | case System.IO.SeekOrigin.Current: 75 | skip = AndroidInputStream.Call("skip", offset); 76 | AndroidInputStreamPostion += skip; 77 | break; 78 | 79 | case System.IO.SeekOrigin.End: 80 | throw new NotImplementedException(); 81 | } 82 | return AndroidInputStreamPostion; 83 | } 84 | 85 | public override void SetLength(long value) 86 | { 87 | throw new NotImplementedException(); 88 | } 89 | 90 | public override void Write(byte[] buffer, int offset, int count) 91 | { 92 | throw new NotImplementedException(); 93 | } 94 | 95 | public override bool CanRead 96 | { 97 | get 98 | { 99 | return AndroidInputStream != null; 100 | } 101 | } 102 | public override bool CanSeek 103 | { 104 | get 105 | { 106 | return false; 107 | } 108 | } 109 | public override bool CanWrite 110 | { 111 | get 112 | { 113 | return false; 114 | } 115 | } 116 | public override long Length 117 | { 118 | get 119 | { 120 | if (AndroidInputStreamLength == long.MaxValue) 121 | throw new NotImplementedException(); 122 | return AndroidInputStreamLength; 123 | } 124 | } 125 | 126 | public override long Position 127 | { 128 | get 129 | { 130 | return AndroidInputStreamPostion; 131 | } 132 | set 133 | { 134 | throw new NotImplementedException(); 135 | } 136 | } 137 | 138 | int Read(AndroidJavaObject javaObject, byte[] buffer, int offset, int count) 139 | { 140 | var args = new object[]{buffer, offset, count}; 141 | IntPtr methodID = AndroidJNIHelper.GetMethodID(javaObject.GetRawClass(), "read", args, false); 142 | jvalue[] array = AndroidJNIHelper.CreateJNIArgArray(args); 143 | try 144 | { 145 | var readLen = AndroidJNI.CallIntMethod(javaObject.GetRawObject(), methodID, array); 146 | if (readLen > 0) 147 | { 148 | var temp = AndroidJNI.FromByteArray(array[0].l); 149 | Array.Copy(temp, offset, buffer, offset, readLen); 150 | } 151 | return readLen; 152 | } 153 | finally 154 | { 155 | AndroidJNIHelper.DeleteJNIArgArray(args, array); 156 | } 157 | } 158 | } 159 | } 160 | #endif -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/AndroidAssetStream.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e682e3f60e0a433e816fa2f9701ca0e 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/DynamicObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.IO; 4 | using System.Runtime.Serialization.Formatters.Binary; 5 | 6 | namespace dpull 7 | { 8 | public static class DynamicObject 9 | { 10 | /// 11 | /// 作用 根据基类 和 子类型的type字符串创建一个子类的实例 12 | /// 要确保要创建的对象类型和 T在一个程序集中 13 | /// 继承于T的类名字 14 | /// 该类的构造函数参数 15 | /// 该类的构造函数参数 16 | /// 成功返回 类实例,失败返回null 17 | /// 18 | public static T Create(string typename, Type[] types, object[] parameters) 19 | { 20 | Assembly assembly = typeof(T).Assembly; 21 | Type type = assembly.GetType(typename); 22 | if (type == null) 23 | return default(T); 24 | 25 | 26 | ConstructorInfo constructor = type.GetConstructor(types); 27 | if (constructor == null) 28 | return default(T); 29 | 30 | T result = (T)constructor.Invoke(parameters); 31 | return result; 32 | } 33 | 34 | public static T Clone(T item) 35 | { 36 | MemoryStream ms = new MemoryStream(); 37 | BinaryFormatter bf = new BinaryFormatter(); 38 | bf.Serialize(ms, item); 39 | ms.Seek(0, SeekOrigin.Begin); 40 | 41 | return (T)bf.Deserialize(ms); 42 | } 43 | 44 | /// 45 | /// 这个限制很强的一个模板函数 46 | /// 生成镜像,把原类型中的属性转化为字符串赋值给目标类 47 | /// 目标类中字段或者属性是public,且都是字符串 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | public static void MirrorTo(TSource source, /*ref*/TDestination destination) 54 | { 55 | Type sourceType = typeof(TSource); 56 | Type destinationType = typeof(TDestination); 57 | 58 | FieldInfo[] fields = destinationType.GetFields(); 59 | foreach (FieldInfo field in fields) 60 | { 61 | string destinationValue = GetObjectValue(source, sourceType, field.Name).ToString(); 62 | field.SetValue(destination, destinationValue); 63 | } 64 | 65 | PropertyInfo[] propertys = destinationType.GetProperties(); 66 | foreach (PropertyInfo property in propertys) 67 | { 68 | if (!property.CanWrite) 69 | continue; 70 | 71 | string destinationValue = GetObjectValue(source, sourceType, property.Name).ToString(); 72 | property.SetValue(destination, destinationValue, null); 73 | } 74 | } 75 | 76 | static object GetObjectValue(object obj, Type objType, string name) 77 | { 78 | object result = null; 79 | PropertyInfo property = objType.GetProperty(name); 80 | if (property != null) 81 | { 82 | result = property.GetValue(obj, null); 83 | } 84 | else 85 | { 86 | FieldInfo field = objType.GetField(name); 87 | if (field == null) 88 | throw new ArgumentException(string.Format("{0}不存在类型{1}", objType.Name, name)); 89 | 90 | result = field.GetValue(obj); 91 | } 92 | return result; 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/DynamicObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2fdd2715912d6433f931003bdcbfc109 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 050f3c0492bf14fd3adc8ae26ff35a3f 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/AssetDatabase.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | namespace dpull 6 | { 7 | [ExecuteInEditMode] 8 | public static class AssetDatabaseEx 9 | { 10 | static string[] GetBeDependencies(string path) 11 | { 12 | var ret = new System.Collections.Generic.List(); 13 | var assets = AssetDatabase.GetAllAssetPaths(); 14 | foreach (var asset in assets) 15 | { 16 | var dependencies = AssetDatabase.GetDependencies(new string[]{asset}); 17 | if (ArrayUtility.Contains(dependencies, path)) 18 | ret.Add(asset); 19 | } 20 | return ret.ToArray(); 21 | } 22 | 23 | [MenuItem("XStudio/Tools/Search Assets")] 24 | public static void Process() 25 | { 26 | var files = GetBeDependencies("Assets/Component/ClientUIEvent.cs"); 27 | foreach (var file in files) 28 | Debug.Log(file); 29 | } 30 | 31 | static bool HasDependencies(string asset, string srcCodeFile) 32 | { 33 | var dependencies = AssetDatabase.GetDependencies(new string[]{asset}); 34 | foreach (var dependencie in dependencies) 35 | { 36 | if (!dependencie.Contains(srcCodeFile)) 37 | continue; 38 | return true; 39 | } 40 | return false; 41 | } 42 | 43 | static void Replace(string srcCodeFile) where T : Component 44 | { 45 | var assets = AssetDatabase.GetAllAssetPaths(); 46 | foreach (var asset in assets) 47 | { 48 | if (!asset.StartsWith("Assets")) 49 | continue; 50 | 51 | var assetObj = AssetDatabase.LoadMainAssetAtPath(asset); 52 | if (assetObj == null) 53 | continue; 54 | 55 | if (PrefabUtility.GetPrefabType(assetObj) != PrefabType.Prefab) 56 | continue; 57 | 58 | if (!string.IsNullOrEmpty(srcCodeFile)) 59 | { 60 | if (HasDependencies(asset, srcCodeFile)) 61 | continue; 62 | } 63 | 64 | var go = GameObject.Instantiate(assetObj) as GameObject; 65 | if (go == null) 66 | continue; 67 | 68 | go.name = assetObj.name; 69 | var isChange = false; 70 | 71 | var children = go.GetComponentsInChildren(); 72 | foreach (var child in children) 73 | { 74 | var serializedObject = new SerializedObject(child); 75 | var sp = serializedObject.FindProperty("prefabFile"); 76 | var target = sp.objectReferenceValue; 77 | if (target != null) 78 | { 79 | var path = AssetDatabase.GetAssetPath(target); 80 | var spPath = serializedObject.FindProperty("prefabPath"); 81 | if (path.StartsWith("Assets/Resources/")) 82 | { 83 | spPath.stringValue = path.Substring("Assets/Resources/".Length); 84 | sp.objectReferenceValue = null; 85 | serializedObject.ApplyModifiedProperties(); 86 | isChange = true; 87 | } 88 | else 89 | { 90 | Debug.Log(string.Format("asset:{0}.{1}, path{2}", asset, child.name, path)); 91 | } 92 | } 93 | } 94 | 95 | if (isChange) 96 | PrefabUtility.ReplacePrefab(go, assetObj); 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/AssetDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 268bed914b12942af9289de35a3889ac 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/CodeFormat.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | namespace dpull 6 | { 7 | [ExecuteInEditMode] 8 | public static class CodeFormat 9 | { 10 | [MenuItem("XStudio/Tools/Code Format")] 11 | public static void Process() 12 | { 13 | // ProcessDirectory("Assets/Component"); 14 | // ProcessDirectory("Assets/Thirdparty/AutoBuild"); 15 | ProcessDirectory("Assets/Thirdparty/UnityUtils"); 16 | ProcessDirectory("Assets/Thirdparty/NGUIParticleSystem"); 17 | ProcessDirectory("Assets/Thirdparty/UnityLua/Expand"); 18 | Debug.Log("Code format finish"); 19 | } 20 | 21 | static void ProcessDirectory(string path) 22 | { 23 | var srcs = System.IO.Directory.GetFiles(path, "*.cs", System.IO.SearchOption.AllDirectories); 24 | var utf8Encoding = new System.Text.UTF8Encoding(true); 25 | 26 | foreach(var src in srcs) 27 | { 28 | var auto = System.IO.File.ReadAllText(src); 29 | auto = auto.Replace("\r\n", "\n"); 30 | auto = auto.Replace("\t", " "); 31 | System.IO.File.WriteAllText(src, auto, utf8Encoding); 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/CodeFormat.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3939ca28bbef46fa9bf4513ab64f372 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace dpull 6 | { 7 | public class CommandArgs 8 | { 9 | public Dictionary ArgPairs 10 | { 11 | get { return mArgPairs; } 12 | } 13 | 14 | public List Params 15 | { 16 | get { return mParams; } 17 | } 18 | 19 | List mParams = new List(); 20 | Dictionary mArgPairs = new Dictionary(); 21 | } 22 | 23 | public class CommandLine 24 | { 25 | public static CommandArgs Parse(string[] args) 26 | { 27 | char[] kEqual = new char[] { '=' }; 28 | char[] kArgStart = new char[] { '-', '\\' }; 29 | CommandArgs ca = new CommandArgs(); 30 | 31 | int ii = -1; 32 | string token = NextToken(args, ref ii); 33 | 34 | while (token != null) 35 | { 36 | if (IsArg(token)) 37 | { 38 | string arg = token.TrimStart(kArgStart).TrimEnd(kEqual); 39 | string value = null; 40 | 41 | if (arg.Contains("=")) 42 | { 43 | string[] r = arg.Split(kEqual, 2); 44 | 45 | if (r.Length == 2 && r[1] != string.Empty) 46 | { 47 | arg = r[0]; 48 | value = r[1]; 49 | } 50 | } 51 | 52 | while (value == null) 53 | { 54 | if (ii > args.Length) 55 | break; 56 | 57 | string next = NextToken(args, ref ii); 58 | if (next != null) 59 | { 60 | if (IsArg(next)) 61 | { 62 | ii--; 63 | value = "true"; 64 | } 65 | else if (next != "=") 66 | { 67 | value = next.TrimStart(kEqual); 68 | } 69 | } 70 | } 71 | ca.ArgPairs.Add(arg, value); 72 | } 73 | else if (token != string.Empty) 74 | { 75 | ca.Params.Add(token); 76 | } 77 | 78 | token = NextToken(args, ref ii); 79 | } 80 | return ca; 81 | } 82 | 83 | static bool IsArg(string arg) 84 | { 85 | return (arg.StartsWith("-") || arg.StartsWith("\\")); 86 | } 87 | 88 | static string NextToken(string[] args, ref int ii) 89 | { 90 | ii++; 91 | while (ii < args.Length) 92 | { 93 | string cur = args[ii].Trim(); 94 | if (cur != string.Empty) 95 | { 96 | return cur; 97 | } 98 | ii++; 99 | } 100 | return null; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/CommandLine.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed673f379a571514dbd253ea7248bc8b 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/EditorGUITools.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | namespace dpull 7 | { 8 | public static class EditorGUITools 9 | { 10 | static public bool DrawHeader (string text) 11 | { 12 | return DrawHeader(text, null, false, false); 13 | } 14 | 15 | static public bool DrawHeader (string text, string key, bool forceOn, bool minimalistic) 16 | { 17 | key = (key == null) ? text : key; 18 | bool state = EditorPrefs.GetBool(key, true); 19 | 20 | if (!minimalistic) GUILayout.Space(3f); 21 | if (!forceOn && !state) GUI.backgroundColor = new Color(0.8f, 0.8f, 0.8f); 22 | GUILayout.BeginHorizontal(); 23 | GUI.changed = false; 24 | 25 | if (minimalistic) 26 | { 27 | if (state) text = "\u25BC" + (char)0x200a + text; 28 | else text = "\u25BA" + (char)0x200a + text; 29 | 30 | GUILayout.BeginHorizontal(); 31 | GUI.contentColor = EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.7f) : new Color(0f, 0f, 0f, 0.7f); 32 | if (!GUILayout.Toggle(true, text, "PreToolbar2", GUILayout.MinWidth(20f))) state = !state; 33 | GUI.contentColor = Color.white; 34 | GUILayout.EndHorizontal(); 35 | } 36 | else 37 | { 38 | text = "" + text + ""; 39 | if (state) text = "\u25BC " + text; 40 | else text = "\u25BA " + text; 41 | if (!GUILayout.Toggle(true, text, "dragtab", GUILayout.MinWidth(20f))) state = !state; 42 | } 43 | 44 | if (GUI.changed) 45 | EditorPrefs.SetBool(key, state); 46 | 47 | if (!minimalistic) 48 | GUILayout.Space(2f); 49 | GUILayout.EndHorizontal(); 50 | GUI.backgroundColor = Color.white; 51 | if (!forceOn && !state) 52 | GUILayout.Space(3f); 53 | return state; 54 | } 55 | 56 | static public void BeginContents () 57 | { 58 | GUILayout.BeginHorizontal(); 59 | EditorGUILayout.BeginHorizontal("AS TextArea", GUILayout.MinHeight(10f)); 60 | GUILayout.BeginVertical(); 61 | GUILayout.Space(2f); 62 | } 63 | 64 | static public void EndContents () 65 | { 66 | GUILayout.Space(3f); 67 | GUILayout.EndVertical(); 68 | EditorGUILayout.EndHorizontal(); 69 | GUILayout.Space(3f); 70 | GUILayout.EndHorizontal(); 71 | GUILayout.Space(3f); 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/EditorGUITools.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0bcaf6b7f80974708a654328b9604b72 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/UIAdapterEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | #if USE_NGUI 6 | 7 | namespace dpull 8 | { 9 | class UIAdapterEditor : EditorWindow 10 | { 11 | [MenuItem("XStudio/Tools/UI Adapter")] 12 | public static void UIAdapter() 13 | { 14 | EditorWindow.GetWindow(false, "UI Adapter", true).Show(); 15 | } 16 | 17 | UIRoot.Scaling Scaling; 18 | int ManualWidth = 1280; 19 | int ManualHeight = 720; 20 | int MinimumHeight = 320; 21 | int MaximumHeight = 1536; 22 | bool FitWidth = false; 23 | bool FitHeight = true; 24 | bool AdjustByDPI = false; 25 | bool ShrinkPortraitUI = false; 26 | 27 | void AddLine(string name, string width, string height, string widthScale, string heightScale, string widthView, string heightView, string desc) 28 | { 29 | EditorGUILayout.BeginHorizontal(); 30 | EditorGUILayout.LabelField(name, GUILayout.Width(100f)); 31 | EditorGUILayout.LabelField(width, GUILayout.Width(60f)); 32 | EditorGUILayout.LabelField(height, GUILayout.Width(60f)); 33 | EditorGUILayout.LabelField(widthScale, GUILayout.Width(60f)); 34 | EditorGUILayout.LabelField(heightScale, GUILayout.Width(60f)); 35 | EditorGUILayout.LabelField(widthView, GUILayout.Width(60f)); 36 | EditorGUILayout.LabelField(heightView, GUILayout.Width(60f)); 37 | EditorGUILayout.LabelField(desc, GUILayout.Width(100)); 38 | EditorGUILayout.EndHorizontal(); 39 | } 40 | 41 | void AddLine(string name, int width, int height) 42 | { 43 | if (Scaling == UIRoot.Scaling.Flexible) 44 | { 45 | int manualWidth = width; 46 | int manualHeight = height; 47 | 48 | int heightScale = activeHeight(new Vector2(width, height)); 49 | int widthScale = Mathf.RoundToInt((float)manualWidth * heightScale / manualHeight); 50 | AddLine(name, width.ToString(), height.ToString(), widthScale.ToString(), heightScale.ToString(), "", "", ((float)height / heightScale).ToString()); 51 | } 52 | else 53 | { 54 | int heightScale = activeHeight(new Vector2(width, height)); 55 | int widthScale = Mathf.RoundToInt((float)ManualWidth * heightScale / ManualHeight); 56 | int widthView = Mathf.RoundToInt((float)width * heightScale / height); 57 | int heightView = heightScale; 58 | 59 | AddLine(name, width.ToString(), height.ToString(), widthScale.ToString(), heightScale.ToString(), widthView.ToString(), heightView.ToString(), ((float)height / heightScale).ToString()); 60 | } 61 | 62 | } 63 | 64 | void OnGUI() 65 | { 66 | Scaling = (UIRoot.Scaling)EditorGUILayout.EnumPopup("Scaling Style", Scaling); 67 | 68 | if (Scaling == UIRoot.Scaling.Flexible) 69 | { 70 | MinimumHeight = EditorGUILayout.IntField("Minimum Height", MinimumHeight); 71 | MaximumHeight = EditorGUILayout.IntField("Maximum Height", MaximumHeight); 72 | ShrinkPortraitUI = EditorGUILayout.Toggle("Shrink Portrait UI", ShrinkPortraitUI); 73 | AdjustByDPI = EditorGUILayout.Toggle("Adjust by DPI", AdjustByDPI); 74 | 75 | EditorGUILayout.LabelField("结果按手机实际显示,非编辑器预览显示"); 76 | } 77 | else 78 | { 79 | GUILayout.BeginHorizontal(); 80 | ManualWidth = EditorGUILayout.IntField("Content Width", ManualWidth, GUILayout.Width(260f)); 81 | FitWidth = EditorGUILayout.Toggle("Fit", FitWidth); 82 | GUILayout.EndHorizontal(); 83 | 84 | GUILayout.BeginHorizontal(); 85 | ManualHeight = EditorGUILayout.IntField("Content Height", ManualHeight, GUILayout.Width(260f)); 86 | FitHeight = EditorGUILayout.Toggle("Fit", FitHeight); 87 | GUILayout.EndHorizontal(); 88 | } 89 | 90 | EditorGUILayout.Space(); 91 | EditorGUILayout.Space(); 92 | EditorGUILayout.Space(); 93 | EditorGUILayout.BeginVertical(); 94 | AddLine("手机", "像素长", "像素宽", "UI缩放长", "UI缩放宽", "UI可视长", "UI可视宽", "缩放"); 95 | AddLine("iPhone4", 960, 640); 96 | AddLine("iPhone5", 1136, 640); 97 | AddLine("iPhone6", 1334, 750); 98 | AddLine("iPhone6 plus", 1920, 1080); 99 | AddLine("iPad mini", 1024, 768); 100 | AddLine("iPad air", 2048, 1536); 101 | 102 | AddLine("Android1", 1280, 720); 103 | AddLine("Android2", 1920, 1080); 104 | 105 | EditorGUILayout.EndVertical(); 106 | } 107 | 108 | UIRoot.Constraint constraint 109 | { 110 | get 111 | { 112 | if (FitWidth) 113 | { 114 | if (FitHeight) 115 | return UIRoot.Constraint.Fit; 116 | return UIRoot.Constraint.FitWidth; 117 | } 118 | else if (FitHeight) 119 | return UIRoot.Constraint.FitHeight; 120 | return UIRoot.Constraint.Fill; 121 | } 122 | } 123 | 124 | int activeHeight(Vector2 screen) 125 | { 126 | if (Scaling == UIRoot.Scaling.Flexible) 127 | { 128 | float aspect = screen.x / screen.y; 129 | 130 | if (screen.y < MinimumHeight) 131 | { 132 | screen.y = MinimumHeight; 133 | screen.x = screen.y * aspect; 134 | } 135 | else if (screen.y > MaximumHeight) 136 | { 137 | screen.y = MaximumHeight; 138 | screen.x = screen.y * aspect; 139 | } 140 | 141 | // Portrait mode uses the maximum of width or height to shrink the UI 142 | int height = Mathf.RoundToInt((ShrinkPortraitUI && screen.y > screen.x) ? screen.y / aspect : screen.y); 143 | 144 | // Adjust the final value by the DPI setting 145 | return AdjustByDPI ? NGUIMath.AdjustByDPI(height) : height; 146 | } 147 | else 148 | { 149 | var cons = constraint; 150 | if (cons == UIRoot.Constraint.FitHeight) 151 | return ManualHeight; 152 | 153 | float aspect = screen.x / screen.y; 154 | float initialAspect = (float)ManualWidth / ManualHeight; 155 | 156 | switch (cons) 157 | { 158 | case UIRoot.Constraint.FitWidth: 159 | { 160 | return Mathf.RoundToInt(ManualWidth / aspect); 161 | } 162 | 163 | case UIRoot.Constraint.Fit: 164 | { 165 | return (initialAspect > aspect) ? Mathf.RoundToInt(ManualWidth / aspect) : ManualHeight; 166 | } 167 | case UIRoot.Constraint.Fill: 168 | { 169 | return (initialAspect < aspect) ? Mathf.RoundToInt(ManualWidth / aspect) : ManualHeight; 170 | } 171 | } 172 | return ManualHeight; 173 | } 174 | } 175 | } 176 | } 177 | #endif 178 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Editor/UIAdapterEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f172c1c2d038242f6b1728b9351165f2 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/EventHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace dpull 6 | { 7 | public static class EventHelper 8 | { 9 | //警告 8 CA1030 10 | public static void Raise(EventHandler hander, object sender, TEventArgs args) 11 | where TEventArgs : EventArgs 12 | { 13 | //.net设计规范 P128 14 | EventHandler eventHander = hander; 15 | if (eventHander != null) 16 | { 17 | eventHander(sender, args); 18 | } 19 | } 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/EventHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f4dd23d51297444e294d741e5ec1f0d5 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/IO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using UnityEngine; 4 | using System.Collections; 5 | using System.Text; 6 | 7 | namespace dpull 8 | { 9 | public class DirectoryEx 10 | { 11 | public static void CreateDirectory(string path) 12 | { 13 | path = Path.GetFullPath(path); 14 | CreateDirectory(new DirectoryInfo(path)); 15 | } 16 | 17 | public static void CreateDirectory(DirectoryInfo path) 18 | { 19 | if (path.Exists) 20 | return; 21 | 22 | while (true) 23 | { 24 | var parent = path.Parent; 25 | if (parent == null || parent.Exists) 26 | break; 27 | CreateDirectory(parent); 28 | } 29 | 30 | path.Create(); 31 | } 32 | 33 | public static void DeleteDirectory(string path) 34 | { 35 | path = Path.GetFullPath(path); 36 | if (Directory.Exists(path)) 37 | Directory.Delete(path, true); 38 | } 39 | } 40 | 41 | public class FileEx 42 | { 43 | public static Stream OpenRead(string sourceFileName) 44 | { 45 | #if UNITY_ANDROID 46 | if (sourceFileName.StartsWith(Application.streamingAssetsPath)) 47 | { 48 | var startIndex = Application.streamingAssetsPath.Length; 49 | if (!PathEx.EndWithDirectorySeparatorChar(Application.streamingAssetsPath)) 50 | startIndex++; 51 | 52 | sourceFileName = sourceFileName.Substring(startIndex); 53 | return new AndroidAssetStream(sourceFileName); 54 | } 55 | #endif 56 | return File.OpenRead(sourceFileName); 57 | } 58 | 59 | public static bool SetFileLength(string filepath, long length) 60 | { 61 | try 62 | { 63 | using (FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.None)) 64 | { 65 | fs.SetLength(length); 66 | } 67 | } 68 | catch (System.Exception e) 69 | { 70 | Debug.LogException(e); 71 | File.Delete(filepath); 72 | return false; 73 | } 74 | 75 | return true; 76 | } 77 | 78 | public static long GetFileLength(string filepath) 79 | { 80 | FileInfo fileInfo = new FileInfo(filepath); 81 | return fileInfo.Length; 82 | } 83 | } 84 | 85 | public class PathEx 86 | { 87 | public static bool EndWithDirectorySeparatorChar(string path) 88 | { 89 | return path.EndsWith("\\") || path.EndsWith("/"); 90 | } 91 | 92 | /// 93 | /// 绝对路径转相对路径 94 | /// 95 | /// 基本路径 96 | /// 绝对路径 97 | /// strFullPath相对于strBasePath的相对路径 98 | public static string GetRelativePath(string strBasePath, string strFullPath) 99 | { 100 | if (strBasePath == null) 101 | throw new ArgumentNullException("strBasePath"); 102 | 103 | if (strFullPath == null) 104 | throw new ArgumentNullException("strFullPath"); 105 | 106 | strBasePath = Path.GetFullPath(strBasePath); 107 | strFullPath = Path.GetFullPath(strFullPath); 108 | 109 | var DirectoryPos = new int[strBasePath.Length]; 110 | int nPosCount = 0; 111 | 112 | DirectoryPos[nPosCount] = -1; 113 | ++nPosCount; 114 | 115 | int nDirectoryPos = 0; 116 | while (true) 117 | { 118 | nDirectoryPos = strBasePath.IndexOf('\\', nDirectoryPos); 119 | if (nDirectoryPos == -1) 120 | break; 121 | 122 | DirectoryPos[nPosCount] = nDirectoryPos; 123 | ++nPosCount; 124 | ++nDirectoryPos; 125 | } 126 | 127 | if (!strBasePath.EndsWith("\\")) 128 | { 129 | DirectoryPos[nPosCount] = strBasePath.Length; 130 | ++nPosCount; 131 | } 132 | 133 | int nCommon = -1; 134 | for (int i = 1; i < nPosCount; ++i) 135 | { 136 | int nStart = DirectoryPos[i - 1] + 1; 137 | int nLength = DirectoryPos[i] - nStart; 138 | 139 | if (string.Compare(strBasePath, nStart, strFullPath, nStart, nLength, true) != 0) 140 | break; 141 | 142 | nCommon = i; 143 | } 144 | 145 | if (nCommon == -1) 146 | return strFullPath; 147 | 148 | var strBuilder = new StringBuilder(); 149 | for (int i = nCommon + 1; i < nPosCount; ++i) 150 | strBuilder.Append("..\\"); 151 | 152 | int nSubStartPos = DirectoryPos[nCommon] + 1; 153 | if (nSubStartPos < strFullPath.Length) 154 | strBuilder.Append(strFullPath.Substring(nSubStartPos)); 155 | 156 | string strResult = strBuilder.ToString(); 157 | return strResult == string.Empty ? ".\\" : strResult; 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/IO.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 926594a7b1ad44952939b03be5706c75 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Log.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace dpull 5 | { 6 | public class Log : MonoBehaviour 7 | { 8 | private System.IO.StreamWriter LogWriter; 9 | 10 | void Start () 11 | { 12 | CleanOldLog(); 13 | Application.RegisterLogCallback(HandleLog); 14 | } 15 | 16 | void OnDestory() 17 | { 18 | Application.RegisterLogCallback(null); 19 | } 20 | 21 | string GetLogDirectory() 22 | { 23 | var path = System.IO.Path.Combine(Application.persistentDataPath, "logs"); 24 | if (!System.IO.Directory.Exists(path)) 25 | System.IO.Directory.CreateDirectory(path); 26 | return path; 27 | } 28 | 29 | void CleanOldLog() 30 | { 31 | var dir = GetLogDirectory(); 32 | var files = System.IO.Directory.GetFiles(dir, "*.log", System.IO.SearchOption.AllDirectories); 33 | var now = System.DateTime.Now; 34 | var expirationTime = new System.TimeSpan(24 * 3, 0, 0); 35 | 36 | foreach (var file in files) 37 | { 38 | var fileInfo = new System.IO.FileInfo(file); 39 | var subTime = now - fileInfo.LastWriteTime; 40 | if (subTime < expirationTime) 41 | continue; 42 | 43 | try 44 | { 45 | System.IO.File.Delete(file); 46 | } 47 | catch 48 | { 49 | } 50 | } 51 | } 52 | 53 | void HandleLog(string logString, string stackTrace, LogType type) 54 | { 55 | if (type == LogType.Log && !logString.StartsWith("Lua:")) 56 | return; 57 | 58 | if (LogWriter == null) 59 | { 60 | lock(this) 61 | { 62 | if (LogWriter == null) 63 | { 64 | try 65 | { 66 | var logfile = GetLogDirectory(); 67 | logfile = System.IO.Path.Combine(logfile, string.Format("{0}.log", System.DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss"))); 68 | LogWriter = new System.IO.StreamWriter(logfile); 69 | } 70 | catch 71 | { 72 | } 73 | } 74 | } 75 | } 76 | 77 | if (LogWriter != null) 78 | { 79 | this.SendMessage("CacheLog", new string[]{logString, stackTrace}, SendMessageOptions.DontRequireReceiver); 80 | 81 | string log = string.Format("{0}<{1}>: {2}", System.DateTime.Now.ToString("MM-dd HH:mm:ss"), type.ToString(), logString); 82 | LogWriter.WriteLine(log); 83 | if (!string.IsNullOrEmpty(stackTrace)) 84 | { 85 | var formatStackTrace = stackTrace.Replace("\n", "\n\t"); 86 | LogWriter.Write("\t"); 87 | LogWriter.WriteLine(formatStackTrace); 88 | } 89 | LogWriter.Flush(); 90 | } 91 | } 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Log.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ab1b27f637c1d4df8aa907d15c5a855f 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/README.md: -------------------------------------------------------------------------------- 1 | # unity_utils # 2 | 3 | 是开发中用到的一些和项目无关的小工具 4 | 5 | ## Log ## 6 | 7 | 日志组件 8 | 9 | ## IO ## 10 | 11 | IO 扩展 12 | 13 | ## AndroidAssetStream ## 14 | 15 | Android AssetManager 16 | 17 | ## Editor/UIAdapterEditor ## 18 | 19 | 用来做NGUI适配 20 | 21 | ## Editor/CodeFormat ## 22 | 23 | 解决不同程序使用mac和windows系统开发引入的一些问题: 24 | 25 | 1. 换行符到底是\r\n 还是 \n 26 | 1. 文件中的中文是不是utf8 27 | 1. 文件有没有unf8 bom头 -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01b5646e6f0084461a3c0e4adbbb1e59 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/SimpleJson.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 91c2d808697a8490eb32aa082c83c936 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Util.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | public static class Util 6 | { 7 | public static T GetChildByName(this GameObject go, string name) where T:Component 8 | { 9 | var child = GetChildByName(go, name); 10 | if (child == null) 11 | return default(T); 12 | 13 | return child.gameObject.GetComponent(); 14 | } 15 | 16 | public static GameObject GetChildByName(this GameObject go, string name) 17 | { 18 | var child = GetChildByName(go.transform, name); 19 | return child == null ? null : child.gameObject; 20 | } 21 | 22 | public static Transform GetChildByName(Transform tr, string name) 23 | { 24 | // 广度优先 25 | foreach (Transform child in tr) 26 | { 27 | if (child.name == name) 28 | return child; 29 | } 30 | 31 | foreach (Transform child in tr) 32 | { 33 | Transform c = GetChildByName(child, name); 34 | if (c != null) 35 | return c; 36 | } 37 | 38 | return null; 39 | } 40 | 41 | public delegate bool TraversalCallback(Transform go); 42 | public static bool Traversal(this Transform transform, TraversalCallback callback) 43 | { 44 | // 深度优先 45 | foreach (Transform child in transform) 46 | { 47 | if (!callback(child)) 48 | return false; 49 | 50 | if (!child.Traversal(callback)) 51 | return false; 52 | } 53 | return true; 54 | } 55 | 56 | public static void ChangeLayer(GameObject go, int layer) 57 | { 58 | go.layer = layer; 59 | go.transform.Traversal(child=>{child.gameObject.layer = layer; return true; }); 60 | } 61 | 62 | public static string UrlToIP(string url) 63 | { 64 | try 65 | { 66 | var host = System.Net.Dns.GetHostEntry(url); 67 | foreach (System.Net.IPAddress ip in host.AddressList) 68 | { 69 | if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) 70 | return ip.ToString(); 71 | } 72 | return url; 73 | } 74 | catch(System.Exception e) 75 | { 76 | Debug.LogException(e); 77 | return url; 78 | } 79 | } 80 | 81 | public static string Md5File(string file) 82 | { 83 | using (var stream = System.IO.File.OpenRead(file)) 84 | { 85 | var md5 = System.Security.Cryptography.MD5.Create(); 86 | var data = md5.ComputeHash(stream); 87 | var sb = new System.Text.StringBuilder(); 88 | 89 | foreach(var b in data) 90 | { 91 | sb.Append(b.ToString("x2")); 92 | } 93 | return sb.ToString().ToLower(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Assets/Thirdparty/UnityUtils/Util.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18eda558b679f4a3bb9d4b93966e87b2 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 dpull.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpull/AssetBundlePatch/d3f008d3c5d561f7c865f6178362a2396da240f6/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AssetBundlePatch # 2 | 3 | `AssetBundlePatch` 可以对 Unity3d 的 AssetBundle进行差异更新。 4 | 5 | 可以根据客户端安装包资源和已有的AssetBundle包,判断出重复资源,只进行差异更新。 6 | 7 | 该插件诞生过程:[http://www.dpull.com/blog/2015-01-23-hero_assetbundle](http://www.dpull.com/blog/2015-01-23-hero_assetbundle) 8 | 9 | # 测试工程使用方法 # 10 | 测试环境:编辑器:unity4.6 mac, windows;移动设备:itouch4, 小米2 11 | 12 | ## iPhone ## 13 | 1. 打开XStudio->Tools->One Builder插件界面 14 | 1. 点击 Test iPhone 按钮 15 | 1. 运行 根目录中的 Bin/iPhone 文件夹中的XCode工程 16 | 1. 发布到手机上。 17 | 18 | ## Android ## 19 | 1. 打开XStudio->Tools->One Builder插件界面 20 | 1. 点击 Test Android 按钮 21 | 1. 使用Eclipse Import 根目录中的 Bin/Android 文件夹 22 | 1. 发布到手机上。 23 | 24 | # 做了什么 # 25 | 该工程共有两个场景,一个小人跑在蓝色的场景上(Level1),一个小人跑在绿色的场景上(Level2),也就是说,除了场景的材质,其他的资源都是一样的。 26 | 27 | 我们的安装包通过BuildPlayer只Build了Level1,然后通过BuildStreamedSceneAssetBundle制作了Level2的AssetBundle,这个AssetBundle有2.93MB,但其实这个AssetBundle中的大部分资源都在客户端安装包中,使用 `AssetBundlePatch`将其取差异,将差异压缩后大小为19.4KB,然后客户端开始运行时,通过`AssetBundlePatch` 将其恢复为原来2.93MB的AssetBundle,合并完成后客户端将Enter Level2的按钮,可以进入绿色背景的Level2. 28 | 29 | 30 | # 依赖库 # 31 | 32 | * [`SharpZip.dll`](https://github.com/icsharpcode/SharpZipLib) 多种压缩格式的解压和压缩库。 33 | * [`AssetBundleParser.dll`](https://github.com/dpull/AssetBundleParser) AssetBundle文件的解析库,因为效率,写在了C中,其实就是 [`disunity`](https://github.com/ata4/disunity) 的C版本 34 | --------------------------------------------------------------------------------