操作
Bilibili:BV1XZ4y1G7Me
安装 首先是安装,安装的话去Unity官网下载一个UnityHub,然后在UnityHub的安装界面点击安装,会列出最新的几个稳定的版本,选择自己所要安装的版本点击下一步,会列出捆绑安装的一些工具,默认的话会附带安装一个VStudio,不同版本的Unity也会附带不同版本的VStudio,当然也可以选择不装,之后使用自己喜欢的版本或工具编写代码。
如果之前没有安装默认的VStudio,这时需要在编辑->首选项->外置工具里 选择自己使用的编译器。
链接 首先在UI界面创建好自己所需要的元素,然后在下方的Project窗口右键新建一个脚本,在脚本里声明好之前所创建的那些元素,这里注意要加上public,否则无法被UI读到。
脚本的生命周期是必须要依托于所创建的对象的,所以可以新建一个空的Object或使用比较公有的一个元素,把脚本拖动到元素上,这个时候在元素的属性里就会多出一个Script,之前在脚本里所创建的变量就会显示出来,这时候就可以直接把元素拖动到这个框里,这样就相当于我们在脚本里创建的对象与UI里的元素链接起来了。
事件 在脚本里创建好函数,像之前那样把脚本附属在元素上,然后在Button属性里的OnClick新建,把附属脚本的元素拖动到框里,这时就可以在Function里面找到在脚本里所创建的函数,如果函数有参数的话,在这里可以自定义返回一个定值,这种方法适合多个元素公用一个函数的情况。
比如这里有很多个按钮,他们公用一个函数,通过返回不同的值就可以区分出当前点击的是哪一个按钮。
参考自:UGUI中Button添加事件大总结(有参,无参,动态) - 吸血鬼1124 - CSDN
传值 两个场景之间传值有很多种方法,这里的话是新建一个static类,里面创建static变量,这样就可以在第一个场景里赋值,然后在第二个场景里读取。
其他 Unity 用户手册 (2019.4 LTS) Unity 用户手册 (2019.4 LTS)
编译问题 如果有提示 错误,需要在文件->Player Setting->Player->Other Setting里找到Api Compatibility Level改为4.x就好。
Application各种路径在终端的本地路径 dataPath: 返回程序的数据文件所在的文件夹的路径(只读)。返回路径为相对路径,一般是相对于程序安装目录的位置。不同游戏平台的数据文件保存路径不同。
StreamingAssetsPath: 此属性用于返回数据流的缓存目录,返回路径为相对路径,适合设置一些外部数据文件的路径。(只读)
PersistentDataPath: 返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件。对应同一平台,在不同程序中调用此属性时,其返回值是相同的,但是在不同的运行平台下,其返回值会不一样。
temporaryCachePath: 此属性用于返回一个临时数据的缓冲目录(只读)。对于同一平台,在不同程序中调用此属性时,其返回值是相同的,但是在不同的运行平台下,其返回值是不一样的。
persistentDataPath 和temporaryCachePath 的返回值一般是程序所在平台的固定位置,适合程序在运行过程中产生的数据文件。
PC: Application.dataPath : /Assets
Application.streamingAssetsPath : /Assets/StreamingAssets
Application.persistentDataPath : C:/Users/xxxx/AppData/LocalLow/CompanyName/ProductName
Application.temporaryCachePath : C:/Users/xxxx/AppData/Local/Temp/CompanyName/ProductName
Android: Application.dataPath : /data/app/xxx.xxx.xxx.apk
Application.streamingAssetsPath : jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
Application.persistentDataPath : /data/data/xxx.xxx.xxx/files
Application.temporaryCachePath : /data/data/xxx.xxx.xxx/cache
IOS: Application.dataPath : Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
Application.streamingAssetsPath : Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw
Application.persistentDataPath : Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
Application.temporaryCachePath : Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches
Mac: Application.dataPath : /Assets
Application.streamingAssetsPath : /Assets/StreamingAssets
Application.persistentDataPath : /Users/xxxx/Library/Caches/CompanyName/Product Name
Application.temporaryCachePath : /var/folders/57/6b4_9w8113x2fsmzx_yhrhvh0000gn/T/CompanyName/Product Name
屏幕自适应 在Canvas Scaler(Script)面板中,有个UI Scale Mode选项卡,可以选Scale With Screen Size(默认为Constant Pixel Size),意思是根据实际屏幕的尺寸来自动调节画布缩放因子Scale Factor,选择后要设置一个参考尺寸,下面有个Match选项,可以选择是以高度还是宽度为参考,如下图所示:
然后对不同的UI设置合适的锚点。
跳转场景 1 Application.LoadLevel (1 );
1 2 3 4 using UnityEngine.SceneManagement;SceneManager.LoadScene(“SceneName”, LoadSceneMode.Single);
注意要在Build Setting里加上Scene。
存档 使用Newtonsoft.Json 类库,整理IOHelper类 。
Code:IOHelper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 using UnityEngine;using System.Collections;using System;using System.IO;using System.Text;using System.Security.Cryptography;using Newtonsoft.Json;public class IOHelper : MonoBehaviour { public static bool IsFileExists (string fileName ) { return File.Exists(fileName); } public static bool IsDirectoryExists (string dirpath ) { return Directory.Exists(dirpath); } public static string [] GetDirectoryFiles (string dirpath ) { DirectoryInfo directory = new DirectoryInfo(dirpath); FileInfo[] files = directory.GetFiles("*.olSave" , SearchOption.TopDirectoryOnly); string [] filesName = new string [files.Length]; for (int i_Files = 0 ; i_Files < files.Length; i_Files++) { filesName[i_Files] = files[i_Files].Name.Replace(".olSave" , "" ); } return filesName; } public static void CreateFile (string fileName, string content ) { StreamWriter streamWriter = File.CreateText(fileName); streamWriter.Write(content); streamWriter.Close(); } public static void CreateDirectory (string dirpath ) { if (IsDirectoryExists(dirpath)) return ; Directory.CreateDirectory(dirpath); } public static void SetData (string fileName, object pObject ) { string toSave = SerializeObject(pObject); StreamWriter streamWriter = File.CreateText(fileName); streamWriter.Write(toSave); streamWriter.Close(); } public static object GetData (string fileName, Type pType ) { StreamReader streamReader = File.OpenText(fileName); string data = streamReader.ReadToEnd(); streamReader.Close(); return DeserializeObject(data, pType); } private static string RijndaelEncrypt (string pString, string pKey ) { byte [] keyArray = UTF8Encoding.UTF8.GetBytes(pKey); byte [] toEncryptArray = UTF8Encoding.UTF8.GetBytes(pString); RijndaelManaged rDel = new RijndaelManaged(); rDel.Key = keyArray; rDel.Mode = CipherMode.ECB; rDel.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = rDel.CreateEncryptor(); byte [] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0 , toEncryptArray.Length); return Convert.ToBase64String(resultArray, 0 , resultArray.Length); } private static String RijndaelDecrypt (string pString, string pKey ) { byte [] keyArray = UTF8Encoding.UTF8.GetBytes(pKey); byte [] toEncryptArray = Convert.FromBase64String(pString); RijndaelManaged rDel = new RijndaelManaged(); rDel.Key = keyArray; rDel.Mode = CipherMode.ECB; rDel.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = rDel.CreateDecryptor(); byte [] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0 , toEncryptArray.Length); return UTF8Encoding.UTF8.GetString(resultArray); } private static string SerializeObject (object pObject ) { string serializedString = string .Empty; serializedString = JsonConvert.SerializeObject(pObject); return serializedString; } private static object DeserializeObject (string pString, Type pType ) { object deserializedObject = null ; deserializedObject = JsonConvert.DeserializeObject(pString, pType); return deserializedObject; } }
参考自:Unity3D游戏开发之游戏读/存档功能在Unity3D中的实现 - qinyuanpei - CSDN
调试窗口 在Build游戏后按Q现实Debug窗口,整理ChinarViewConsole类 。
Code:ChinarViewConsole 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 #define MACRO_CHINAR using System.Collections.Generic;using UnityEngine;namespace ChinarConsole { class ChinarViewConsole : MonoBehaviour { #if MACRO_CHINAR struct Log { public string Message; public string StackTrace; public LogType LogType; } #region Inspector 面板属性 [Tooltip("快捷键-开/关控制台" ) ] public KeyCode ShortcutKey = KeyCode.Q; [Tooltip("摇动开启控制台?" ) ] public bool ShakeToOpen = true ; [Tooltip("窗口打开加速度" ) ] public float shakeAcceleration = 3f ; [Tooltip("是否保持一定数量的日志" ) ] public bool restrictLogCount = false ; [Tooltip("最大日志数" ) ] public int maxLogs = 1000 ; #endregion private readonly List<Log> logs = new List<Log>(); private Log log; private Vector2 scrollPosition; private bool visible; public bool collapse; static readonly Dictionary<LogType, Color> logTypeColors = new Dictionary<LogType, Color> { {LogType.Assert, Color.white}, {LogType.Error, Color.red}, {LogType.Exception, Color.red}, {LogType.Log, Color.white}, {LogType.Warning, Color.yellow}, }; private const string ChinarWindowTitle = "Chinar-控制台" ; private const int Edge = 20 ; readonly GUIContent clearLabel = new GUIContent("清空" , "清空控制台内容" ); readonly GUIContent hiddenLabel = new GUIContent("合并信息" , "隐藏重复信息" ); readonly Rect titleBarRect = new Rect(0 , 0 , 10000 , 20 ); Rect windowRect = new Rect(Edge, Edge, Screen.width - (Edge * 2 ), Screen.height - (Edge * 2 )); void OnEnable ( ) {#if UNITY_4 Application.RegisterLogCallback(HandleLog); #else Application.logMessageReceived += HandleLog; #endif } void OnDisable ( ) {#if UNITY_4 Application.RegisterLogCallback(null ); #else Application.logMessageReceived -= HandleLog; #endif } void Update ( ) { if (Input.GetKeyDown(ShortcutKey)) visible = !visible; if (ShakeToOpen && Input.acceleration.sqrMagnitude > shakeAcceleration) visible = true ; } void OnGUI ( ) { if (!visible) return ; windowRect = GUILayout.Window(666 , windowRect, DrawConsoleWindow, ChinarWindowTitle); } void DrawConsoleWindow (int windowid ) { DrawLogsList(); DrawToolbar(); GUI.DragWindow(titleBarRect); } void DrawLogsList ( ) { scrollPosition = GUILayout.BeginScrollView(scrollPosition); for (var i = 0 ; i < logs.Count; i++) { if (collapse && i > 0 ) if (logs[i].Message != logs[i - 1 ].Message) continue ; GUI.contentColor = logTypeColors[logs[i].LogType]; GUILayout.Label(logs[i].Message); } GUILayout.EndScrollView(); GUI.contentColor = Color.white; } void DrawToolbar ( ) { GUILayout.BeginHorizontal(); if (GUILayout.Button(clearLabel)) { logs.Clear(); } collapse = GUILayout.Toggle(collapse, hiddenLabel, GUILayout.ExpandWidth(false )); GUILayout.EndHorizontal(); } void HandleLog (string message, string stackTrace, LogType type ) { logs.Add(new Log { Message = message, StackTrace = stackTrace, LogType = type, }); DeleteExcessLogs(); } void DeleteExcessLogs ( ) { if (!restrictLogCount) return ; var amountToRemove = Mathf.Max(logs.Count - maxLogs, 0 ); print(amountToRemove); if (amountToRemove == 0 ) { return ; } logs.RemoveRange(0 , amountToRemove); } #endif } }
Demo