【制作100个unity游戏之26】unity2d横版卷轴动作类游13(附带项目源码)
最终效果
系列导航
文章目录
- 最终效果
- 系列导航
- 前言
- 存储点
- 灯光
- 后处理
- 存储位置信息
- 存储更多数据
- 存储场景信息
- 持久化存储数据
- 引入Unity 的可序列化字典类
- 调用
- 游戏结束
- 源码
- 完结
前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第26篇中,我们将探索如何用unity制作一个unity2d横版卷轴动作类游戏,我会附带项目源码,以便你更好理解它。
本节主要实现灯光 后处理 存储和持久化存储
存储点
存储点的实现和宝箱类似
新增SavePoint
public class SavePoint : MonoBehaviour, IInteractable {private SpriteRenderer spriteRenderer;public Sprite darkSprite;public Sprite lightSprite;public bool isDone;private void Awake() {spriteRenderer = GetComponent<SpriteRenderer>(); }private void OnEnable() {spriteRenderer.sprite = isDone ? lightSprite : darkSprite;}public void TriggerAction(){if(!isDone){spriteRenderer.sprite = lightSprite;GetComponent<Collider2D>().enabled = false;isDone = true;Save();}}//存储数据private void Save(){Debug.Log("存储数据");}
}
配置
效果
灯光
具体可以查看文章:【实现100个unity特效之6】Unity2d光源的使用
调低全局灯光
石头添加点灯光
效果
后处理
后处理效果,我之前也做过不少,感兴趣的可以回头去看看
【用unity实现100个游戏之14】Unity2d做一个建造与防御类rts游戏
unity实战】3D水系统,游泳,潜水,钓鱼功能实现
为了方便测试,记得勾选显示后处理效果,默认都是勾选的
主相机勾选渲染后处理
添加一些简单的后处理效果
实现上面区域比下面区域亮
效果
存储位置信息
新增Data
public class Data
{/// <summary>/// 存储角色位置信息的字典,键为角色名称,值为对应的位置坐标(Vector3)。/// </summary>public Dictionary<string, Vector3> characterPosDict = new Dictionary<string, Vector3>();
}
新增DataManager,为了保证Data Manager可以优先其他代码执行,为它添加特性[DefaultExecutionOrder(-100)]
。很多小伙伴没有留意后面会提到的这个内容,发现有ISaveable的注册报错。[DefaultExecutionOrder(-100)]
是 Unity 中的一个属性,用于指定脚本的默认执行顺序。参数 -100 表示该脚本的执行顺序优先级,数值越小,优先级越高,即越先执行。
新输入系统获取键盘的输入,按下L按键读取一下进度。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;//指定脚本的默认执行顺序,数值越小,优先级越高
[DefaultExecutionOrder(-100)]
public class DataManager : MonoBehaviour
{public static DataManager instance;[Header("事件监听")]public VoidEventSO saveDataEvent; // 保存数据事件/// <summary>/// 存储需要保存数据的 ISaveable 实例的列表。/// </summary>private List<ISaveable> saveableList = new List<ISaveable>();/// <summary>/// 保存数据到 Data 对象中。/// </summary>private Data saveData;private void Awake(){if (instance == null){instance = this;}else{Destroy(gameObject);}saveData = new Data();}private void Update(){// 按L 加载测试if(Keyboard.current.lKey.wasPressedThisFrame){Debug.Log("加载");Load();}}/// <summary>/// 注册需要保存数据的 ISaveable 实例。/// </summary>/// <param name="saveable">需要保存数据的 ISaveable 实例。</param>public void RegisterSaveData(ISaveable saveable){if (!saveableList.Contains(saveable)){saveableList.Add(saveable);}}public void UnRegisterSaveData(ISaveable saveable){if (saveableList.Contains(saveable)){// 如果在,就从列表中移除saveableList.Remove(saveable);}}private void OnEnable(){saveDataEvent.OnEventRaised += Save; // 监听保存数据事件}private void OnDisable(){saveDataEvent.OnEventRaised -= Save; // 取消监听保存数据事件}/// <summary>/// 保存数据。/// </summary>public void Save(){foreach (var saveable in saveableList){saveable.GetSaveData(saveData);}}/// <summary>/// 加载数据并应用到相应的 ISaveable 实例中。/// </summary>public void Load(){foreach (var saveable in saveableList){saveable.LoadData(saveData);}}
}
挂载配置
新增接口ISaveable
public interface ISaveable
{DataDefination GetDataID();/// <summary>/// 将该实例注册到数据管理器以便保存数据。/// </summary>void RegisterSaveData() => DataManager.instance.RegisterSaveData(this);/// <summary>/// 将该实例从数据管理器中注销,停止保存数据。/// </summary>void UnRegisterSaveData() => DataManager.instance.UnRegisterSaveData(this);/// <summary>/// 获取需要保存的数据并存储到指定的 Data 对象中。/// </summary>/// <param name="data">保存数据的 Data 对象。</param>void GetSaveData(Data data);/// <summary>/// 从指定的 Data 对象中加载数据并应用到该实例中。/// </summary>/// <param name="data">包含加载数据的 Data 对象。</param>void LoadData(Data data);
}
那么如果有三个野猪的名字完全一样,我们怎么区分每一只野猪具体存储的位置呢,所以接下来我们要创建一个唯一的标识,我们可以直接使用c#为我们设置好的全局唯一标识符,GUID就是个16位的串码,保证它的唯一性
新增枚举
/// <summary>
/// 指示数据定义的持久化类型。
/// </summary>
public enum PersistentType
{/// <summary>/// 可读写的持久化类型,数据会被持久化保存。/// </summary>ReadWrite,/// <summary>/// 不持久化类型,数据不会被持久化保存。/// </summary>DoNotPerst
}
新增DataDefination
public class DataDefination : MonoBehaviour
{/// <summary>/// 持久化类型,指示数据定义的持久化方式。/// </summary>public PersistentType persistentType;/// <summary>/// 数据定义的唯一标识符。/// </summary>public string ID;/// <summary>/// 当编辑器中的属性值发生更改时调用,用于自动设置默认的ID值。/// </summary>private void OnValidate(){if (persistentType == PersistentType.ReadWrite){if (ID == string.Empty){ID = System.Guid.NewGuid().ToString();}}else{ID = string.Empty;}}
}
配置挂载脚本,比如我们放在人物身上,生成唯一的UID
修改PlayerController,调用接口
public class PlayerController : MonoBehaviour, ISaveable
{//...private void OnEnable(){ISaveable saveable = this;saveable.RegisterSaveData();}private void OnDisable(){ISaveable saveable = this;saveable.UnRegisterSaveData();}// 获取数据ID,用于唯一标识当前对象的位置信息public DataDefination GetDataID(){return GetComponent<DataDefination>();}// 将对象的位置信息保存到数据中public void GetSaveData(Data data){// 检查数据中是否已经存在当前对象的位置信息if (data.characterPosDict.ContainsKey(GetDataID().ID)){// 如果已经存在,则更新位置信息data.characterPosDict[GetDataID().ID] = transform.position;}else{// 如果不存在,则添加新的位置信息data.characterPosDict.Add(GetDataID().ID, transform.position);}}// 从数据中加载对象的位置信息public void LoadData(Data data){// 检查数据中是否存在当前对象的位置信息if (data.characterPosDict.ContainsKey(GetDataID().ID)){// 如果存在,则将位置信息设置为对应的数值transform.position = data.characterPosDict[GetDataID().ID];}}
}
修改SavePoint,调用存储数据
public class SavePoint : MonoBehaviour, IInteractable {private SpriteRenderer spriteRenderer;public Sprite darkSprite;public Sprite lightSprite;public bool isDone;public VoidEventSO saveDataEvent; // 保存数据事件private void Awake() {spriteRenderer = GetComponent<SpriteRenderer>(); }private void OnEnable() {spriteRenderer.sprite = isDone ? lightSprite : darkSprite;}public void TriggerAction(){if(!isDone){Save();spriteRenderer.sprite = lightSprite;GetComponent<Collider2D>().enabled = false;isDone = true;}}//存储数据private void Save(){Debug.Log("存储数据");saveDataEvent.RaiseEvent();}
}
效果,按L测试读取数据,角色回到存储的位置
存储更多数据
修改Data,定义通用的float的类型,所有和float相关的类型都可用它保存
public class Data
{//...public Dictionary<string, float> floatSaveData = new Dictionary<string, float>();
}
但是如何区分是人物的血条还是能量呢?我们可以加入不同的后缀,修改PlayerController
// 将对象的位置信息保存到数据中
public void GetSaveData(Data data)
{// 检查数据中是否已经存在当前对象的位置信息if (data.characterPosDict.ContainsKey(GetDataID().ID)){// 如果已经存在,则更新位置信息data.characterPosDict[GetDataID().ID] = transform.position;data.floatSaveData[GetDataID().ID + "Health"] = GetComponent<Character>().currentHealth;data.floatSaveData[GetDataID().ID + "Power"] = GetComponent<Character>().currentPower;}else{// 如果不存在,则添加新的位置信息data.characterPosDict.Add(GetDataID().ID, transform.position);//存储玩家血量和能量data.floatSaveData.Add(GetDataID().ID + "Health", GetComponent<Character>().currentHealth);data.floatSaveData.Add(GetDataID().ID + "Power", GetComponent<Character>().currentPower);}
}// 从数据中加载对象的位置信息
public void LoadData(Data data)
{// 检查数据中是否存在当前对象的位置信息if (data.characterPosDict.ContainsKey(GetDataID().ID)){// 如果存在,则将位置信息设置为对应的数值transform.position = data.characterPosDict[GetDataID().ID];GetComponent<Character>().currentHealth = data.floatSaveData[GetDataID().ID + "Health"];GetComponent<Character>().currentPower = data.floatSaveData[GetDataID().ID + "Power"];//更新血条能量UIGetComponent<Character>().OnHealthChanged?.Invoke(GetComponent<Character>());}
}
效果
同理你可以存储其他的比如宝箱,野猪等信息
存储场景信息
修改Data,将场景信息转为json数据进行存取
public string sceneToSave;public void SaveGameScene(SceneField savedScene){sceneToSave = JsonUtility.ToJson(savedScene);
}public SceneField GetSavedScene(){SceneField loadedData = JsonUtility.FromJson<SceneField>(sceneToSave);return loadedData;
}
修改SavePoint,存储场景信息
public SceneField currentLoadedScene;public class SavePoint : MonoBehaviour, IInteractable, ISaveable
{//...public DataDefination GetDataID(){return null;}public void GetSaveData(Data data){data.SaveGameScene(currentLoadedScene);//存储场景}public void LoadData(Data data){}
}
配置当前场景
修改DataManager,我们希望加载存储场景完成后,再进行其他的LoadData操作,所以加载存储场景的操作我们就不放在LoadData里执行了。可以加入场景过渡渐变,让效果更好,这里我就不加了
/// <summary>
/// 加载数据并应用到相应的 ISaveable 实例中。
/// </summary>
public void Load()
{//获取存储的场景var scence = saveData.GetSavedScene();if (scence != null){// 获取当前活动的场景Scene activeScene = SceneManager.GetActiveScene();// 获取所有加载的场景for (int i = 0; i < SceneManager.sceneCount; i++){Scene loadedScene = SceneManager.GetSceneAt(i);Debug.Log("Loaded Scene " + i + ": " + loadedScene.name);if (activeScene.name != loadedScene.name) SceneManager.UnloadSceneAsync(loadedScene.name); // 异步卸载所有非主场景}//加载scence场景SceneManager.LoadSceneAsync(scence.SceneName, LoadSceneMode.Additive).completed += operation =>{if (operation.isDone){//获取相机边界方法cameraControl.GetNewCameraBounds();//加载其他数据foreach (var saveable in saveableList){saveable.LoadData(saveData);}}};//控制按钮的显示隐藏sceneLoadTrigger.StartMenu();}
}
效果
持久化存储数据
具体可以看我这篇文章:【unity小技巧】Unity存储存档保存——PlayerPrefs、JsonUtility和MySQL数据库的使用
需要注意的是,Dictionary 类型不能直接序列化为 JSON 字符串,因为 JsonUtility.ToJson() 方法只能序列化 Unity 引擎内置支持的类型。解决这个问题的一种方法是创建一个自定义类。其实我在之前的文章早就有用到这种方法:【用unity实现100个游戏之12】unity制作一个俯视角2DRPG《类星露谷物语、浮岛物语》资源收集游戏(附项目源码)
引入Unity 的可序列化字典类
Unity 无法序列化标准词典。这意味着它们不会在检查器中显示或编辑,
也不会在启动时实例化。一个经典的解决方法是将键和值存储在单独的数组中,并在启动时构造字典。
我们使用gitthub大佬的源码即可,此项目提供了一个通用字典类及其自定义属性抽屉来解决此问题。
源码地址:https://github.com/azixMcAze/Unity-SerializableDictionary
你可以选择下载源码,也可以直接复制我下面的代码,我把主要代码提出来了
SerializableDictionary.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;public abstract class SerializableDictionaryBase
{public abstract class Storage {}protected class Dictionary<TKey, TValue> : System.Collections.Generic.Dictionary<TKey, TValue>{public Dictionary() {}public Dictionary(IDictionary<TKey, TValue> dict) : base(dict) {}public Dictionary(SerializationInfo info, StreamingContext context) : base(info, context) {}}
}[Serializable]
public abstract class SerializableDictionaryBase<TKey, TValue, TValueStorage> : SerializableDictionaryBase, IDictionary<TKey, TValue>, IDictionary, ISerializationCallbackReceiver, IDeserializationCallback, ISerializable
{Dictionary<TKey, TValue> m_dict;[SerializeField]TKey[] m_keys;[SerializeField]TValueStorage[] m_values;public SerializableDictionaryBase(){m_dict = new Dictionary<TKey, TValue>();}public SerializableDictionaryBase(IDictionary<TKey, TValue> dict){ m_dict = new Dictionary<TKey, TValue>(dict);}protected abstract void SetValue(TValueStorage[] storage, int i, TValue value);protected abstract TValue GetValue(TValueStorage[] storage, int i);public void CopyFrom(IDictionary<TKey, TValue> dict){m_dict.Clear();foreach (var kvp in dict){m_dict[kvp.Key] = kvp.Value;}}public void OnAfterDeserialize(){if(m_keys != null && m_values != null && m_keys.Length == m_values.Length){m_dict.Clear();int n = m_keys.Length;for(int i = 0; i < n; ++i){m_dict[m_keys[i]] = GetValue(m_values, i);}m_keys = null;m_values = null;}}public void OnBeforeSerialize(){int n = m_dict.Count;m_keys = new TKey[n];m_values = new TValueStorage[n];int i = 0;foreach(var kvp in m_dict){m_keys[i] = kvp.Key;SetValue(m_values, i, kvp.Value);++i;}}#region IDictionary<TKey, TValue>public ICollection<TKey> Keys { get { return ((IDictionary<TKey, TValue>)m_dict).Keys; } }public ICollection<TValue> Values { get { return ((IDictionary<TKey, TValue>)m_dict).Values; } }public int Count { get { return ((IDictionary<TKey, TValue>)m_dict).Count; } }public bool IsReadOnly { get { return ((IDictionary<TKey, TValue>)m_dict).IsReadOnly; } }public TValue this[TKey key]{get { return ((IDictionary<TKey, TValue>)m_dict)[key]; }set { ((IDictionary<TKey, TValue>)m_dict)[key] = value; }}public void Add(TKey key, TValue value){((IDictionary<TKey, TValue>)m_dict).Add(key, value);}public bool ContainsKey(TKey key){return ((IDictionary<TKey, TValue>)m_dict).ContainsKey(key);}public bool Remove(TKey key){return ((IDictionary<TKey, TValue>)m_dict).Remove(key);}public bool TryGetValue(TKey key, out TValue value){return ((IDictionary<TKey, TValue>)m_dict).TryGetValue(key, out value);}public void Add(KeyValuePair<TKey, TValue> item){((IDictionary<TKey, TValue>)m_dict).Add(item);}public void Clear(){((IDictionary<TKey, TValue>)m_dict).Clear();}public bool Contains(KeyValuePair<TKey, TValue> item){return ((IDictionary<TKey, TValue>)m_dict).Contains(item);}public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex){((IDictionary<TKey, TValue>)m_dict).CopyTo(array, arrayIndex);}public bool Remove(KeyValuePair<TKey, TValue> item){return ((IDictionary<TKey, TValue>)m_dict).Remove(item);}public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator(){return ((IDictionary<TKey, TValue>)m_dict).GetEnumerator();}IEnumerator IEnumerable.GetEnumerator(){return ((IDictionary<TKey, TValue>)m_dict).GetEnumerator();}#endregion#region IDictionarypublic bool IsFixedSize { get { return ((IDictionary)m_dict).IsFixedSize; } }ICollection IDictionary.Keys { get { return ((IDictionary)m_dict).Keys; } }ICollection IDictionary.Values { get { return ((IDictionary)m_dict).Values; } }public bool IsSynchronized { get { return ((IDictionary)m_dict).IsSynchronized; } }public object SyncRoot { get { return ((IDictionary)m_dict).SyncRoot; } }public object this[object key]{get { return ((IDictionary)m_dict)[key]; }set { ((IDictionary)m_dict)[key] = value; }}public void Add(object key, object value){((IDictionary)m_dict).Add(key, value);}public bool Contains(object key){return ((IDictionary)m_dict).Contains(key);}IDictionaryEnumerator IDictionary.GetEnumerator(){return ((IDictionary)m_dict).GetEnumerator();}public void Remove(object key){((IDictionary)m_dict).Remove(key);}public void CopyTo(Array array, int index){((IDictionary)m_dict).CopyTo(array, index);}#endregion#region IDeserializationCallbackpublic void OnDeserialization(object sender){((IDeserializationCallback)m_dict).OnDeserialization(sender);}#endregion#region ISerializableprotected SerializableDictionaryBase(SerializationInfo info, StreamingContext context) {m_dict = new Dictionary<TKey, TValue>(info, context);}public void GetObjectData(SerializationInfo info, StreamingContext context){((ISerializable)m_dict).GetObjectData(info, context);}#endregion
}public static class SerializableDictionary
{public class Storage<T> : SerializableDictionaryBase.Storage{public T data;}
}[Serializable]
public class SerializableDictionary<TKey, TValue> : SerializableDictionaryBase<TKey, TValue, TValue>
{public SerializableDictionary() {}public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(dict) {}protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {}protected override TValue GetValue(TValue[] storage, int i){return storage[i];}protected override void SetValue(TValue[] storage, int i, TValue value){storage[i] = value;}
}[Serializable]
public class SerializableDictionary<TKey, TValue, TValueStorage> : SerializableDictionaryBase<TKey, TValue, TValueStorage> where TValueStorage : SerializableDictionary.Storage<TValue>, new()
{public SerializableDictionary() {}public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(dict) {}protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {}protected override TValue GetValue(TValueStorage[] storage, int i){return storage[i].data;}protected override void SetValue(TValueStorage[] storage, int i, TValue value){storage[i] = new TValueStorage();storage[i].data = value;}
}
调用
修改Data,Dictionary 全部改为SerializableDictionary
public class Data
{/// <summary>/// 存储角色位置信息的字典,键为角色名称,值为对应的位置坐标(Vector3)。/// </summary>public SerializableDictionary <string, Vector3> characterPosDict = new SerializableDictionary <string, Vector3>();public SerializableDictionary <string, float> floatSaveData = new SerializableDictionary <string, float>();public SerializableDictionary <string, bool> boolSaveData = new SerializableDictionary <string, bool>();public string sceneToSave;public void SaveGameScene(SceneField savedScene){sceneToSave = JsonUtility.ToJson(savedScene);}public SceneField GetSavedScene(){SceneField loadedData = JsonUtility.FromJson<SceneField>(sceneToSave);return loadedData;}
}
修改DataManager
String savePath = "test.json";/// <summary>
/// 保存数据。
/// </summary>
public void Save()
{//。。。//持久化存储数据String jsonData = JsonUtility.ToJson(saveData);File.WriteAllText(savePath, jsonData);
}/// <summary>
/// 加载数据并应用到相应的 ISaveable 实例中。
/// </summary>
public void Load()
{//读取数据string jsonData = File.ReadAllText(savePath);//将JSON数据反序列化为游戏数据对象Data saveData = JsonUtility.FromJson<Data>(jsonData);//。。。
}
查看存储的test.json数据
效果
游戏结束
比如触碰水死亡,我们直接加个Attack脚本就可以了,把伤害设置很高
人物死亡,返回菜单,修改PlayerController
//死亡
public void PlayerDead()
{AudioManager.Instance.PlaySFX("人物死亡");isDead = true;inputControl.Player.Disable();//多少秒后重新加载场景Invoke("RestartGame", 1.5f);
}//重新开始
public void RestartGame()
{SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
效果
源码
源码不出意外的话我会放在最后一节
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,以便我第一时间收到反馈,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
相关文章:

【制作100个unity游戏之26】unity2d横版卷轴动作类游13(附带项目源码)
最终效果 系列导航 文章目录 最终效果系列导航前言存储点灯光后处理存储位置信息存储更多数据存储场景信息持久化存储数据引入Unity 的可序列化字典类调用 游戏结束源码完结 前言 欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各…...
Golang使用HTTP框架zdpgo_resty实现文件下载
核心代码 代码解析: client.SetOutputDirectory("Downloads") 设置下载目录client.R().SetOutput("test.go").Get("http://127.0.0.1:3333/download 指定下载文件名并进行下载 // 设置输出目录路径,如果目录不存在ÿ…...

提取COCO 数据集的部分类
1.python提取COCO数据集中特定的类 安装pycocotools github地址:https://github.com/philferriere/cocoapi pip install githttps://github.com/philferriere/cocoapi.git#subdirectoryPythonAPI若报错,pip install githttps://github.com/philferriere…...

高刚性滚柱直线导轨有哪些优势?
滚柱导轨是机械传动系统中用于支持和引导滑块或导轨的装置,承载能力较高、刚性强及高精度等特点。特别适用于大负载和高刚性的工业设备,如机床、数控机床等设备,这些优势使其在工业生产和机械设备中得到了广泛的应用。 1、高精度:…...

KNN及降维预处理方法LDA|PCA|MDS
文章目录 基本原理模型介绍模型分析 python代码实现降维处理维数灾难 curse of dimensionality线性变换 Linear TransformationLDA - 线性判别分析LDA python 实现PCA - 主成分分析PCA最近重构性PCA最大可分性PCA求解及说明PCA python实现 多维缩放 Multiple Dimensional Scali…...

论文精读-SwinIR Image Restoration Using Swin Transformer
论文精读-SwinIR: Image Restoration Using Swin Transformer SwinIR:使用 Swin Transformer进行图像恢复 参数量:SR 11.8M、JPEG压缩伪影 11.5M、去噪 12.0M 优点:1、提出了新的网络结构。它采用分块设计。包括浅层特征提取:cnn提取&#…...
解释Spring Bean的生命周期
Spring Bean的生命周期涉及到Bean的创建、配置、使用和销毁的各个阶段。理解这个生命周期对于编写高效的Spring应用和充分利用框架的功能非常重要。下面是Spring Bean生命周期的主要步骤: 1. 实例化Bean Spring容器首先将使用Bean的定义(无论是XML、注…...

CTF网络安全大赛web题目:字符?正则?
题目来源于:bugku 题目难度:难 题目描 述: 字符?正则? 题目htmnl源代码: <code><span style"color: #000000"> <span style"color: #0000BB"><?php <br />highl…...

Linux——Docker容器虚拟化平台
安装docker 安装 Docker | Docker 从入门到实践https://vuepress.mirror.docker-practice.com/install/ 不需要设置防火墙 docker命令说明 docker images #查看所有本地主机的镜像 docker search 镜像名 #搜索镜像 docker pull 镜像名 [标签] #下载镜像&…...

Transformer详解(3)-多头自注意力机制
attention multi-head attention pytorch代码实现 import math import torch from torch import nn import torch.nn.functional as Fclass MultiHeadAttention(nn.Module):def __init__(self, heads8, d_model128, droput0.1):super().__init__()self.d_model d_model # 12…...

运用HTML、CSS设计Web网页——“西式甜品网”图例及代码
目录 一、效果展示图 二、设计分析 1.整体效果分析 2.头部header模块效果分析 3.导航及banner模块效果分析 4.分类classify模块效果分析 5.产品展示show模块效果分析 6.版权banquan模块效果分析 三、HTML、CSS代码分模块展示 1. 头部header模块代码 2.导航及bann…...

大语言模型是通用人工智能的实现路径吗?【文末有福利】
相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型:从线性回归到通用人工智能》,欢迎有兴趣的读者多多支持。 关于大语言模型的内容,推荐参考这个专栏。 内容大纲 相关说明一、哲学与人工智能二、内容简介三、书籍简介与福利粉…...

c语言——宏offsetof
1.介绍 !!! offsetof 是一个宏 2.使用举例 结构体章节的计算结构体占多少字节需要先掌握(本人博客结构体篇章中已经讲解过) 计算结构体中某变量相对于首地址的偏移,并给出说明 首先,结构体首个…...
C#串口通信-串口相关参数介绍
串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种双向通讯方式。 串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的通信协议,…...
节省时间与精力:用BAT文件和任务计划器自动执行重复任务
文章目录 1.BAT文件详解2. 经典BAT文件及使用场景3. 使用方法4. 如何设置BAT文件为定时任务5. 实例应用:自动清理临时文件 BAT文件,也就是批处理文件,是一种在Windows操作系统中自动执行一系列命令的文本文件。这些文件的扩展名为 .bat。通过…...

一年前的Java作业,模拟游戏玩家战斗
说明:一年前写的作业,感觉挺有意思的,将源码分享给大家。 刚开始看题也觉得很难,不过写着写着思路更加清晰,发现也没有想象中的那么难。 一、作业题目描述: 题目:模拟游戏玩家战斗 1.1 基础功…...
C++ 学习 关于引用
🙋本文主要讲讲C的引用 是基础入门篇~ 本文是阅读C Primer 第五版的笔记 🌈 关于引用 几个比较重要的点 🌿引用相当于为一个已经存在的对象所起的另外一个名字 🌞 定义引用时,程序把引用和它的初始值绑定(b…...

BERT ner 微调参数的选择
针对批大小和学习率的组合进行收敛速度测试,结论: 相同轮数的条件下,batchsize-32 相比 batchsize-256 的迭代步数越多,收敛更快批越大的话,学习率可以相对设得大一点 画图代码(deepseek生成)…...
【MySQL精通之路】系统变量-持久化系统变量
MySQL服务器维护用于配置其操作的系统变量。 系统变量可以具有影响整个服务器操作的全局值,也可以具有影响当前会话的会话值,或者两者兼而有之。 许多系统变量是动态的,可以在运行时使用SET语句进行更改,以影响当前服务器实例的…...
fdk-aac将aac格式转为pcm数据
int sampleRate 44100; // 采样率int sampleSizeInBits 16; // 采样位数,通常是16int channels 2; // 通道数,单声道为1,立体声为2FILE *m_fd NULL;FILE *m_fd2 NULL;HANDLE_AACDECODER decoder aacDecoder_Open(TT_MP4_ADTS, 1);if (!…...

【C语言深度解剖】(15):动态内存管理和柔性数组
🤡博客主页:醉竺 🥰本文专栏:《C语言深度解剖》 😻欢迎关注:感谢大家的点赞评论关注,祝您学有所成! ✨✨💜💛想要学习更多C语言深度解剖点击专栏链接查看&…...
力扣每日一题 5/25
题目: 给你一个下标从 0 开始、长度为 n 的整数数组 nums ,以及整数 indexDifference 和整数 valueDifference 。 你的任务是从范围 [0, n - 1] 内找出 2 个满足下述所有条件的下标 i 和 j : abs(i - j) > indexDifference 且abs(nums…...
(1)无线电失控保护(一)
文章目录 前言 1 何时触发失控保护 2 将会发生什么 3 接收机配置...

基于51单片机的多功能万年历温度计—可显示农历
基于51单片机的万年历温度计 (仿真+程序+原理图+设计报告) 功能介绍 具体功能: 本设计基于STC89C52(与AT89S52、AT89C52通用,可任选)单片机以及DS1302时钟芯片、DS18B…...

【软件设计师】下午题总结-数据流图、数据库、统一建模语言
下午题总结 1 试题一1.1 结构化语言 2 试题二弱实体增加权限增加实体间联系和联系的类型 3 试题三3.1 UML关系例子 3.2 例子(2016上半年)3.3 设计类分类3.3.1 接口类3.3.2 控制类3.3.3 实体类 3.4 简答题3.4.1 简要说明选择候选类的原则3.4.2 某个类必须…...

CSDN 自动评论互动脚本
声明 该脚本的目的只是为了提升博客创作效率和博主互动效率,希望大家还是要尊重各位博主的劳动成果。 数据库设计 尽量我们要新建一个数据库csdn_article,再在其中建一个数据表article -- csdn_article-- article-- 需要进行自动评论的表格信息...CREATE TABLE `article`…...

Tomcat端口配置
Tomcat是开源免费的服务器,其默认的端口为8080,本文讲述一下如何配置端口。 最后在浏览器中输入localhost:8888即可打开Tomcat界面...

SpringBoot中使用AOP实现日志记录功能
目录 一、SpringBoot框架介绍 二、什么是 AOP 三、日志记录的必要性 四、SpringBoot中如何使用AOP实现日志记录功能 一、SpringBoot框架介绍 SpringBoot是一个开源的Java开发框架,旨在简化基于Spring框架的应用程序的开发。它提供了一套开箱即用的工具…...

kubernetes(k8s) v1.30.1 helm 集群安装 Dashboard v7.4.0 可视化管理工具 图形化管理工具
本文 紧接上一篇:详细教程 Centos8.5 基于 k8s v1.30.1 部署高可用集群 kubeadm 安装 kubernetes v1.30.1 docker集群搭建 延长证书有效期-CSDN博客 1 Dashboard 从版本 7.0.0 开始,不再支持基于清单的安装。仅支持基于 Helm 的安装. #Helm 下载安装 …...
CS144(所有lab解析)
CS144 lab0-CSDN博客 (CS144 2024)Lab Checkpoint 1: stitching substrings into a byte stream (详细解析)-CSDN博客 CS144 Lab2 (2024)超详细解析-CSDN博客 Lab Checkpoint 3: the TCP sender-CSDN博客 CS144 Checkpoint 4: in…...