《学Unity的猫》——第十三章:Unity使用Animator控制动画播放,皮皮猫打字机游戏

本文主要是介绍《学Unity的猫》——第十三章:Unity使用Animator控制动画播放,皮皮猫打字机游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

        • 13.1 皮皮猫打字机游戏
        • 13.2 场景制作
          • 13.2.1 入口场景
          • 13.2.2 游戏场景
          • 13.2.3 场景切换
        • 13.3 游戏管理器
          • 13.3.1 数据定义
          • 13.3.2 生成字母盘
          • 13.3.3 按键判断
          • 13.3.4 连击定时器
        • 13.4 动画控制器Animator
          • 13.4.1 添加Animator
          • 13.4.2 Animator状态机
            • 13.4.2.1 Any State状态
            • 13.4.2.2 Entry状态
            • 13.4.2.3 Exit状态
          • 13.4.3 动画状态的属性
          • 13.4.4 状态间的过渡关系(Transitions)
          • 13.4.5 添加状态控制参数
          • 13.4.6 编辑切换状态的条件
        • 13.5 猫娘动画状态机
          • 13.5.1 模型资源下载
          • 13.5.2 动画循环设置
          • 13.5.3 状态过渡设置
        • 13.6 角色动画控制器
          • 13.6.1 数据定义
          • 13.6.2 直接播放动画接口
          • 13.6.3 设置变量值
          • 13.6.4 根据状态队列设置状态
        • 13.7 入口场景脚本
        • 13.8 游戏场景脚本
        • 13.9 文字特效动画

简介:我是一名Unity游戏开发工程师,皮皮是我养的猫,会讲人话,它接到了喵星的特殊任务:学习编程,学习Unity游戏开发。
于是,发生了一系列有趣的故事。
在这里插入图片描述

13.1 皮皮猫打字机游戏

皮皮:“铲屎官,你为什么打字速度这么快?”
我:“一个字,练。”
皮皮:“教教我,怎么连打字速度。”
我:“来,我给你做一个打字练习游戏吧。”
我:“当你可以一分钟连击180次的时候,你就可以出山了。”
皮皮:“作为猫族,不能被速度打败。”
游戏画面如下:
在这里插入图片描述
模块设计如下
在这里插入图片描述

本工程使用的Unity版本为2020.1.14f1c1 (64-bit),工程已上传到GitHub,感兴趣的同学可以下载下来学习。
GitHub地址:https://github.com/linxinfa/Unity-TypeWriting-Game
在这里插入图片描述

13.2 场景制作
13.2.1 入口场景

EntryScene.unity
在这里插入图片描述
在这里插入图片描述
一个标题文本(Text组件),一个开始按钮(Button组件),一个难度选择勾选(ToggleGroupToggle组件)。
背景图使用SpriteRender组件在3D摄像机中渲染。
在这里插入图片描述
难度等级的勾选使用了ToggleGroup组件,用来给Toggle分组。
在这里插入图片描述
子节点中的Toggle需要指明相同的ToggleGroup
在这里插入图片描述
实现单选的效果。
在这里插入图片描述

13.2.2 游戏场景

GameScene.unity
在这里插入图片描述
在这里插入图片描述
一个血条(Slider组件),一个得分(Text组件),一个字母盘(GridLayoutGroupText组件)、一个连击(Text组件),一个角色(SpriteRendererAnimator组件)、一个背景图(SpriteRenderer组件)。
其中字母盘只做一个字母,游戏中进行动态克隆。
在这里插入图片描述
再做游戏结束面板,提供一个返回和重来的按钮。
在这里插入图片描述

13.2.3 场景切换

点击菜单File - Build Settings...
在这里插入图片描述
将场景添加到Scenes In Build中。
在这里插入图片描述
代码中,通过SceneManager.LoadScene切换场景,如下

// 进入GameScene场景
UnityEngine.SceneManagement.SceneManager.LoadScene(1);
13.3 游戏管理器

游戏管理器GameMgr,它需要包括数据和逻辑,如下。
在这里插入图片描述

13.3.1 数据定义
	/// <summary>/// 难度等级/// </summary>public int hardLevel { get; set; }/// <summary>/// 得分/// </summary>public int score { get; set; }/// <summary>/// 最大血量/// </summary>private const int MAX_BLOOD = 1500;/// <summary>/// 血量/// </summary>public int blood{get { return m_blood; }set{m_blood = value;if (m_blood <= 0){gameOver = true;// TODO 抛出事件}}}private int m_blood = 0;/// <summary>/// 连击数量/// </summary>public int comboCnt { get; set; }/// <summary>/// 连击定时器/// </summary>public float comboTimer { get; set; }/// <summary>/// 游戏结束/// </summary>public bool gameOver { get; private set; }/// <summary>/// 按键列表/// </summary>public List<KeyCode> keyList { get { return m_keyList; } }private List<KeyCode> m_keyList = new List<KeyCode>();
13.3.2 生成字母盘

生成字母盘(16个字母),要求每个字母都不重复,生成的字母存到m_keyList中。
在这里插入图片描述

 	/// <summary>/// 生成字母盘/// </summary>private void GenKeys(){for (int i = 0; i < 16; ++i){m_keyList.Add(GenOneKey());}}/// <summary>/// 生成一个字母/// </summary>/// <returns></returns>private KeyCode GenOneKey(){var key = (KeyCode)UnityEngine.Random.Range((int)KeyCode.A, (int)KeyCode.Z);for(int i=0,cnt=m_keyList.Count;i<cnt;++i){if(m_keyList[i] == key){// 如果生成的字母已存在,则递归生成return GenOneKey();}}return key;}
13.3.3 按键判断

我们需要先判断按键类型,封装一个接口GetKeyDownCode

    /// <summary>/// 获取按键类型/// </summary>/// <returns></returns>public KeyCode GetKeyDownCode(){if (Input.anyKeyDown){foreach (KeyCode keyCode in Enum.GetValues(typeof(KeyCode))){if (Input.GetKeyDown(keyCode)){return keyCode;}}}return KeyCode.None;}

然后判断按下的按键是否在字母盘中,返回对应的索引,如果不在字母盘中,则返回-1。

    /// <summary>/// 判断按键是否在字母盘中/// </summary>/// <param name="key">按键</param>/// <returns></returns>private int IsKeyBingo(KeyCode key){for (int i = 0, cnt = m_keyList.Count; i < cnt; ++i){if (m_keyList[i] == key)return i;}return -1;}

按键正确的时候,执行连击计算,加血加分,生成新的字母,抛事件更新ui

    /// <summary>/// 按键正确/// </summary>private void OnKeyBingo(int bingoIndex){// 加连击++comboCnt;if (comboCnt >= 3){// 加血加分,连击加持blood += 150;if (blood > MAX_BLOOD)blood = MAX_BLOOD;score += 20;}else{// 加血加分blood += 50;score += 10;}// 生成新的字母var oldKey = m_keyList[bingoIndex];var newKey = GenOneKey();m_keyList[bingoIndex] = newKey;// TODO 抛事件,更新ui}

按键错误的时候,连击中断,扣血,抛事件更新ui

    /// <summary>/// 按键错误/// </summary>private void OnKeyError(){// 连击中断comboCnt = 0;// 扣血blood -= 30;// TODO 抛事件,更新ui}
13.3.4 连击定时器

如下,其中Time.deltaTime是一帧的间隔时间。每帧调用UpdateComboTimer,对comboTimer进行帧间隔时间递减,通过comboTimer判断是否超过时间限制,超过则中断连击。

    /// <summary>/// 连击定时器/// </summary>public void UpdateComboTimer(){if (comboTimer > 0){comboTimer -= Time.deltaTime;// 超过时间限制,连击断开if (comboTimer <= 0){comboCnt = 0;// TODO 抛事件更新连击ui}}}
13.4 动画控制器Animator

Unity可以用两种方式控制动画
1 Animation,这种方式简单,直接 Play(“Idle”)或者CorssFade(“Idle”)就可以播放动画;
2 AnimatorUnity5.x之后推荐使用这种方式,因为里面可以加上混合动画,让动画切换更加平滑。

13.4.1 添加Animator

点击菜单Window - Animation - Animation,可以打开Animation窗口,快捷键是Ctrl+6
在这里插入图片描述
选中某个物体后,可以为该物体添加或编辑动画,比如选中一个空物体,由于没有动画,会出现一个Create按钮。在这里插入图片描述
点击Create按钮,会弹出窗口设置文件保存路劲。
在这里插入图片描述
创建成功后,物体上会出现一个Animator组件。
在这里插入图片描述

并且我们可以在目录中看到生成了两个文件。
在这里插入图片描述
.controller文件是一个动画状态机,在Unity中双击它会打开Animator窗口,即可看到里面的内容,我们可以在这个窗口中组织各个动画文件。
在这里插入图片描述
.anim是动画文件,在Unity中双击它会打开Animation窗口,我们可以在这个窗口中制作动画。
在这里插入图片描述

13.4.2 Animator状态机

每个Animator Controller都会自带三个状态:Any State, EntryExit
在这里插入图片描述

13.4.2.1 Any State状态

表示任意状态的特殊状态。例如我们如果希望角色在任何状态下都有可能切换到死亡状态,那么Any State就可以帮我们做到。当你发现某个状态可以从任何状态以相同的条件跳转到时,那么你就可以用Any State来简化过渡关系。

13.4.2.2 Entry状态

表示状态机的入口状态。当我们为某个GameObject添加上Animator组件时,这个组件就会开始发挥它的作用。
如果Animator Controller控制多个Animation的播放,那么默认情况下Animator组件会播放哪个动画呢? 由Entry来决定的。
但是Entry本身并不包含动画,而是指向某个带有动画的状态,并设置其为默认状态。被设置为默认状态的状态会显示为 橘黄色。
在这里插入图片描述
当然,你可以随时在任意一个状态上通过 鼠标右键->Set as Layer Default State更改默认状态。
在这里插入图片描述

记住, EntryAnimator组件被激活后 无条件 跳转到默认状态,并且每个Layer有且仅有一个默认状态。

13.4.2.3 Exit状态

表示状态机的出口状态,以红色标识。如果你的动画控制器只有一层,那么这个状态可能并没有什么卵用。但是当你需要从子状态机中返回到上一层(Layer)时,把状态指向Exit就可以了。
在这里插入图片描述

13.4.3 动画状态的属性

我们可以选中某个自定义状态,并在Inspector窗口下观察它具有的属性
在这里插入图片描述

属性名描述
Motion状态对应的动画。每个状态的基本属性,直接选择已定义好的动画(Animation Clip)即可
Speed动画播放的速度。默认值为1,表示速度为原动画的1.0倍。
Mutiplier勾选右侧的Parameter后可用,即在计算Speed的时考虑 区域1 中定义的某个参数。若选择的参数为smooth, 则动画播放速度的计算公式为 smooth * speed * fps(animation clip中指定)
Mirror仅适用于humanoid animation(人型机动画)
Cycle Offset周期偏移,取值范围为0-1.0,用于控制动画起始的偏移量。把它和正弦函数的offset进行对比就能够理解了,只会影响起始动画的播放位置。
Foot IK仅适用于humanoid animation(人型机动画)
Write Default最好保持默认,感兴趣可以参考官方手册
Transitions该状态向其他状态发起的过渡列表,包含了Solo和Mute两个参数,在预览状态机的效果时起作用
Add Behaviour用于向状态添加“行为
13.4.4 状态间的过渡关系(Transitions)

状态间的过渡关系,直观上说它们就是连接不同状态的有向箭头。

在这里插入图片描述
要创建一个从状态A状态B的过渡,直接在状态A上 鼠标右键 - Make Transition并把出现的箭头拖拽到状态B上点击鼠标左边即可。
在这里插入图片描述

13.4.5 添加状态控制参数

参数有FloatIntBoolTrigger
在这里插入图片描述
FloatInt用来控制一个动画状态的参数,比如速度方向等可以用数值量化的东西,
Bool用来控制动画状态的转变,比如从走路转变到跑步,
Trigger本质上也是bool类型,但它默认为false,且当程序设置为true后,它会自动变回false

如下这里创建一个Int类型的参数AnimState
在这里插入图片描述

13.4.6 编辑切换状态的条件

点击连线,在Inspecter窗口中可以进行设置,在Conditions栏下可以添加条件,如下图表示当参数
AnimState0时会执行这个动画Any StateNew Animation2的过渡

必须在Parameters面板中添加了参数才可以在这里查看到,其次添加的条件为&& ”与” 关系,即必须同时满足。

在这里插入图片描述

13.5 猫娘动画状态机
13.5.1 模型资源下载

Assets Store上下载猫娘模型,资源地址:https://assetstore.unity.com/packages/2d/characters/fancydoll-c000-little-cat-girl-112776
在这里插入图片描述

13.5.2 动画循环设置

模型自带了一些动画
在这里插入图片描述
idle(站立)、walk(走路)、run(跑)需要循环播放,勾选Loop Time
在这里插入图片描述
get_hit(受击)、die(阵亡)不需要循环播放,不勾选Loop Time
在这里插入图片描述

13.5.3 状态过渡设置

我们需要通过Animator将这些动画进行合理的组织,如下
在这里插入图片描述
添加变量Action,过渡条件根据Action的值进行判断。
在这里插入图片描述
过渡条件如下

状态1状态2条件
Any StateidleAction == 1
Any Stateget_hitAction == 4
get_hitidle
Any StatedieAction == 5
13.6 角色动画控制器

角色动画控制器CharacterAniCtrler,它需要包括数据和逻辑,如下。
在这里插入图片描述
运行中的状态过渡
在这里插入图片描述

13.6.1 数据定义
	/// <summary>/// 状态定义,默认为Idle状态。/// </summary>public enum CharacterAniId{Idle = 1,Walk = 2,Run = 3,Hit = 4,Death = 5,}/// <summary>/// 角色动画Animator组件/// </summary>private Animator m_animator;/// <summary>/// 动画队列/// </summary>private Queue<int> m_animQueue = new Queue<int>();
13.6.2 直接播放动画接口
    /// <summary>/// 立即播放某个动画/// </summary>/// <param name="name">动画名称</param>private void PlayAniImmediately(string name){if (IsDeath) return;m_animator.CrossFade(name, 0.1f, 0);}

如立即播放走路动画

    public void PlayWalk(){PlayAniImmediately("walk");}
13.6.3 设置变量值
// 设置Action变量值为4m_animator.SetInteger("Action", 4);

封装成接口

	private const string STR_ACTION = "Action";/// <summary>/// 播放不同动作ID/// </summary>/// <param name="isJump"></param>/// public void PlayAnimation(int actionID){if (IsDeath) return;if (m_animator == null)return;if (!m_animator.isInitialized || m_animator.IsInTransition(0)){// 如果正在过渡,则先塞到队列中m_animQueue.Enqueue(actionID);return;}m_animator.SetInteger(STR_ACTION, actionID);}
13.6.4 根据状态队列设置状态

提供一个LateUpdate接口每帧调用,设置了Action值需要在下一帧的时候重置为0,然后从队列中取下一个状态进行处理。

    /// <summary>/// 每帧调用/// </summary>public void LateUpdate(){if (m_animator == null){return;}if (!m_animator.isInitialized || m_animator.IsInTransition(0)){return;}if (null == mClips)mClips = m_animator.GetCurrentAnimatorClipInfo(0);if (null == mClips || mClips.Length == 0)return;int actionID = m_animator.GetInteger(STR_ACTION);if (actionID > 0){//将Action复位m_animator.SetInteger(STR_ACTION, 0);}//将剩余队列的动作重新拿出来播放PlayRemainAction();}/// <summary>/// 将剩余队列的动作重新拿出来播放/// </summary>void PlayRemainAction(){if (m_animQueue.Count > 0){PlayAnimation(m_animQueue.Dequeue());}}
13.7 入口场景脚本

入口场景脚本EntryScene.cs挂在Canvas上,设置Start Game BtnTgl Group
在这里插入图片描述
代码如下

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;public class EntryScene : MonoBehaviour
{public Button startGameBtn;public ToggleGroup tglGroup;void Start(){startGameBtn.onClick.AddListener(() =>{// 根据勾选,缓存难度等级foreach (var item in tglGroup.ActiveToggles()){GameMgr.Instance.hardLevel = int.Parse(item.name);break;}// 进入Game场景SceneManager.LoadScene(1);});}
}
13.8 游戏场景脚本

游戏场景脚本GameScene.cs挂在Canvas上,设置公开的成员对象。
在这里插入图片描述
主要根据各种事件更新ui

using System;
using UnityEngine;
using UnityEngine.UI;public class GameScene : MonoBehaviour
{public Animator anitor;public Text comboText;public Text scoreText;public Slider bloodSlider;public Image bloodImage;public GameOverDlg gameOverDlg;public KeyGrid keyGrid;private CharacterAniCtrler m_aniCtrler;private void Awake(){// 注册事件EventDispatcher.Instance.Regist(EventNameDef.EVENT_KEY_BINGO_INDEX, OnEventKeyBingoIndex);EventDispatcher.Instance.Regist(EventNameDef.EVENT_COMBO, OnEventCombo);EventDispatcher.Instance.Regist(EventNameDef.EVENT_PLAY_ANI, OnEventPlayAni);EventDispatcher.Instance.Regist(EventNameDef.EVENT_UPDATE_SCORE, OnEventUpdateScore);EventDispatcher.Instance.Regist(EventNameDef.EVENT_RESTART_GAME, OnEventRestartGame);EventDispatcher.Instance.Regist(EventNameDef.EVENT_GAMEOVER, OnEventGameOver);m_aniCtrler = new CharacterAniCtrler();m_aniCtrler.Init(anitor);// 开始游戏StartGame();}private void OnDestroy(){// 注销事件EventDispatcher.Instance.UnRegist(EventNameDef.EVENT_KEY_BINGO_INDEX, OnEventKeyBingoIndex);EventDispatcher.Instance.UnRegist(EventNameDef.EVENT_COMBO, OnEventCombo);EventDispatcher.Instance.UnRegist(EventNameDef.EVENT_PLAY_ANI, OnEventPlayAni);EventDispatcher.Instance.UnRegist(EventNameDef.EVENT_UPDATE_SCORE, OnEventUpdateScore);EventDispatcher.Instance.UnRegist(EventNameDef.EVENT_RESTART_GAME, OnEventRestartGame);EventDispatcher.Instance.UnRegist(EventNameDef.EVENT_GAMEOVER, OnEventGameOver);}/// <summary>/// 开始游戏/// </summary>private void StartGame(){GameMgr.Instance.Init();TextEffect.Init();// 初始化血量bloodSlider.maxValue = GameMgr.Instance.blood;bloodSlider.value = GameMgr.Instance.blood;bloodImage.enabled = true;// 生成字母盘keyGrid.CreateKeyList(GameMgr.Instance.keyList);comboText.gameObject.SetActive(false);scoreText.text = "0";gameOverDlg.Hide();}void Update(){if (GameMgr.Instance.gameOver) return;// 更新连击定时器GameMgr.Instance.UpdateComboTimer();// 更新血量uibloodSlider.value = GameMgr.Instance.blood;GameMgr.Instance.blood -= GameMgr.Instance.hardLevel;// 按键判断var keyCode = GameMgr.Instance.GetKeyDownCode();if (KeyCode.None == keyCode) return;GameMgr.Instance.OnKey(keyCode);}private void LateUpdate(){// 更新动画控制器m_aniCtrler.LateUpdate();}/// <summary>/// 按键正确事件/// </summary>/// <param name="args"></param>private void OnEventKeyBingoIndex(params object[] args){int index = (int)args[0];KeyCode oldKey = (KeyCode)args[1];KeyCode newKey = (KeyCode)args[2];keyGrid.UpdateKeyByIndex(index, oldKey, newKey);}/// <summary>/// 连击事件/// </summary>/// <param name="args"></param>private void OnEventCombo(params object[] args){var combo = (int)args[0];comboText.text = "连击" + combo;comboText.gameObject.SetActive(combo >= 3);}/// <summary>/// 播放动画事件/// </summary>/// <param name="args"></param>private void OnEventPlayAni(params object[] args){var ani = (string)args[0];switch (ani){case "idle": m_aniCtrler.PlayAnimation((int)CharacterAniId.Idle); break;case "walk": GameMgr.Instance.comboTimer = 0.5f; m_aniCtrler.PlayWalk(); break;case "run": GameMgr.Instance.comboTimer = 0.5f; m_aniCtrler.PlayRun(); break;case "hit": m_aniCtrler.PlayAnimation((int)CharacterAniId.Hit); break;case "die": m_aniCtrler.PlayDieImmediately(); break;}}/// <summary>/// 更新得分事件/// </summary>/// <param name="args"></param>private void OnEventUpdateScore(params object[] args){var score = (int)args[0];scoreText.text = score.ToString();}/// <summary>/// 游戏结束事件/// </summary>/// <param name="args"></param>private void OnEventGameOver(params object[] args){bloodImage.enabled = false;gameOverDlg.Show(GameMgr.Instance.score);}/// <summary>/// 重新开始游戏事件/// </summary>/// <param name="args"></param>private void OnEventRestartGame(params object[] args){m_aniCtrler.PlayReviveImmediately();StartGame();}
}

其中事件定义如下

/// <summary>
/// 事件定义
/// </summary>
public class EventNameDef 
{/// <summary>/// 按键正确事件/// </summary>public const string EVENT_KEY_BINGO_INDEX = "EVENT_KEY_BINGO_INDEX";/// <summary>/// 连击事件/// </summary>public const string EVENT_COMBO = "EVENT_COMBO";/// <summary>/// 播放动画事件/// </summary>public const string EVENT_PLAY_ANI = "EVENT_PLAY_ANI";/// <summary>/// 游戏结束事件/// </summary>public const string EVENT_GAMEOVER = "EVENT_GAMEOVER";/// <summary>/// 更新得分事件/// </summary>public const string EVENT_UPDATE_SCORE = "EVENT_UPDATE_SCORE";/// <summary>/// 重新开始游戏事件/// </summary>public const string EVENT_RESTART_GAME = "EVENT_RESTART_GAME";
}
13.9 文字特效动画

在这里插入图片描述
制作一个TextEffect.prefab预设,添加动画如下。
在这里插入图片描述
由于游戏中需要重复显示这个特效,所以采用对象池方式。
特效动画结束时回收到对象池中,这样可以反复利用。为了监听动画结束,在动画的最后一帧添加帧事件。
在这里插入图片描述
创建一个TextEffect.cs脚本,挂到预设上,提供一个OnAnimationEnd共有方法

public void OnAnimationEnd()

这样就可以设置帧事件的响应函数了
在这里插入图片描述
TextEffect.cs脚本如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 文本特效
/// </summary>
public class TextEffect : MonoBehaviour
{/// <summary>/// 初始化/// </summary>public static void Init(){if(null != s_root){Destroy(s_root.gameObject);s_root = null;}s_objPool.Clear();var canvas = GameObject.Find("Canvas");if (null != canvas){var rootObj = new GameObject("EffectRoot");s_root = rootObj.transform;s_root.SetParent(canvas.transform, false);}}/// <summary>/// 显示特效/// </summary>/// <param name="text"></param>/// <param name="pos"></param>public static void Show(string text, Vector3 pos){if (null == s_prefab){s_prefab = Resources.Load<GameObject>("TextEffect");}TextEffect bhv = null;if (s_objPool.Count > 0){// 从对象池中取对象,bhv = s_objPool.Dequeue();}else{var obj = Instantiate(s_prefab);obj.transform.SetParent(s_root, false);bhv = obj.GetComponent<TextEffect>();}bhv.gameObject.SetActive(true);bhv.transform.position = pos;bhv.keyText.text = text;}/// <summary>/// 动画结束事件的响应函数/// </summary>public void OnAnimationEnd(){gameObject.SetActive(false);// 对象回收s_objPool.Enqueue(this);}private static GameObject s_prefab;/// <summary>/// 对象池/// </summary>private static Queue<TextEffect> s_objPool = new Queue<TextEffect>();/// <summary>/// 根节点/// </summary>private static Transform s_root;/// <summary>/// 文字组件/// </summary>public Text keyText;
}

完成。
如果有什么疑问,欢迎留言或私信。


《学Unity的猫》——第十四章:Unity实现文件上传下载,支持续传,猫后爪的秘密

这篇关于《学Unity的猫》——第十三章:Unity使用Animator控制动画播放,皮皮猫打字机游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/446616

相关文章

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意