Unity组件开发--AB包打包工具

news2024/11/18 13:50:58

1.项目工程路径下创建文件夹:ABundles

2.AB包打包脚本:

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

public class AssetBundlePackage {


    static string[] GetBuildScenes() {
        List<string> sceneArray = new List<string>();
        foreach (EditorBuildSettingsScene e in EditorBuildSettings.scenes) {
            if (e == null) continue;
            if (e.enabled) sceneArray.Add(e.path);
        }
        return sceneArray.ToArray();
    }


    [MenuItem("BuildScene/Build")]
    public static void BuildScene() {
        //BundleAssetsBundle_Webgl();

        string folderPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
        Debug.Log("Selected Folder: " + folderPath);

        BuildPipeline.BuildPlayer(new string[] { "Assets/GameStart.unity" }, folderPath, BuildTarget.WebGL, BuildOptions.AutoRunPlayer);
    }

    [MenuItem("BuildScene/BuildForMobile")]
    public static void BuildSceneForMobile()
    {
        //BundleAssetsBundle_Webgl();

        string folderPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
        Debug.Log("Selected Folder: " + folderPath);

        BuildPipeline.BuildPlayer(new string[] { "Assets/GameStartMoibile.unity" }, folderPath, BuildTarget.WebGL, BuildOptions.AutoRunPlayer);
    }

    [MenuItem("SceneAsset/BuildCurrent")]
    public static void BuildCurrentScene() {
        string rootPath = Application.dataPath.ToLower().Replace("assets", "") + "ABundles/webgl/scenes";
        string scenePath = EditorSceneManager.GetActiveScene().path;
        string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath).ToLower();

        AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
        assetBundleBuild.assetNames = new []{ scenePath };
        assetBundleBuild.assetBundleName = sceneName + ".bundle";
        BuildPipeline.BuildAssetBundles(rootPath, new AssetBundleBuild[] { assetBundleBuild}, BuildAssetBundleOptions.None, BuildTarget.WebGL);
    }

    [MenuItem("SceneAsset/BuildAllScene")]
    public static void BuildAllScene() {
        bool isOk = EditorUtility.DisplayDialog("确认框", "是否将所有场景打成AB包", "确认", "取消");
        if (!isOk) {
            return;
        }

        //AB包路径是ABundles
        string rootPath = Application.dataPath.ToLower().Replace("assets","") + "ABundles/webgl/scenes";
        var allScenesPath = GetBuildScenes();
        foreach (var scenePath in allScenesPath) {
            string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath).ToLower();
            AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
            assetBundleBuild.assetNames = new[] { scenePath };
            assetBundleBuild.assetBundleName = sceneName + ".bundle";
            Debug.Log(sceneName + scenePath);
            BuildPipeline.BuildAssetBundles(rootPath, new AssetBundleBuild[] { assetBundleBuild }, BuildAssetBundleOptions.None, BuildTarget.WebGL);
        }
    }


    [MenuItem("AssetBundle/BuildWebGL")]
    public static void BundleAssetsBundle_Webgl() {
        Debug.Log("BundleAssetsBundle WebGL");
        BuildAllAssetBundles();
    }
    private static void BuildAssetsBundle(BuildTarget target) {
        //string packagePath = Application.streamingAssetsPath;
        //if (packagePath.Length <= 0 && !Directory.Exists(packagePath))
        //{
        //    return;
        //}
        //BuildPipeline.BuildAssetBundles(packagePath, BuildAssetBundleOptions.UncompressedAssetBundle, target);
    }
    //Asset/BundleAsset/Prefab/Com/a.bundle  Prefab/Com/a
    public static string RemovePrefix(string inputString) {
        inputString = inputString.Replace("\\", "/");
        string prefix = "Assets/BundleAsset/";
        string result = inputString.Replace(prefix, "");
        return result.Replace(".bundle", "");
    }
    static void BuildAllAssetBundles() {
        string prefabsFolderPath = "Assets/BundleAsset/Prefab";

        if (!Directory.Exists(prefabsFolderPath)) {
            Debug.LogError($"Folder {prefabsFolderPath} does not exist!");
            return;
        }

        //AB包路径是ABundles
        string rootPath = Application.dataPath.ToLower().Replace("assets", "") + "ABundles/webgl";
        if (!Directory.Exists(rootPath)) {
            Debug.LogError($"Folder {rootPath} does not exist!");
            return;
        }

        string[] prefabGUIDs = AssetDatabase.FindAssets("t:Prefab", new[] { prefabsFolderPath });
        foreach (var prefabGUID in prefabGUIDs) {
            string prefabPath = AssetDatabase.GUIDToAssetPath(prefabGUID);
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
            if (prefab == null) {
                continue;
            }
            var assetPath = AssetDatabase.GetAssetPath(prefab);
            var dependencies = GetAllDependencies(assetPath).ToArray();

            var withoutEx = Path.GetFileNameWithoutExtension(prefabPath);

            AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
            assetBundleBuild.assetBundleName = RemovePrefix(withoutEx).ToLower() + ".bundle";
            assetBundleBuild.assetNames = dependencies;
            var directName = Path.GetDirectoryName(assetPath);
            var outPackagePath = $"{rootPath}/{RemovePrefix(directName).ToLower()}";

            Debug.Log($"prefabPath {prefabPath}");
            if (!Directory.Exists(outPackagePath)) {
                Directory.CreateDirectory(outPackagePath);
            }

            BuildPipeline.BuildAssetBundles(outPackagePath, new AssetBundleBuild[] { assetBundleBuild }, BuildAssetBundleOptions.None, BuildTarget.WebGL);
        }

        Debug.Log("BuildAssetBundles ok");
    }

    public static List<string> GetAllDependencies(string assetPath) {
        var list = new List<string>();
        var dependencies = AssetDatabase.GetDependencies(assetPath, false);
        foreach (var dependency in dependencies) {
            if (Path.GetExtension(dependency) == ".cs" || Path.GetExtension(dependency) == ".meta" || Path.GetExtension(dependency) == ".DS_Store") {
                continue;
            }
            list.Add(dependency);
        }
        list.Add(assetPath);
        return list;
    }


}

3.需要打包的场景添加到打包配置:

4.unity编辑器生成菜单:

5.场景加载AB包管理器:

using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using UnityEngine.Networking;
using GLTFast;
using LitJson;
using System.Web;

public class SceneLoader : MonoBehaviour {
    
    public int TemplateId;

    public bool useBundle;

    public bool isDeBug;

    public bool isShowCase;

    public bool isMobileTest;

    [Header("天空盒材质球")]
    public UnityEngine.Material skyboxMaterial;

    bool sceneIsLoaded = false;
    [DllImport("__Internal")]
    private static extern string GetUA();

    public virtual void Awake() {

#if !UNITY_EDITOR && UNITY_WEBGL
          string a = GetUA();
          if (a == "1")
            {
                //PC端
                Debug.Log("当前运行环境在PC端");
                PlayerData.Instance.isRunningPC = true;
            }
            if (a == "2")
            {
                //移动端
                Debug.Log("当前运行环境在移动端");
                PlayerData.Instance.isRunningPC = false;
            }
#endif



#if UNITY_EDITOR

        AppConst.UseAssetBundle = useBundle;

#endif

        AppConst.useShowBundlePath = isShowCase;

        DontDestroyOnLoad(gameObject);
        EventManager.Instance.AddListener(EventName.LoadSceneAction, OnSceneLoad);
        EventManager.Instance.AddListener(EventName.OnSceneCfgLoadEnd, RemoveUnuse);



    }

    public virtual void Start() {

        var fps = transform.Find("FPS");
        if (fps) {
            fps.gameObject.SetActive(isDeBug);
        }

        if (isMobileTest) LoadNetCofig();



    }


    void LoadNetCofig() {
        var configPath = Application.dataPath;

#if UNITY_EDITOR
        var filepath = Path.Combine(Application.dataPath.Replace("Assets", ""), "config.txt");
#else
        var filepath = Path.Combine(Application.dataPath, "config.txt");
#endif
        Debug.Log("configPath" + filepath);
        filepath = filepath.Replace("\\", "/");
        StartCoroutine(LoadFileSetNetwork(filepath));
    }

    IEnumerator LoadFileSetNetwork(string filepath) {
        UnityWebRequest www = UnityWebRequest.Get(filepath);


        yield return www.SendWebRequest();


        if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) {
            Debug.LogError(www.error);
        }
        else {
            string json = www.downloadHandler.text;
            var data = LitJson.JsonMapper.ToObject(json);

            if ((string)data["AssetBundleIP"] != string.Empty) {
                Host.AssetBundleIP = (string)data["AssetBundleIP"];
            }
            Host.gameServer = (string)data["local"];
            Host.ApiHost = (string)data["ApiHost"];
            Host.remote = (string)data["remote"];

            Debug.Log("url config:" + json);
            StartCoroutine(tempLoad());

        }
    }

    public IEnumerator tempLoad() {
        Debug.Log("OnBaelogin" + TemplateId);
        var SceneName = TemplateId.ToString();
#if UNITY_EDITOR
        if (AppConst.UseAssetBundle) {
            yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
        }
        else {
            yield return SceneManager.LoadSceneAsync(SceneName);
        }
#else
        yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
#endif

        EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
        UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL); //这里有个坑, 如果把界面放在场景加载之前添加,会出现各种错误乱象
        UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
        Debug.Log("DownLoadScenConfig");
        if (HttpHelper.Instance != null) {
            HttpHelper.Instance.GetDefaultSpaceImg();
            HttpHelper.Instance.DownLoadScenConfig();
        }
    }


    private void RemoveUnuse(object sender, EventArgs e) {
        RemoveSceneUnUseDefault();

        ResetSkyBox();
    }


    public void ResetSkyBox() {
        JsonData sceneJson = JsonMapper.ToObject(SceneModel.Instance.sceneJsonInitData);
        if (sceneJson["skyBox"] != null) {

            string imgdata = sceneJson["skyBox"]["body"].ToString();
            string decodedString = HttpUtility.UrlDecode(JsonMapper.ToObject(imgdata)["imgDatas"].ToString());
            StartCoroutine(LoadTexturesAndGenerateCubemap(JsonMapper.ToObject<List<skyImgData>>(decodedString)));
        }

    }

    private IEnumerator LoadTexturesAndGenerateCubemap(List<skyImgData> skyImgDataList) {
        Texture2D[] textures = new Texture2D[skyImgDataList.Count];
        Cubemap cubemap;

        for (int i = 0; i < skyImgDataList.Count; i++) {
            using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(skyImgDataList[i].url)) {
                yield return www.SendWebRequest();

                if (www.result == UnityWebRequest.Result.Success) {
                    Texture2D texture = DownloadHandlerTexture.GetContent(www);
                    textures[i] = texture;
                }
                else {
                    Debug.LogError("Failed to load image: " + www.error);
                    yield break;
                }
            }
        }

        Material material = new Material(skyboxMaterial);

        material.SetTexture("_FrontTex", textures[0]);
        material.SetTexture("_BackTex", textures[1]);
        material.SetTexture("_LeftTex", textures[2]);
        material.SetTexture("_RightTex", textures[3]);
        material.SetTexture("_UpTex", textures[4]);
        material.SetTexture("_DownTex", textures[5]);

        RenderSettings.skybox = material;

    }



    /// <summary>
    /// 移除场景默认设置的那些被删除的板
    /// </summary>
    public void RemoveSceneUnUseDefault() {
        var comVOs = SceneModel.Instance.rootCfg.comCfg.comVOs;
        var scene = SceneManager.GetActiveScene();
        GameObject[] roots = scene.GetRootGameObjects();
        foreach (GameObject root in roots) {
            var loaders = root.GetComponentsInChildren<ComLoader>();
            foreach (var loader in loaders) {
                if (comVOs.TryGetValue(loader.instanceName, out _) == false) {
                    StartCoroutine(waitSeconds(loader.gameObject));
                }
            }
        }
    }

    IEnumerator waitSeconds(GameObject go) {
        yield return new WaitForEndOfFrame();
        GameObject.Destroy(go);
    }






    IEnumerator coLoadSceneAsync() {

        if (PlayerData.Instance.isRunningPC == false) {
            yield return new WaitForSeconds(1f);
        }

#if UNITY_EDITOR
        if (SceneModel.Instance.useGlb == false) {
            PlayerData.Instance.TemplateId = TemplateId;
        }
#endif
        var SceneName = "";

        if (SceneModel.Instance.useGlb == true) {
            SceneName = "1000";
        }
        else {
            if (PlayerData.Instance.isRunningPC) {
                SceneName = PlayerData.Instance.TemplateId.ToString();
            }
            else {
                SceneName = PlayerData.Instance.TemplateId.ToString() + "_mobile";
            }
        }

        Debug.Log("SceneName TemplateId:" + SceneName);
#if UNITY_EDITOR
        if (AppConst.UseAssetBundle) {
            yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
        }
        else {
            yield return SceneManager.LoadSceneAsync(SceneName);
        }

#else
        yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
#endif

    }

    /// <summary>
    /// 发布态场景加载完成
    /// </summary>
    /// <param name="arg0"></param>
    /// <param name="arg1"></param>
    private void OnPublishModeSceneLoadSuccess(Scene arg0, LoadSceneMode arg1) {
        UIManager.Instance.PushPanel(UIPanelType.EDITOR_MODE_PANEL);
        UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
        EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
        HttpHelper.Instance.GetDefaultSpaceImg();
        SceneModel.Instance.setDefaultSceneConfig();

        if (PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>()) {
            PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>().publicModeForName();
            PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>().isShowOwnerObj(true);
        }

        if (SceneModel.Instance.useGlb) {
            EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
        }
    }

    public void OnSceneLoad(object sender, EventArgs e) {

        if (sceneIsLoaded == true) {
            return;
        }
        sceneIsLoaded = true;
        var arg = e as SceneLoadActionArgs;
        Debug.Log("OnSceneLoad:" + arg.state);
        if (arg.state == AppConst.PublicMode) //创建态
        {
            SceneManager.sceneLoaded += OnPublishModeSceneLoadSuccess;
        }
        else { //浏览态

            SceneManager.sceneLoaded += OnViewSceneLoadOk;
        }
        StartCoroutine(coLoadSceneAsync());
    }



    /// <summary>
    /// 浏览态场景加载完成
    /// </summary>
    /// <param name="arg0"></param>
    /// <param name="arg1"></param>
    private void OnViewSceneLoadOk(Scene arg0, LoadSceneMode arg1) {
        EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
        if (PlayerData.Instance.isRunningPC == true) {
            UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
        }
        //ToastPanel.Show("OnViewSceneLoadOk");
        //AlertPanel.Show("OnViewSceneLoadOk", null);
        //Debug.Log("DownLoadScenConfig");
        //if (HttpHelper.Instance != null)
        //{
        //    HttpHelper.Instance.GetDefaultSpaceImg();
        //    //HttpHelper.Instance.DownLoadScenConfig(); //挪到登陆的时候请求场景数据
        //}


        if (SceneModel.Instance.useGlb) {
            EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
        }


        if (PlayerData.Instance.isRunningPC) {
            SceneModel.Instance.ImplementComLoder();
            UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);

        }
        else {
            if (SceneModel.Instance.useGlb) {

                EventManager.Instance.AddListener(EventName.onGlbSceneLoadOK, (s, e) => {

                    StartCoroutine(waitSeconds(1, () => {
                        UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
                    }));

                });

                StartCoroutine(waitSeconds(1, () => {

                    if (SceneModel.Instance.useGlb) {
                        EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
                    }
                }));
            }
            else {

                StartCoroutine(waitSeconds(1, () => {
                    UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
                }));

            }


        }
    }

    private IEnumerator waitSeconds(float scecond, Action call) {
        yield return new WaitForSeconds(scecond);
        call();


    }

    public virtual void Onlogin() {



    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1371630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python从入门到网络爬虫(OS模块详解)

前言 本章介绍python自带模块os&#xff0c;os为操作系统 operating system 的简写&#xff0c;意为python与电脑的交互。os 模块提供了非常丰富的方法用来处理文件和目录。通过使用 os 模块&#xff0c;一方面可以方便地与操作系统进行交互&#xff0c;另一方面页可以极大增强…

C语言如何提高程序的可读性?

一、问题 可读性是评价程序质量的一个重要标准&#xff0c;直接影响到程序的修改和后期维护&#xff0c;那么如何提高程序的可读性呢? 二、解答 提高程序可读性可以从以下几方面来进行。 &#xff08;1&#xff09;C程序整体由函数构成的。 程序中&#xff0c;main()就是其中…

Maven依赖冲突解决

Maven介绍 Maven 是 Apache 软件基金会唯一维护的一款自动化构建工具&#xff0c;专注于服务Java平台的项目构建和依赖管理。 1.Maven是如何寻找依赖的? 首先会去本地仓库寻找&#xff0c;然后会去公司的私服仓库寻找&#xff0c;一般私服仓库存的都是公司自己开发的 jar 包&…

蚁群算法解决旅行商问题的完整Python实现

蚁群算法&#xff08;Ant Colony Optimization&#xff0c;简称ACO&#xff09;是一种模拟蚂蚁觅食行为的启发式优化算法。它通过模拟蚂蚁在寻找食物时释放信息素的行为&#xff0c;来解决组合优化问题&#xff0c;特别是旅行商问题&#xff08;TSP&#xff09;。 蚁群算法的基…

RAG:让大语言模型拥有特定的专属知识

作为一个在Chatbot领域摸爬滚打了7年的从业者&#xff0c;笔者可以诚实地说&#xff0c;在大语言模型的推动下&#xff0c;检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09;技术正在快速崛起。 RAG的搜索请求和生成式AI技术&#xff0c;为搜…

【数据库原理】期末突击(2)

有不会的题可以后台问我的哦&#xff0c;看见了就会回。祝大家期末心想事成。 数据库大题显而易见就只有几类&#xff0c;大家可以根据老师平时讲解的例题对应去解决一类型的题目。 前提知识; 候选码候选键关键字键码 关系代数&#xff1a;&#xff08;1&#xff09;传统&…

echarts使用之柱状图

一、引入Echarts npm install eacharts --save 二、选择一个Echarts图 选择创建一个柱状图 option { // x轴参数的基本配置xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun] //X轴数据}, // y轴参数的基本配置yAxis: {type: value}, // series:[{data: …

MySQL连接池、C3P0、Druid德鲁伊连接池技术

MySQL连接池 连接池C3P0Druid 连接池 概念&#xff1a;其实就是一个容器(集合)&#xff0c;存放数据库连接的容器。当系统初始化好后&#xff0c;容器被创建&#xff0c;容器中会申请一些连接对象&#xff0c;当用户来访问数据库时&#xff0c;从容器中获取连接对象&#xff0…

怎么样检查自己系统上的Python环境中是否有某个包(扩展库)?

比如我们这里想看下有没有库pytz 很简单&#xff0c;进入Python的命令行&#xff0c;然后输入下面的命令&#xff1a; import pytz如果有这个库&#xff0c;则不会报错&#xff0c;否则会报错。 Windows的测试结果如下&#xff1a; Centos的测试结果如下&#xff1a;

Linux中vim查看文件某内容

一、编辑文件命令 [rootyinheqilin ~]# vim test.txt 1&#xff0c;在编辑的文件中连续按2次键盘的【g】键&#xff0c;光标会移动到文档开头第一行 2&#xff0c;输入一个大写 G&#xff0c;光标会跳转到文件的最后一行第一列&#xff08;末行) 二、查看文件内容命令 gre…

改善制造业客户体验的实用技巧与策略

制造业是一个关键行业&#xff0c;在经济中发挥着至关重要的作用。它负责为我们的日常生活生产必需品和服务。然而近年来&#xff0c;该行业发生了重大变化&#xff0c;企业现在面临着日益激烈的竞争和满足消费者需求的压力。为了保持竞争力&#xff0c;制造商必须专注于打造更…

算法通关村番外篇-LeetCode编程从0到1系列二

大家好我是苏麟 , 今天来说LeetCode编程从0到1系列二 . 内置函数 最后一个单词的长度 描述 : 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子…

PHP大型企业人才招聘网站源码带文字安装教程

PHP大型企业人才招聘网站源码带文字安装教程 运行环境 服务器宝塔面板 PHP 5.6 Mysql 5.5及以上版本 Linux Centos7以上 功能说明&#xff1a; 会员模块包括企业管理、职位管理、名企管理、企业认证审核、 企业设置。内容模块包括新闻管理、新闻类别、新闻属性、添加新闻。 运营…

海外云手机:一机多用,引领跨境电商新潮流

如今&#xff0c;跨境卖家除了经营跨境平台外&#xff0c;还需抓住短视频和社交媒体的机遇。在社交媒体上实现引流&#xff0c;将流量导向自己的跨境平台或独立站&#xff0c;吸引用户购买&#xff0c;完成流量变现&#xff0c;已成为跨境电商的一项关键策略。本文将介绍如何用…

获取深层次字段报错TypeError: Cannot read properties of undefined (reading ‘title‘)

动态生成菜单时报错,不能多层获取路由meta下面的title字段 <template><p>{{ meneList }}</p><template v-for"item in meneList" :key"item.path"><el-menu-item v-if"!item.children"><template #title>{…

【Tomcat】在一台计算机上运行两个Tomcat服务

首先把Tomcat整个文件复制一份放在其他文件夹路径中 1.修改环境变量 添加环境变量在系统变量里面 “CATALINA_HOME” 指向一个Tomcat文件夹路径 “CATALINA_HOME1” 指另一个Tomcat文件夹路径 2.修改startup里面的环境变量&#xff0c;全部修改 分别修改两个apache-tomcat…

教你用SadTalker一键整合包轻松制作专属数字人

数字人的效果&#xff1a; &#x1f3b5;我用SadTalker制作了专属虚拟数字人&#xff0c;还会唱歌哦&#xff0c;多多点赞关注就出教程呦&#x1f497; SadTalker有独立离线版Ai数字人&#xff0c;也可以在Stable Diffusion以插件的形式使用&#xff0c;但是如果显卡小的话还是…

水经微图安卓版APP正式上线!

在水经微图APP&#xff08;简称“微图APP”&#xff09;安卓版已正式上线&#xff01; 在随着IOS版上线约一周之后&#xff0c;安卓版终于紧随其后发布了。 微图安卓版APP下载安装 自从IOS版发布之后&#xff0c;就有用户一直在问安卓版什么时候发布&#xff0c;这里非常感谢…

PHP Web应用程序中常见漏洞

一淘模板&#xff08;56admin.com)发现PHP 是一种流行的服务器端脚本语言&#xff0c;用于开发动态 Web 应用程序。但是&#xff0c;与任何其他软件一样&#xff0c;PHP Web 应用程序也可能遭受安全攻击。 在本文中&#xff0c;我们将讨论 PHP Web 应用程序中一些最常见的漏洞…

计算机网络——应用层(2)

计算机网络——应用层&#xff08;2&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) Web和HTTP概念解读HTTPHTTP请求和响应包含内容常见的请求方法Web缓存优点缺点 总结 DNS提供的服务 小程一言 我的计算机网络专栏&#xff0c;是自己在计算机网络学习过程…