unity 多sdk 打包方案

多个sdk 打包方案

需求
最近一直在接sdk,同一个工程要接好几个sdk,比如小米的广告sdk,vivo的支付和广告,oppo的游戏中心,
然后每换一个sdk打包我都要从新复制一个工程,然后去接sdk,再在里面打包,这样做很浪费时间,也很浪费精力,所以想了很长时间,大致想出来两种解决方案

解决方案
1.使用Android的多渠道打包方案,配置一个个库文件,引用那个直接导出
优点:大部分工作集中在Android端和unity分离,无论是耦合性还是效率都不错,能够很完美的解决需求
缺点:我不会配置
2.使用unity窗口,将每一个版本的包的配置信息记录下来,然后将接好的文件放到指定的目录,,每次更换打包的话通过配置信息将plugins从别的地方复制进unity,然后使用编辑器打包
优点:除了对接sdk还是要手动去接,其他的内容全部放在unity端来处理,更加方便我来控制
缺点:或者说这是我想到的两种方案都出现的问题,,解耦 无论是c#还是java,都是要编译的,但是每个包要处理的反应是不一样的,有的要显示广告有的要显示支付,这是要处理的
还好的是,我一直比较喜欢将项目解耦和,让各个部分互不干扰,通过一些方法,大致实现了这种解耦

先看最后的效果unity 多sdk 打包方案_第1张图片

然后上代码

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using LitJson;
using System;

public class ProjectBuildForAndroid : EditorWindow
{

    string JsonPath = @"F:\SDK配置\欢乐玻璃杯\Json";
    string FilePath = @"F:\SDK配置\欢乐玻璃杯\File";
    DictionaryJsonData> Dic = new DictionaryJsonData>();
    //公用信息 开始
    string ConfigureJsonName = "";
    string ProductName = "";
    string PacketageName = "";
    string Version = "";
    string BundleVersionCode = "";

    string PluginsPath = "";
    string ScriptsPath = "";



     static JsonData  lookJson;


    ProjectBuildForAndroid()
    {
        this.titleContent = new GUIContent("ProjectBuildForAndroid");
        titleContent.text = "安卓设置";
        getConfigureJson();
    }

    [MenuItem("Tool/自定义打包")]
    static void showWindow()
    {
        EditorWindow.GetWindow(typeof(ProjectBuildForAndroid));
    }
    void OnGUI()
    {
        GUILayout.BeginVertical();
        //绘制标题
        GUILayout.Space(10);
        GUI.skin.label.fontSize = 24;
        GUI.skin.label.alignment = TextAnchor.MiddleCenter;
        GUILayout.Label("自定义打包");
        GUILayout.Label(System.DateTime.Now + "");

        GUILayout.EndVertical();




        GUILayout.BeginVertical();


        GUILayout.Space(10);
        if (Dic.Count >= 0)
        {
            foreach (KeyValuePairJsonData> item in Dic)
            {
                if (GUILayout.Button(item.Key.ToString().Split('.')[0], GUILayout.Width(200), GUILayout.ExpandWidth(true)))
                {
                    lookJson = item.Value;
                    ShowSetting();
                }
            }
        }



        GUILayout.BeginHorizontal();
        if (GUILayout.Button("查看信息", GUILayout.Height(60),GUILayout.Width(200)))
        {
            if (lookJson==null )
            {
                this.ShowNotification(new GUIContent("暂无提示信息,请选择要打包的配置"));
                return;
            }
            string txt = "";
            for (int i = 0; i < lookJson.Count; i++)
            {
                txt +=  lookJson[i].ToString() + "\n";
            }
            this.ShowNotification(new GUIContent(txt));
        }
        GUILayout.EndHorizontal();

        GUILayout.EndVertical();





        GUILayout.BeginVertical( );

        GUILayout.Space(10);
        GUILayout.Label("配置信息");
        ConfigureJsonName = EditorGUILayout.TextField("配置信息名称:", ConfigureJsonName);
        ProductName = EditorGUILayout.TextField("产品名字:", ProductName);
        PacketageName = EditorGUILayout.TextField("包名:", PacketageName);
        Version = EditorGUILayout.TextField("版本", Version);
        BundleVersionCode = EditorGUILayout.TextField("代码版本:", BundleVersionCode);


        GUILayout.Space(10);
        GUILayout.Label("复制Plugins");
        PluginsPath = EditorGUILayout.TextField("Plugins路径:", PluginsPath);
        ScriptsPath = EditorGUILayout.TextField("SDK脚本路径:", ScriptsPath);


        GUILayout.BeginHorizontal();

        if (GUILayout.Button("保存配置信息",GUILayout.Height(60), GUILayout.Width(200)))
        {
            SaveConfigureJson();
        }
        if (GUILayout.Button("修改配置信息", GUILayout.Height(60), GUILayout.Width(200)))
        {
            ChangeConfigureJson();
        }
        if (GUILayout.Button("复制脚本文件", GUILayout.Height(60), GUILayout.Width(200)))
        {
            CopyFile();
        }
        if (GUILayout.Button("开始打包", GUILayout.Height(60), GUILayout.Width(200)))
        {
            Build();
        }
        GUILayout.EndHorizontal();



        GUILayout.EndVertical();
    }
    //得到所有的以保存渠道的信息
    void getConfigureJson()
    {
        DirectoryInfo dir = new DirectoryInfo(JsonPath);
        if (dir.GetFiles().Length ==0)
        {
            this.ShowNotification(new GUIContent("暂无配置信息"));
            return;
        }
        FileInfo[]  Jsonfiles = dir.GetFiles();

        for (int i = 0; i < Jsonfiles.Length; i++)
        {
            string name = Jsonfiles[i].Name;
            string txt= File.ReadAllText(Jsonfiles[i].FullName, Encoding.UTF8);
            JsonData obj = JsonMapper.ToObject(txt);
            if(!Dic.ContainsKey (name))
            Dic.Add(name, obj);
        }
        if (lookJson!=null )
        {
            ShowSetting();
        }

    }
    //用于保存当前信息
    void SaveConfigureJson()
    {
        if (Dic.ContainsKey (ConfigureJsonName+".json"))
        {
            this.ShowNotification(new GUIContent("该配置已存在"));
            return;
        }
        if (!Directory.Exists (JsonPath ))
        {
            Directory.CreateDirectory(JsonPath );
        }
        JsonData saveJson = new JsonData();
        saveJson["ConfigureJsonName"] = ConfigureJsonName;
        saveJson["ProductName"] = ProductName;
        saveJson["PacketageName"] = PacketageName;
        saveJson["Version"] = Version;
        saveJson["BundleVersionCode"] = BundleVersionCode;
        saveJson["PluginsPath"] = FilePath + "/" + ConfigureJsonName + "/Plugins";
        saveJson["ScriptsPath"] = FilePath + "/" + ConfigureJsonName + "/SDK";
        string str = saveJson.ToJson();

        StreamWriter sw = new StreamWriter(JsonPath+ "/" + ConfigureJsonName + ".json");
        sw.WriteLine(str);
        sw.Close();
        if (!Directory.Exists (FilePath+"/"+ ConfigureJsonName))
        {
            Directory.CreateDirectory(FilePath + "/" + ConfigureJsonName+"/Plugins");
            Directory.CreateDirectory(FilePath + "/" + ConfigureJsonName + "/SDK");
        }


        getConfigureJson();


    }
    void ChangeConfigureJson()
    {
        if (!Dic.ContainsKey(ConfigureJsonName + ".json"))
        {
            this.ShowNotification(new GUIContent("该配置不存在,请直接保存配置信息"));
            return;
        }
        else
        {
            Dic.Remove(ConfigureJsonName + ".json");
            File.Delete(JsonPath + "/" + ConfigureJsonName + ".json");
            lookJson["ConfigureJsonName"] = ConfigureJsonName;
            lookJson["ProductName"] = ProductName;
            lookJson["PacketageName"] = PacketageName;
            lookJson["Version"] = Version;
            lookJson["BundleVersionCode"] = BundleVersionCode;
            lookJson["PluginsPath"] = PluginsPath;
            lookJson["ScriptsPath"] = ScriptsPath;
            string str = lookJson.ToJson();

            StreamWriter sw = new StreamWriter(JsonPath + "/" + ConfigureJsonName + ".json");
            sw.WriteLine(str);
            sw.Close();

            getConfigureJson();
        }

    }
    bool isCopyOver;
    void CopyFile()
    {
        string PluginsFilePath = FilePath + "/"+ ConfigureJsonName+ "/Plugins";
        if (!Directory.Exists(PluginsFilePath))
        {
            this.ShowNotification(new GUIContent("要复制的Plugins文件不存在,请注意"));
            return;
        }
        string ScriptsFilePath = FilePath + "/" + ConfigureJsonName + "/SDK/SDKManager.cs";
        if (!File.Exists(ScriptsFilePath))
        {
            this.ShowNotification(new GUIContent("要复制的SDKManager文件不存在,请注意"));
            return;
        }

        string Pluginspath = Application.dataPath+"/Plugins";
        if (Directory .Exists (Pluginspath))
        {
            FileAttributes attr = File.GetAttributes(Pluginspath);
            if (attr == FileAttributes.Directory)
            {
                Directory.Delete(Pluginspath, true);
            }
            else
            {
                File.Delete(Pluginspath);
            }
        }
        string Scriptspath = Application.dataPath + "/SDK/SDKManager.cs";
        if (File .Exists(Scriptspath))
        {
            File.Delete(Scriptspath);
        }
        CopyOldLabFilesToNewLab(PluginsFilePath, Pluginspath);
        while (isCopyOver==false )
        {

        }
        FileInfo ScriptSDKManager = new FileInfo(ScriptsFilePath);
        ScriptSDKManager.CopyTo(Scriptspath);

    }
    void Build()
    {
        PlayerSettings.companyName = ConfigureJsonName;
        PlayerSettings.productName = ProductName;

        PlayerSettings.Android.keystoreName = @"C:\Users\administered\Desktop\签名\Sg3.keystore";
        PlayerSettings.Android.keyaliasName = "Sg3.keystore";
        PlayerSettings.Android.keystorePass = "morefuntek";
        PlayerSettings.Android.keyaliasPass = "morefuntek";
        PlayerSettings.applicationIdentifier = PacketageName;
        PlayerSettings.bundleVersion = Version;
        PlayerSettings.Android.bundleVersionCode =int.Parse (BundleVersionCode) ;

        string apkName = string.Format(@"C:\Users\administered\Desktop\Build\{0}.apk", ConfigureJsonName);

        List levels = new List();
        foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
        {
            if (!scene.enabled) continue;
            // 获取有效的 Scene
            levels.Add(scene.path);
        }
        BuildTarget buildTarget = BuildTarget.Android;
        // 切换到 Android 平台
        EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android,buildTarget);
        string res = BuildPipeline.BuildPlayer(levels.ToArray(), apkName, buildTarget, BuildOptions.None);

        if (res.Length > 0)
        {
            throw new Exception("BuildPlayer failure: " + res);
        }

        AssetDatabase.Refresh();


    }


    void ShowSetting()
    {
        ConfigureJsonName = lookJson["ConfigureJsonName"].ToString();
        ProductName = lookJson["ProductName"].ToString();
        PacketageName = lookJson["PacketageName"].ToString();
        Version = lookJson["Version"].ToString();
        BundleVersionCode = lookJson["BundleVersionCode"].ToString();
        PluginsPath = lookJson["PluginsPath"].ToString();
        ScriptsPath=lookJson["ScriptsPath"].ToString ();
    }

    public void  CopyOldLabFilesToNewLab(string sourcePath, string savePath)
    {
        if (!Directory.Exists(savePath))
        {
            Directory.CreateDirectory(savePath);
        }

        #region //拷贝labs文件夹到savePath下
        try
        {
            string[] labDirs = Directory.GetDirectories(sourcePath);//目录
            string[] labFiles = Directory.GetFiles(sourcePath);//文件
            if (labFiles.Length > 0)
            {
                for (int i = 0; i < labFiles.Length; i++)
                {
                    if (Path.GetExtension(labFiles[i]) != ".meta")//排除.lab文件
                    {
                        File.Copy(sourcePath + "\\" + Path.GetFileName(labFiles[i]), savePath + "\\" + Path.GetFileName(labFiles[i]), true);
                    }
                }
            }
            if (labDirs.Length > 0)
            {
                for (int j = 0; j < labDirs.Length; j++)
                {
                    Directory.GetDirectories(sourcePath + "\\" + Path.GetFileName(labDirs[j]));

                    //递归调用
                    CopyOldLabFilesToNewLab(sourcePath + "\\" + Path.GetFileName(labDirs[j]), savePath + "\\" + Path.GetFileName(labDirs[j]));
                }
            }
        }
        catch (Exception)
        {
            isCopyOver = false;
        }
        #endregion
        isCopyOver = true;
    }
}

这就是全部的代码了,想了几天的时间,plugins文件夹和SDkmanager.cs文件是要先写好的,plugins是放接好的sdk和Android文件 而 SDKMnaager.cs是解耦的关键 是最后跟sdk交接的部分

C#交互脚本

这里写图片描述
这里采用了消息的传递机制,SDKEventDisPatcer.cs是消息传递中心 SDKManager.cs是真正接受消息,并与sdk交互的部分,后面直接更换这个脚本就行了 SDKUI.cs是需要拖到物体上的,里面发出各种消息 UnitySingleton.cs 是单例类

先说一下思路,再上代码 SDKUI.cs是要挂到物体上的,由这个脚本负责消息的发出 和SDKManager的初始化 SDKEventDisPatcer.cs负责将消息发给已经注册消息的脚本,而SDKManager会根据不同的情况,注册并接受不同的消息从而实现解耦
要换sdk的话只需要更换plugins和更换sdkmanager就行了

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SDKEventDisPatcer : Singleton
{


    public delegate void OnActionHandle(object obj = null);
    public Dictionary<ushort, List> dic = new Dictionary<ushort, List>();

    public void AddEventListener(ushort ProtoCode, OnActionHandle handle)
    {
        if (dic.ContainsKey(ProtoCode))
        {
            dic[ProtoCode].Add(handle);
        }
        else
        {
            List listHandle = new List();
            listHandle.Add(handle);
            dic[ProtoCode] = listHandle;
        }
    }
    public void RemeiveEventListener(ushort ProtoCode, OnActionHandle handle)
    {
        if (dic.ContainsKey(ProtoCode))
        {
            List listhandle = dic[ProtoCode];
            listhandle.Remove(handle);
            if (listhandle.Count == 0)
            {
                dic.Remove(ProtoCode);
            }
        }

    }

    public void Dispatch(ushort ProtoCode, object obj=null)
    {
        if (dic.ContainsKey(ProtoCode))
        {
            List listhandle = dic[ProtoCode];
            if (listhandle != null && listhandle.Count > 0)
            {
                for (int i = 0; i < listhandle.Count; i++)
                {
                    if (listhandle[i] != null)
                    {
                        listhandle[i](obj);
                    }
                }
            }
        }
    }
    public int GetlisthandleCount(ushort ProtoCode)
    {
        return dic[ProtoCode].Count;
    }
}
public class EvevtCode
{
    public const ushort Pay = 1;
    public const ushort Banner = 2;
    public const ushort Inter = 3;
    public const ushort Video = 4;
    public const ushort Splash = 5;
}

SDKManager

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// 
/// /////////////////
/// 
public class SDKManager : UnitySingleton {

    protected override void Awake()
    {
        base.Awake();
        SDKEventDisPatcer.Instance.AddEventListener(EvevtCode.Pay, OnPay);
        SDKEventDisPatcer.Instance.AddEventListener(EvevtCode.Banner, OnBanner);
        SDKEventDisPatcer.Instance.AddEventListener(EvevtCode.Inter, OnInter);
        SDKEventDisPatcer.Instance.AddEventListener(EvevtCode.Video, OnVideo);
        SDKEventDisPatcer.Instance.AddEventListener(EvevtCode.Splash, OnSplash);
    }


    AndroidJavaObject ao;
    void Start()
    {
        AndroidJavaClass ac = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        ao = ac.GetStatic("currentActivity");
    }

    public void LateUpdate()
    {
        if (Application.platform == RuntimePlatform.Android && (Input.GetKeyDown(KeyCode.Escape)))
        {
            try
            {
                ao.CallStatic("exitMyGame");
            }
            catch (System.Exception)
            {}

        }
    }




    private void OnSplash(object obj)
    {

    }

    private void OnVideo(object obj)
    {
        ao.Call("showVideoAd");
    }

    private void OnInter(object obj)
    {
        ao.Call("showInterAd");
    }

    private void OnBanner(object obj)
    {
        ao.Call("showBannerAd");
    }

    private void OnPay(object obj)
    {
        ao.Call("doPay");
    }

}

SDKUI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SDKUI : MonoBehaviour {
    private void Awake()
    {
        GameObject SDKManager = GameObject.Find("SDKManager");
        if (SDKManager==null )
        {
            SDKManager = new GameObject("SDKManager");
            SDKManager.AddComponent();
        }
    }
    // Use this for initialization
    void Start () {
        switch (gameObject.name )
        {
            case "Button":
                GetComponent

UnitySingleton

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UnitySingleton : MonoBehaviour where T : Component
{

    public static T Instance;
    protected virtual void Awake()
    {
        if (Instance)
        {
            DestroyImmediate(this);
        }
        else
        {
            DontDestroyOnLoad(this );
            Instance = this as T;
        }
    }

}
public abstract class Singleton where T : new()
{
    private static T _instance;
    static object _lock = new object();
    public static T Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                        _instance = new T();
                }
            }
            return _instance;
        }
    }
}

以上就是全部的代码,写的很简陋,日后会一点点更新的,有大神觉得那里写的不对或者可以优化的请直接说出,万分感谢,有不懂的同学也可以留言

你可能感兴趣的:(编辑器)