unity【动画】脚本_角色动画控制器 c#
首先创建一个代码文件夹Scripts

从人物角色Player的基类开始 创建IPlayer类
首先我们考虑到如果不挂载MonoBehaviour需要将角色设置成预制体实例化到场景上十分麻烦,
所以我们采用继承MonoBehaviour类的角色基类方法写代码
也就是说这个脚本直接绑定在角色物体身上,就不需要实例化了,相对降低了复杂程度。
首先我们需要在unity场景制作一个Renderer类型的目标点
首先创建一个平面Plane改名为MovementTargetSign

修改位置

移除掉碰撞器


添加一个材质

对材质进行修改 点击Shader选项





选择一个纹理



代码:

using UnityEngine;
//抽象角色类-包括玩家和NPC
public class IPlayer : MonoBehaviour{
protected Animator _animator;//动画器组件引用
private IWeapon _weapon = null;//武器的引用
}
public class IWeapon{
}
using UnityEngine;
public class Player : IPlayer{
private Renderer movementSign;//移动标志
private Collider attackPlane;//攻击区
private Collider floorPlane;//普通地面(非攻击区)
private Vector3 lookatPos;//面向位置
private float rotSpeed = 20f;//移动旋转速度
private float attackRotSpeed = 10f;//攻击旋转速度
}
public class FemaleWarrior : Player{
}
将FemaleWarrior代码挂载Player对象身上

对角色Player添加胶囊碰撞器

调整胶囊碰撞器位于角色中心

再添加刚体

关掉 使用重力Use Gravity 勾选

在约束上constraints 冻结旋转 x y z

如果制作的角色不需要重力则用碰撞器实现,
如果制作的角色需要重力 则用刚体 实现
先用刚体实现:
代码如下:

using UnityEngine;
//抽象角色类-包括玩家和NPC
public class IPlayer : MonoBehaviour{
protected Animator _animator;//动画器组件引用
private IWeapon _weapon = null;//武器的引用
}

public class IWeapon{
}
using UnityEngine;
public class Player : IPlayer{
private Renderer movementSign;//移动标志
private Collider attackPlane;//攻击区
private Collider floorPlane;//普通地面(非攻击区)
private Vector3 lookatPos;//面向位置
private float rotSpeed = 20f;//移动旋转速度
private float attackRotSpeed = 10f;//攻击旋转速度
protected virtual void Awake() {
//移动标志
if (movementSign == null)
movementSign = GameObject.Find("MovementTargetSign").GetComponent<Renderer>();
}
protected virtual void Start(){
//移动标志默认放在玩家脚下
movementSign.transform.position = transform.position + new Vector3(0,0.02f,0);
movementSign.enabled = false;//关闭移动标志的显示
}
//跟随鼠标旋转
public void RotateWithCursorPos() {
RaycastHit hit;
//构建一条从摄像机到鼠标位置的射线
var Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(Ray, out hit)) {
//计算方向
Vector3 mousePos = new Vector3(hit.point.x, transform.position.y, hit.point.z);
Vector3 playerDirection = mousePos - transform.position;
if (playerDirection != Vector3.zero) {
//旋转到目标方向
transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.LookRotation(playerDirection), Time.deltaTime * attackRotSpeed);
}
}
}
protected virtual void Update() {
RotateWithCursorPos();
}
}
public class FemaleWarrior : Player{
protected override void Awake(){
base.Awake();
}
protected override void Start(){
base.Start();
}
}
完成人物转向之后,开始做人物移动功能
首先添加代码,将动画机参数转换为哈希值

using UnityEngine;
public class AnimaterConsteantVelues {
public static int WeaponID = Animator.StringToHash("WeaponID");
public static int isCombat = Animator.StringToHash("isCombat");
public static int isIdle = Animator.StringToHash("isIdle");
public static int Attack = Animator.StringToHash("Attack");
}
在角色基类中添加函数

using UnityEngine;
//抽象角色类-包括玩家和NPC
public class IPlayer : MonoBehaviour{
protected Animator _animator;//动画器组件引用
private IWeapon _weapon = null;//武器的引用
public IWeapon Weapon {
get => _weapon;
set => _weapon = value;
}
public void Attack() {
if (_weapon != null)
_weapon.Attack();
}
}
修改抽象武器基类

using UnityEngine;
public abstract class IWeapon{
public string WeaponName { get; set; }
protected GameObject _weaponModel;
protected GameObject _weaponPrefab;
private int weaponID { get; set; }
protected IPlayer _player { get; set; }
public GameObject WeaponPrefab {
get => _weaponModel;
set => _weaponModel = value;
}
public virtual void Attack() { }
public virtual void RefreshLine() { }
public IWeapon(int weaponID, string name, string weaponModelPath, IPlayer player){
this.weaponID = weaponID;
WeaponName = name;
_player = player;
if (weaponModelPath != "") {
_weaponModel = Resources.Load<GameObject>(weaponModelPath);
if (_weaponModel != null) {
var weaponPos = ((Player)_player).handleWeaponPosList[weaponID];
_weaponPrefab = GameObject.Instantiate(_weaponModel, weaponPos.position, weaponPos.rotation);
_weaponPrefab.transform.SetParent(weaponPos);
_weaponPrefab.SetActive(false);
}
}
}
}
修改角色子类

using System.Collections.Generic;
using UnityEngine;
public class Player : IPlayer{
private Renderer movementSign;//移动标志
private Collider attackPlane;//攻击区
private Collider floorPlane;//普通地面(非攻击区)
private Vector3 lookatPos;//面向位置
private float rotSpeed = 20f;//移动旋转速度
private float attackRotSpeed = 10f;//攻击旋转速度
private float fallSpeed;
//列表
[SerializeField]
public List<Transform>handleWeaponPosList = new List<Transform>();
protected virtual void Awake() {
_animator = GetComponent<Animator>();
floorPlane = GameObject.Find("Plane").GetComponent<Collider>();
//移动标志
if (movementSign == null)
movementSign = GameObject.Find("MovementTargetSign").GetComponent<Renderer>();
}
protected virtual void Start(){
//移动标志默认放在玩家脚下
movementSign.transform.position = transform.position + new Vector3(0,2f,0);
movementSign.enabled = false;//关闭移动标志的显示
}
//跟随鼠标旋转
public void RotateWithCursorPos() {
RaycastHit hit;
//构建一条从摄像机到鼠标位置的射线
var Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(Ray, out hit)) {
//计算方向
Vector3 mousePos = new Vector3(hit.point.x, transform.position.y, hit.point.z);
Vector3 playerDirection = mousePos - transform.position;
if (playerDirection != Vector3.zero) {
//旋转到目标方向
transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.LookRotation(playerDirection), Time.deltaTime * attackRotSpeed);
}
}
}
public void Move(){
RaycastHit hit;
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetMouseButton(0)){
if (floorPlane.Raycast(ray, out hit, 50f)){
movementSign.transform.position = hit.point + new Vector3(0, 0.01f, 0);
movementSign.enabled = true;
lookatPos = hit.point;
}
}
else if(Input.GetMouseButtonUp(1)){
_animator.SetBool(AnimaterConsteantVelues.isCombat, true);
_animator.SetTrigger(AnimaterConsteantVelues.Attack);
Attack();
}
lookatPos.y = transform.position.y;
var playerDirection = lookatPos - transform.position;
if (playerDirection != Vector3.zero)
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(playerDirection), Time.deltaTime * rotSpeed);
var offset = movementSign.transform.position - transform.position;
var sqrDistance = offset.sqrMagnitude;
if (sqrDistance > 0.1f){
_animator.SetBool(AnimaterConsteantVelues.isIdle, false);
rotSpeed = 20f;
}
else {
_animator.SetBool(AnimaterConsteantVelues.isIdle,true);
movementSign.enabled = false;
movementSign.transform.position = transform.position;
rotSpeed = 0;
}
var bodyRay = new Ray(transform.position + transform.up, transform.up * -1);
if (floorPlane.Raycast(bodyRay, out hit, 1.0f)) {
if (hit.point.y > transform.position.y + 0.02f)
transform.position = hit.point + new Vector3(0, 0.02f, 0);
else if (floorPlane.Raycast(bodyRay, out hit, 1.2f))
if (hit.point.y > transform.position.y - 0.02f)
transform.position = hit.point + new Vector3(0, -0.02f, 0);
else {
fallSpeed += 0.1f;
var v = new Vector3(0, fallSpeed * Time.deltaTime, 0);
transform.position -= v;
movementSign.transform.position = transform.position + new Vector3(0, 0.01f, 0);
}
}
}
protected virtual void Update() {
RotateWithCursorPos();
Move();
}
}
回到Unity场景中拖拽填充武器刷新
人物移动完成
接下来完成背包系统











放进预制体包后完全解压缩




调整好Slot0-4的背景位置,将四个子物体预制体包后删除




子物体位置都改成0

隐藏/取消激活

接下来完成拾取道具

加碰撞器

调节碰撞器

加触发器

加刚体

修改名字


创建脚本
![]()

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//可拾取道具
public class CanPickupItem : MonoBehaviour{
public AudioClip pickUpSound;//拾取声音
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player")) {
//播放声音
if (pickUpSound != null)
AudioSource.PlayClipAtPoint(pickUpSound,transform.position);
//将本道具更新到背包列表中
GameObject.FindGameObjectWithTag("InventoryUITag").GetComponent<InventoryManager>().ItemNames.Add(gameObject.name);
Destroy(gameObject);
}
}
}
挂载脚本

同样挂载到手枪上

添加标签



创建脚本
![]()

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryManager : MonoBehaviour
{
//道具名称列表
public List<string> ItemNames = new List<string>();
}


给人物标签

标签


运行即可触发拾取道具

接下来做背包系统
首先这里不用字典代码,运用简单方式制作,前提必须保证道具 和 道具图片的英文名字存在包含关系



在管理类中写一个打开背包的方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryManager : MonoBehaviour
{
//道具名称列表
public List<string> ItemNames = new List<string>();
//打开或关闭背包
public void OpenOrCloseInventoryUI(bool isOpen) {
transform.Find("Panel").gameObject.SetActive(isOpen);
}
}

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting.Antlr3.Runtime;
using UnityEngine;
using UnityEngine.UI;
public class InventoryManager : MonoBehaviour
{
//道具名称列表
public List<string> ItemNames = new List<string>();
//是否显示背包UI
private bool isShowInventoryUI = false;
//打开或关闭背包
public void OpenOrCloseInventoryUI(bool isOpen) {
transform.Find("Panel").gameObject.SetActive(isOpen);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.B)) {
isShowInventoryUI = !isShowInventoryUI;
//打开或关闭UI
OpenOrCloseInventoryUI(isShowInventoryUI);
}
}
}
即可实现背包按B键开关背包UI
接下来我们需要做一个背包图标的UI,点击UI也能打开背包







即完成鼠标点击显隐背包UI 及 键盘B键显隐背包UI
接下来做UI文本更新,意义不大可省略,存在的意义在于完善体系

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryManager : MonoBehaviour{
//道具名称列表
public List<string> ItemNames = new List<string>();
//是否显示背包UI
private bool isShowInventoryUI = false;
//UI界面中的文本
public Text[] textUI;
//激活或关闭背包UI显示
public void OpenOrCloseInventoryUI(bool isOpen) {
transform.Find("Panel").gameObject.SetActive(isOpen);
//更新文本
UpdateInventoryTextUI();
}
private void Update(){
if (Input.GetKeyDown(KeyCode.B))
InventoryUIState();
}
//打开或关闭背包
public void InventoryUIState() {
isShowInventoryUI = !isShowInventoryUI;
//打开或关闭UI
OpenOrCloseInventoryUI(isShowInventoryUI);
}
//更新文本UI
private void UpdateInventoryTextUI(){
for(int i = 0;i< ItemNames.Count;i++)
textUI[i].text = ItemNames[i];
}
}
调整文本在背包UI中的位置



取消激活面板



using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryManager : MonoBehaviour{
public List<string> ItemNames = new List<string>();//道具名称列表
private bool isShowInventoryUI = false;//是否显示背包UI
public Text[] textUI;//UI界面中的文本
public Image[] availableItemIcons;//可以获取的道具图标
public void OpenOrCloseInventoryUI(bool isOpen){//激活或关闭背包UI显示
transform.Find("Panel").gameObject.SetActive(isOpen);
UpdateInventoryTextUI(); //更新文本
UpdateInventoryIconUI();//更新图标
}
private void Update(){
if (Input.GetKeyDown(KeyCode.B))
InventoryUIState();
}
public void InventoryUIState(){//打开或关闭背包
isShowInventoryUI = !isShowInventoryUI;
OpenOrCloseInventoryUI(isShowInventoryUI);//打开或关闭UI
}
private void UpdateInventoryTextUI(){//更新文本UI
for (int i = 0;i < ItemNames.Count;i++)
textUI[i].text = ItemNames[i];
}
private void UpdateInventoryIconUI(){//更新图标UI
for (int i = 0; i < ItemNames.Count; i++){
Image itemIcon = GetIconPrefabByItemName(ItemNames[i]);//根据道具名称返回对应的图标
if (itemIcon != null){
Image newItemIcon = Instantiate(itemIcon);//将图标克隆到对应的Image中
newItemIcon.transform.SetParent(textUI[i].transform.parent);//更改父物体
RectTransform rt = newItemIcon.GetComponent<RectTransform>();//调整位置
rt.anchoredPosition = Vector3.zero;
}
else
Debug.LogError("没找到对应图标");
}
}
private Image GetIconPrefabByItemName(string name){//根据道具名称返回对应的图标
for (int i = 0; i < availableItemIcons.Length; i++){
if (availableItemIcons[i].name.Contains(name))
return availableItemIcons[i];
}
return null;
}
}
隐藏文字部分

运行即完成


挂移动摄像机

using UnityEngine;
public class CameraMove : MonoBehaviour{ //第三人称摄像机简单版
public Transform target;//摄像机的跟随目标
public float distance = 8.0f;//摄像机与目标之间的距离
private float x, y, z;
private float xSpeed = 250.0f;
private float ySpeed = 120.0f;
public float yMinlimit = -45.0f;//限制上下移动角度
public float yMaxlimit = 45.0f;
private void Awake(){
//注册场景加载完毕事件
//EventCenter.AddListener(EventType.SceneLoadComplete, SetTarget);
}
private void SetTarget(){
//将标签为Player的物体设置为跟踪目标
Transform player = GameObject.FindGameObjectWithTag("Player").transform;
if (player != null && target == null)
target = player;
}
private void Start(){
Vector3 angles = transform.eulerAngles;//获取摄像机的当前角度
x = angles.x;
y = angles.y;
z = -distance;
GoRight();
}
private void LateUpdate(){
float temp = Input.GetAxis("Mouse ScrollWheel");//获取滚轮数值
if (target != null){
if (Input.GetMouseButton(0)){
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
}
}
//钳制上下移动的角度
y = ClampAngle(y,yMinlimit,yMaxlimit);
z += temp * 100f * 0.02f;//数值按照自己喜好设定
z = Mathf.Clamp(z,-20f,-3.0f);//距离限制,最远是距离玩家20米,最近是3米
GoRight();//作用于摄像机
}
float ClampAngle(float angle,float min,float max){
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle,min,max);
}
//摄像机控制位置及角度的核心方法
void GoRight(){
if (target == null)
return;
Quaternion rotation = Quaternion.Euler(y,x,0);//摄像机角度
Vector3 position = rotation * new Vector3(0.0f,0.0f,z)+target.position;
transform.position = position;//摄像机位置
transform.rotation = rotation;//摄像机角度
}
}
即完成摄像机跟随人物移动

相关文章:
unity【动画】脚本_角色动画控制器 c#
首先创建一个代码文件夹Scripts 从人物角色Player的基类开始 创建IPlayer类 首先我们考虑到如果不挂载MonoBehaviour需要将角色设置成预制体实例化到场景上十分麻烦, 所以我们采用继承MonoBehaviour类的角色基类方法写代码 也就是说这个脚本直接绑定在角色物体…...
Java代码如何对Excel文件进行zip压缩
1:新建 ZipUtils 工具类 package com.ly.cloud.datacollection.util;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import ja…...
改进YOLO系列:12.Repulsion损失函数【遮挡】
1. RepLoss论文 物体遮挡问题可以分为类内遮挡和类间遮挡两种情况。类间遮挡产生于扎堆的同类物体,也被称为密集遮挡(crowd occlusion)。Repulsion损失函数由三个部分构成,yolov5样本匹配,得到的目标框和预测框-一对应第一部分主要作用:预测目标框吸引IOU最大的真实目标框,…...
win11网络连接正常,但是无法正常上网
前言: 这个是一个win11的bug,好多人都遇到了,在孜孜不倦的百度下,毫无收获,终于是在抖音上看到有人分享的经验而解决了这个问题。 找到internet选项,然后点击打开 选择连接 将代理服务器中,为…...
硬科技企业社区“曲率引擎”品牌正式发布
“曲率引擎”,是科幻作品中最硬核的加速系统,通过改变时空的曲率,可实现光速飞行甚至能够超越光速。11月3日,“曲率引擎(warp drive)”作为硬科技企业社区品牌,在2023全球硬科技创新大会上正式对…...
少儿编程 2023年9月中国电子学会图形化编程等级考试Scratch编程三级真题解析(判断题)
2023年9月scratch编程等级考试三级真题 判断题(共10题,每题2分,共20分) 19、运行程序后,“我的变量”的值为25 答案:对 考点分析:考查积木综合使用,重点考查变量和运算积木的使用 开始我的变量为50,执行完第二行代码我的变量变为49,条件不成立执行否则语句,所以…...
MCU常见通信总线串讲(二)—— RS232和RS485
🙌秋名山码民的主页 😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 获取源码,添加WX 目录 前言一…...
LazyVim: 将 Neovim 升级为完整 IDE | 开源日报 No.67
curl/curl Stars: 31.5k License: NOASSERTION Curl 是一个命令行工具,用于通过 URL 语法传输数据。 核心优势和关键特点包括: 可在命令行中方便地进行数据传输支持多种协议 (HTTP、FTP 等)提供丰富的选项和参数来满足不同需求 kubernetes/ingress-n…...
想要搭建网站帮助中心,看这一篇指南就对了!
在现今互联网时代,除了让用户了解产品的功能和一些操作,很多企业都需要在网上进行信息的发布和产品销售等业务活动。而这就需要一个帮助中心,在用户遇到问题或者需要了解更多信息的时候,能够快速地解答他们的疑惑和提供响应的帮助…...
92.更新一些收藏的经验贴总结学习
一、JS相关 1.进制转换 (1)十进制转二进制 十进制数除2取余法:十进制数除2,余数为权位上的数,得到的商继续除2,直到商为0。最后余数从下往上取值。 (2)二进制转十进制 把二进制…...
mysql 问题解决 4
7、集群 7.1 日志 1、MySQL 中有哪些常见日志? MySQL 中有以下常见的日志类型: 错误日志(Error Log):记录 MySQL 服务器在运行过程中出现的错误信息。通用查询日志(General Query Log):记录所有连接到 MySQL 服务器的 SQL 查询语句。慢查询日志(Slow Query Log):…...
llama-7B、vicuna-7b-delta-v1.1和vicuna-7b-v1.3——使用体验
Chatgpt的出现给NLP领域带来了让人振奋的消息,可以很逼真的模拟人的对话,回答人们提出的问题,不过Chatgpt参数量,规模,训练代价都很昂贵。 幸运的是,出现了开源的一些相对小的模型,可以在本地或…...
深入理解JVM虚拟机第十九篇:JVM字节码中方法内部的结构和与局部变量表中变量槽的介绍
大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。 孙哥链接:孙哥个人主页 作者简介:一个颜值99分,只比孙哥差一点的程序员 本专栏简介:话不多说,让我们一起干翻JVM 本文章简介:话不多说,让我们讲清楚虚拟机栈存储结构和运行原理 文章目…...
windows好玩的cmd命令
颜色 后边的数字查表吧,反正我是喜欢一个随机的数字 color 01MAC getmac /v更新主机IP地址 通过DHCP更新 ipconfig /release ipconfig /renew改标题 title code with 你想要的标题...
线扫相机DALSA--常见问题四:修改相机参数,参数保存无效情况
该问题是操作不当,未按照正常步骤保存参数所致,相机为RAM机制,参数需保存在采集卡的ROM内。 保存参数步骤: ①首先将相机参数保存至User Set1; ②然后回到Board(采集卡)参数设置区,鼠标选中Basic Timing&a…...
linux中用date命令获取昨天、明天或多天前后的日期
在实际操作中,一些脚本中会调用明天,或者昨天,或更多天前的日期,本文将叙述讲述用date命令实现时间的显示。在Linux系统中用man date -d 查询的参数说的比较模糊,以下举例进一步说明: # man date -d, --da…...
【无标题】360压缩软件怎么用?超级好用!
360压缩是一款功能强大的解压缩软件,如何用它压缩文件呢?下面给出了详细的操作步骤。 一、360压缩详细步骤 1、下载软件后,在电脑上右击需要压缩的文件,在弹出的菜单中点击【添加到压缩文件】选项。 2、在360压缩窗口中按需设置相…...
一图搞懂傅里叶变换(FT)、DTFT、DFS和DFT之间的关系
自然界中的信号都是模拟信号,计算机无法处理,因此我们会基于奈奎斯特定理对模拟信号采样得到数字信号。 但是我们发现,即便是经过采样,在时域上得到了数字信号,而在频域上还是连续信号。 因此我们可以在时域中选取N点…...
行情分析——加密货币市场大盘走势(11.7)
大饼昨日下跌过后开始有回调的迹象,现在还是在做指标修复,大饼的策略保持逢低做多。稳健的依然是不碰,目前涨不上去,跌不下来。 以太昨天给的策略,依然有效,现在以太坊开始回调。 目前来看,回踩…...
阿里微服务质量保障系列:故障演练
对于很多大型企业(如阿里巴巴)来说,经过多年的技术演进,系统工具和架构已经高度垂直化,服务器规模也达到了比较大的体量。当服务规模大于一定量(如10000台)时,小概率的硬件故障每天都会发生。这时如果需要人的干预,系统就无法可靠的伸缩。 为此每一层的系统都会面向失…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
