读一读

有些情况我们需要使用自定义的宏来做一些东西的开关,例如测试AssetBundle的加载等

private void Awake()
{
    #if TEST_HONG  //如果定义了这个宏,就会调用
            Debug.LogError("hahaha");
    #endif
}


定义这个宏,打开File/Build Settings/PlayerSettings/Other Settings/Scripting Define Symbols下的输入框输入宏,用;好区分多个控,按回车键确定,注意你要在哪个平台定义

blob.png


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];


blob.png


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,你就可以看到日志的输出了。

image.png


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");
}


看注释。