有些情况我们需要使用自定义的宏来做一些东西的开关,例如测试AssetBundle的加载等
private void Awake() { #if TEST_HONG //如果定义了这个宏,就会调用 Debug.LogError("hahaha"); #endif }
定义这个宏,打开File/Build Settings/PlayerSettings/Other Settings/Scripting Define Symbols下的输入框输入宏,用;好区分多个控,按回车键确定,注意你要在哪个平台定义
UNITY_EDITOR | 编辑器下执行的代码 |
UNITY_EDITOR_WIN | Windows平台下编辑器执行 |
UNITY_EDITOR_OSX | OSX平台编辑器执行 |
UNITY_STANDALONE_OSX | Mac主机平台 |
UNITY_STANDALONE_WIN | Win主机平台 |
UNITY_STANDALONE_LINUX | Linux主机平台 |
UNITY_IOS | 苹果手机 |
UNITY_IPHONE | 弃用. 使用UNITY_IOS替代 |
UNITY_ANDROID | 安卓平台调用 |
UNITY_WEBGL | WEBGL平台 |
UNITY_5 | Unity5++版本,所有5.x.x版本 |
UNITY_5_0 | Unity5.0+版本,所有5.0.x版本 |
UNITY_5_0_1 | Unity 5.0.1版本 |
有时候,我们需要public一个二维数组来赋值,就例如很多类型的声音,每种类型又有很多的子声音,这时候就需要二维数组来解决了,可是public的二维数组并不会显示在Inspector中,就不能拖拉式的赋值了。剩下就只能Resource了,或则远程了。
其实我们可以用一个类来充当数据结构,然后声明为可序列化的,里面的数据为数组,而在客户端中声明这个数据结构类为数组,这样就完美解决了。
[Serializable] public class MajiangSAudio { public AudioClip[] audios; public AudioClip[] localAudios; } //使用 public MajiangSAudio[] _ManSound = new MajiangSAudio[40];
using UnityEditor; using System.IO; public class TipDataAssetBundleName { [MenuItem("Resource/2.Tip AssetBundleName")] public static void TipAssetBundleName() { DirectoryInfo directoryInfo = new DirectoryInfo(EditorConstConfig.TipDataPath); if (!directoryInfo.Exists) { UnityEngine.Debug.LogError("Tip DIR not exists"); return; } string[] dirs = Directory.GetDirectories(EditorConstConfig.TipDataPath); foreach (string dir in dirs) { string name = Path.GetFileName(dir); TipAssetBundleName(dir, name); } AssetDatabase.Refresh(); } private static void TipAssetBundleName(string directory, string name) { if (name.IndexOf("/") == -1) { //再深一层 string[] dirs = Directory.GetDirectories(directory); foreach (string dir in dirs) { name = name + "/" + Path.GetFileName(dir); TipAssetBundleName(dir, name); } } else { string[] files = Directory.GetFiles(directory); foreach (string file in files) { if (file.EndsWith(".meta")) continue; string path = file.Substring(file.IndexOf("Assets")).Replace('\\','/'); AssetImporter importer = AssetImporter.GetAtPath(path); importer.assetBundleName = name; importer.assetBundleVariant = "assetbundle"; } } } }
这里的菜单是2,其实在我写的资源管理中还有一步就是将资源复制到专门用来标志Assetbundle名字的单独文件夹中,然后调用这个会遍历这个文件夹,按照文件夹的名字来给资源添加AssetBundle名字,第一层目录是资源的大分类,第二层目录才是装资源的,例如Lua/login文件夹,login下的资源文件的AssetBundle名字就是lua/login。Lua文件夹下不保存任何资源,只做分类,这只是规定而已,也可以标志为lua,个人爱好。
1.创建事件类型,继承自IEventSystemHandler
using UnityEngine.EventSystems; public interface IMyEvent : IEventSystemHandler { void MyMessage(); }
2.实现这个自定义的接口表示监听这个事件类型
using UnityEngine; public class EventTesta : MonoBehaviour,IMyEvent { public void MyMessage() { Debug.LogError("接收到我的消息"); } }
3.触发事件
using UnityEngine; using UnityEngine.EventSystems; public class OnCubeClick : MonoBehaviour,IPointerClickHandler { //监听了这个事件的目标 private GameObject target; public void OnPointerClick(PointerEventData eventData) { //触发事件,目标,参数,执行 ExecuteEvents.Execute<IMyEvent>(target, null, (x, y) => x.MyMessage()); } private void Awake() { target = GameObject.Find("Main Camera"); } }
using UnityEngine; using System.Collections; public class LogTEST : MonoBehaviour { void Start () { //在一个日志信息上注册一个委托来被调用 Application.RegisterLogCallback (MyLogCallback); } /// log callback check /// </summary> /// <param name="condition">log内容.</param> /// <param name="stackTrace">log产生的栈数据追踪</param> /// <param name="type">log的类型.</param> void MyLogCallback (string condition, string stackTrace, LogType type){} }
在MyLogCallback里面会接受到所有的Debug输出的日志,我们可以在这里整合信息,保存起来,然后使用GUI显示出来,实现一个运行时的Console。也可以使用WWWForm来发送错误报告,在服务端生成多用户的日志报告,分析情况等。
在android-sdk的包中有一个tools工具文件夹,可以双击打开monitor.bat或则是ddms.bat,就会打开一个叫AndroidDeviceMonitor的调试工具,有一个LogCat就是捕捉输出的日志的,他会捕捉android上一切的活动,所以需要新建一个Filter设置Tags为Unity,就可以只看Unity游戏的相关日志了。
在手机上安装好打包后的游戏(开发模式),开启开发者模式的Usb调试,用数据线连接上电脑,然后打开游戏,切换到你游戏的Filter,你就可以看到日志的输出了。
AssetBundle通过Load方法加载资源的时候,是从内存的镜像文件加载成内存的对象,当AssetBundle通过UnLoad(false)卸载资源的时候已经加载出来的资源对象是不会被释放的(只释放镜像内存),需要程序去管理起来了,通过Resource.UnLoad(prefab)卸载掉。
[Test] [UnityPlatform (RuntimePlatform.WindowsPlayer)]//单个 public void TestMethod1() { Assert.AreEqual(Application.platform, RuntimePlatform.WindowsPlayer); } [Test] [UnityPlatform(exclude = new[] { RuntimePlatform.WindowsEditor })]//多个 public void TestMethod2() { Assert.AreEqual(Application.platform, RuntimePlatform.WindowsEditor); }
UnityPlatform指定在哪些平台才会运行这些测试代码。
[Test] public void LogAssertExample() { //指定一些Log的信息 LogAssert.Expect(LogType.Log, "Log message"); //如果输出的信息不是这一句,就会测试不通过 Debug.Log("Log message");//可以通过 Debug.LogError("Error message"); //如果没有下面这一条,上面这一条就会导致测试不通过了 LogAssert.Expect(LogType.Error, "Error message"); }
看注释。