【制作100个unity游戏之26】unity2d横版卷轴动作类游戏6(附带项目源码)

最终效果

在这里插入图片描述

系列导航

文章目录

  • 最终效果
  • 系列导航
  • 前言
  • 敌人
    • 动画配置
    • 撞墙判断
    • 敌人基本AI逻辑实现
  • 野猪受伤死亡
  • 死亡
  • 敌人死亡时,还是会对人物产生伤害
  • 有限状态机&抽象类多态 定义不同状态的敌人行为
  • 防止野猪在悬崖掉下去
  • 野猪的追击状态的转换
    • 敌人主动查找玩家
  • 追击状态
    • 效果
  • 完善追击状态脚本
    • 追击状态 修改速度 播放奔跑动画 敌人碰壁直接转向不等待
    • 野猪丢失目标,一段时间后回到默认状态
  • 野猪朝我们冲锋时,正面受到攻击 无法击退 背面受到攻击又会击退很远
  • 制作多个敌人
  • 源码
  • 完结

前言

欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第26篇中,我们将探索如何用unity制作一个unity2d横版卷轴动作类游戏,我会附带项目源码,以便你更好理解它。

本节主要是完善敌人AI,动画,有限状态机控制敌人状态切换,制作多个敌人

敌人

动画配置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

撞墙判断

修改PhysicsCheck ,地面检测和撞墙判断

public class PhysicsCheck : MonoBehaviour
{public Vector2 bottomOffset;// 检测圆形底部偏移量public float checkRadius; // 圆形检测半径public LayerMask groundLayer; // 地面图层public bool isGround; // 是否在地面上private Vector2 leftOffset;private Vector2 rightOffset;public bool touchLeftWall;//是否接触到左墙壁public bool touchRightWall;//是否接触到右墙壁private CapsuleCollider2D coll;public bool manual; //是否手动配置private void Awake() {coll = GetComponent<CapsuleCollider2D>();//如果不是手动配置偏移量,则根据 Collider 的位置和大小计算左右偏移量if(!manual){Vector2 collPos = coll.offset * (Vector2)transform.localScale;rightOffset = new Vector2(collPos.x + coll.size.x / 2 + checkRadius, coll.size.y / 2);leftOffset = new Vector2(collPos.x - coll.size.x / 2 - checkRadius, coll.size.y / 2);}}private void Update(){//根据物体的 x 轴缩放来更新偏移量Check();}private void FixedUpdate() {UpdateOffset(transform.localScale.x);}private void UpdateOffset(float facedir){// 根据物体的 x 轴缩放更新左右偏移量if(!manual){Vector2 collPos = coll.offset * facedir;rightOffset = new Vector2(collPos.x + coll.size.x / 2 + checkRadius, coll.size.y / 2);leftOffset = new Vector2(collPos.x - coll.size.x / 2 - checkRadius, coll.size.y / 2);}else{leftOffset = leftOffset * facedir;rightOffset = rightOffset * facedir;}}public void Check(){// 检测是否在地面上isGround = Physics2D.OverlapCircle(transform.position + bottomOffset, checkRadius, groundLayer);//墙壁判断touchLeftWall = Physics2D.OverlapCircle((Vector2)transform.position + leftOffset, checkRadius, groundLayer);touchRightWall = Physics2D.OverlapCircle((Vector2)transform.position + rightOffset, checkRadius, groundLayer);}private void OnDrawGizmosSelected(){// 在 Scene 视图中绘制检测范围Gizmos.DrawWireSphere((Vector2)transform.position + bottomOffset, checkRadius);Gizmos.DrawWireSphere((Vector2)transform.position + leftOffset, checkRadius);Gizmos.DrawWireSphere((Vector2)transform.position + rightOffset, checkRadius);}
}

配置
在这里插入图片描述
运行效果,程序会自动找到碰撞体的位置
在这里插入图片描述
前面设置了地面碰撞体复合,只有外框才是碰撞区域,如果敌人快速通过可能检测不到墙壁。可以修改为瓦片地图碰撞几何类型为Polygons,将瓦片地图全部做为一个碰撞体整体。
在这里插入图片描述

敌人基本AI逻辑实现

新增Enemy代码 ,控制敌人基本移动和动画,碰壁等待一段时间,再回头

public class Enemy : MonoBehaviour
{Rigidbody2D rb;protected Animator anim;private PhysicsCheck physicsCheck;[Header("基本参数")]public float normalSpeed; // 常规速度public float chaseSpeed; // 追逐速度public float currentSpeed; // 当前速度public Vector3 faceDir; // 面向方向public bool wait;//是否等待public float waitTime;//等待时长private void Awake(){rb = GetComponent<Rigidbody2D>();anim = GetComponent<Animator>();physicsCheck = GetComponent<PhysicsCheck>();currentSpeed = normalSpeed;}private void Update(){//面向方向 默认右边为正方向faceDir = new Vector3(-transform.localScale.x, 0, 0);//按敌人面向和撞墙 切换敌人状态if((physicsCheck.touchLeftWall && faceDir.x < 0  || physicsCheck.touchRightWall && faceDir.x > 0) && !wait){wait = true; // 设为等待状态anim.SetBool("walk", false);//禁止走路动画StartCoroutine(WaitTimer()); // 启动等待计时}}private void FixedUpdate(){if(!wait) Move();}//移动方法public virtual void Move(){anim.SetBool("walk", true);//播放走路动画rb.velocity = new Vector2(currentSpeed * faceDir.x * Time.deltaTime, rb.velocity.y);}//等待计时携程private IEnumerator WaitTimer(){yield return new WaitForSeconds(waitTime); // 等待时间transform.localScale = new Vector3(faceDir.x, transform.localScale.y, transform.localScale.z);//转向wait = false; // 取消等待状态}
}

配置
在这里插入图片描述

效果
在这里插入图片描述

野猪受伤死亡

切割图片,图片没有死亡动画,这里可以选择使用和受伤一样的动画
在这里插入图片描述
修改死亡动画多一个渐变消失
在这里插入图片描述
受伤和完整播放完受伤动画退出
在这里插入图片描述
在这里插入图片描述

死亡
在这里插入图片描述

修改Enemy,实现受伤面向玩家,

public bool isHurt;//是否受伤
public float hurtForce;//击退力
public float waitHitTime = 0.5f;//受伤时长private void FixedUpdate()
{if(!wait && !isHurt) Move();
}//受伤
public void OnTakeDamage(Transform attackTrans){// attacker = attackTrans;isHurt = true;anim.SetTrigger("hit");//转身面向攻击者if (attackTrans.position.x - transform.position.x > 0)transform.localScale = new Vector3(-Mathf.Abs(transform.localScale.x),transform.localScale.y,transform.localScale.z);if (attackTrans.position.x - transform.position.x < 0)transform.localScale = new Vector3(Mathf.Abs(transform.localScale.x),transform.localScale.y,transform.localScale.z);//受伤被击退Vector2 dir = new Vector2(transform.position.x - attackTrans.position.x, 0).normalized;rb.AddForce(dir * hurtForce, ForceMode2D.Impulse);//等待切换回正常状态StartCoroutine(OnWaitHit());
}//等待切换回正常状态
private IEnumerator OnWaitHit()
{yield return new WaitForSeconds(waitHitTime);isHurt = false;
}

修改配置
在这里插入图片描述

配置受伤事件
在这里插入图片描述

效果
在这里插入图片描述

死亡

修改Enemy

public bool isDead;//是否死亡private void FixedUpdate()
{if(!wait && !isHurt && !isDead) Move();
}//死亡
public void OnDead(){isDead = true;anim.SetBool("isDead", true);//销毁StartCoroutine(OnDeadDestroy());
}private IEnumerator OnDeadDestroy()
{yield return new WaitForSeconds(1f);Destroy(gameObject);
}

配置
在这里插入图片描述
效果
在这里插入图片描述

敌人死亡时,还是会对人物产生伤害

取消玩家和Ignore Raycast的碰撞
在这里插入图片描述

修改Enemy,死亡修改图层

//死亡
public void OnDead(){gameObject.layer = 2;//修改图层,避免敌人死亡时,还是会对人物产生伤害isDead = true;anim.SetBool("isDead", true);//销毁StartCoroutine(OnDeadDestroy());
}

效果
在这里插入图片描述

有限状态机&抽象类多态 定义不同状态的敌人行为

新增一个抽象基类,定义了所有状态类的基本结构。包括进入状态、逻辑更新、物理更新和退出状态等方法。

public abstract class BaseState
{protected Enemy currentEnemy; // 当前敌人public abstract void OnEnter(Enemy enemy); // 进入状态时的方法public abstract void LogicUpdate(); // 逻辑更新方法public abstract void PhysicsUpdate(); // 物理更新方法public abstract void OnExit(); // 退出状态时的方法
}

新增BoarPatrolState,这是野猪的巡逻状态类,继承自BaseState类,并实现了具体的状态行为。

  • 在OnEnter方法中,初始化当前敌人(野猪)对象。
  • LogicUpdate方法中,根据敌人面朝方向和是否撞墙来切换敌人状态。
  • PhysicsUpdate方法中,执行物理更新的逻辑。
  • OnExit方法中,处理退出状态时的逻辑。
public class BoarPatrolState : BaseState
{public override void OnEnter(Enemy enemy){currentEnemy = enemy;}public override void LogicUpdate(){//按敌人面向和撞墙 切换敌人状态if (currentEnemy.physicsCheck.touchLeftWall && currentEnemy.faceDir.x < 0 || currentEnemy.physicsCheck.touchRightWall && currentEnemy.faceDir.x > 0){currentEnemy.wait = true; // 设为等待状态currentEnemy.anim.SetBool("walk", false);//禁止走路动画}}public override void PhysicsUpdate(){}public override void OnExit(){currentEnemy.anim.SetBool("walk", false);}
}

修改Enemy类,作为所有敌人的父类,这个类表示敌人的基本行为,包括移动、受伤、死亡等。使用了状态机模式来管理敌人的状态,包括巡逻状态和追逐状态。在Update和FixedUpdate方法中,通过当前状态对象来执行逻辑更新和物理更新。

public bool isWaitTimer;//是否开始等待计时[Header("状态机")]
private BaseState currentState;// 当前状态
protected BaseState patrolState;// 巡逻状态
protected BaseState ChaseState;// 追逐状态//...private void OnEnable()
{currentState = patrolState;currentState.OnEnter(this);
}private void Update()
{//面向方向 默认右边为正方向faceDir = new Vector3(-transform.localScale.x, 0, 0);currentState.LogicUpdate();}private void FixedUpdate()
{if (!wait && !isHurt && !isDead) Move();currentState.PhysicsUpdate();if (wait && !isWaitTimer){isWaitTimer = true;StartCoroutine(WaitTimer()); // 启动等待计时}
}private void OnDisable()
{currentState.OnExit();
}//...

新增Boar,继承自Enemy类,表示野猪这种特定类型的敌人。在Awake方法中初始化了野猪的巡逻状态。

public class Boar : Enemy {protected override void Awake() {base.Awake();patrolState = new BoarPatrolState();// 设置野猪的巡逻状态}
}

野猪敌人,重新挂载Boar脚本,而不是之前的Enemy ,记得Character的受伤死亡事件也要重新配置
在这里插入图片描述

运行,看看程序是否能跑通
在这里插入图片描述

防止野猪在悬崖掉下去

修改BoarPatrolState,我们直接用脚底地面检测来判断,野猪前方没有地面(即是悬崖),等待回头即可

public override void LogicUpdate()
{//按敌人面向和撞墙切换敌人状态if (!currentEnemy.physicsCheck.isGround|| currentEnemy.physicsCheck.touchLeftWall && currentEnemy.faceDir.x < 0|| currentEnemy.physicsCheck.touchRightWall && currentEnemy.faceDir.x > 0){currentEnemy.wait = true; // 设为等待状态currentEnemy.anim.SetBool("walk", false);//禁止走路动画}else{currentEnemy.wait = false;currentEnemy.anim.SetBool("walk", true);//播放走路动画}
}

修改PhysicsCheck,也就是地面检测多一个* transform.localScale.x,确保敌人转向时,地面检点也跟着偏过去

在这里插入图片描述
记得修改检测偏移到野猪头的前面位置
在这里插入图片描述
效果
请添加图片描述

野猪的追击状态的转换

敌人主动查找玩家

修改Enemy,原理就是向前发射一个方块检测玩家

[Header("主动发现玩家检测")]
public Vector2 centerOffset;//检测框的中心偏移量
public Vector2 checkSize;//检测框的尺寸
public float checkDistance;//检测的距离
public LayerMask attackLayer;//检测图层//发现玩家
public bool FoundPlayer()
{return Physics2D.BoxCast(transform.position + (Vector3)centerOffset, checkSize, 0, faceDir, checkDistance, attackLayer);
}//在场景显示检查距离
private void OnDrawGizmosSelected()
{Gizmos.color = Color.red; // 设置绘制颜色为黄色,你可以根据需要选择其他颜色Gizmos.DrawWireCube(transform.position + (Vector3)centerOffset + new Vector3(-transform.localScale.x * checkDistance, 0, 0), checkSize); // 绘制一个边框的立方体表示检测区域
}

配置
在这里插入图片描述

追击状态

前面我们已经创建了野猪的巡逻状态脚本BoarPatrolState,我们同理再创建一个追击状态脚本即可

新增BoarChaseState,定义野猪追击状态

public class BoarChaseState : BaseState
{public override void OnEnter(Enemy enemy){currentEnemy = enemy;}public override void LogicUpdate(){}public override void PhysicsUpdate(){}public override void OnExit(){}
}

修改Boar ,赋值野猪追击状态

public class Boar : Enemy {protected override void Awake() {base.Awake();patrolState = new BoarPatrolState();// 设置野猪的巡逻状态chaseState = new BoarChaseState();// 设置野猪的追击状态}
}

新增枚举,定义敌人不同的状态

public enum EnemyState
{Patrol, Chase, Skill
}

修改Enemy,定义切换敌人状态,方法

//切换敌人状态
public void SwitchState(EnemyState state)
{var newState = state switch{EnemyState.Patrol => patrolState,EnemyState.Chase => chaseState,_ => null};currentState.OnExit();//退出上一个状态currentState = newState; //赋值新状态currentState.OnEnter(this);//开始新的状态
}

修改BoarPatrolState,发现玩家切换野猪为追击状态

public override void LogicUpdate()
{if(currentEnemy.FoundPlayer()){Debug.Log("发现玩家");currentEnemy.SwitchState(EnemyState.Chase);}//...
}

效果

在这里插入图片描述

完善追击状态脚本

追击状态 修改速度 播放奔跑动画 敌人碰壁直接转向不等待

修改BoarChaseState

public class BoarChaseState : BaseState
{public override void OnEnter(Enemy enemy){currentEnemy = enemy;currentEnemy.currentSpeed = currentEnemy.chaseSpeed;//追击速度currentEnemy.anim.SetBool("run", true);//奔跑动画}public override void LogicUpdate(){// 如果超过等待时间,切换为默认巡逻状态if (currentEnemy.timeSincePlayerLost >= currentEnemy.maxTimeWithoutPlayer){currentEnemy.SwitchState(EnemyState.Patrol);}//按敌人 是否在悬崖边 面向和撞墙 切换敌人状态if (!currentEnemy.physicsCheck.isGround|| currentEnemy.physicsCheck.touchLeftWall && currentEnemy.faceDir.x < 0|| currentEnemy.physicsCheck.touchRightWall && currentEnemy.faceDir.x > 0){currentEnemy.transform.localScale = new Vector3(currentEnemy.faceDir.x, currentEnemy.transform.localScale.y, currentEnemy.transform.localScale.z);//转向}}public override void PhysicsUpdate(){}public override void OnExit(){currentEnemy.anim.SetBool("run", false);}
}

野猪丢失目标,一段时间后回到默认状态

修改Enemy

[Header("丢失目标计时器参数")]
public float lostTimeCounter = 0f;//计时器
public float lostTime = 2f; // 丢失目标时间private void FixedUpdate()
{//...//计时器Timer();
}//追击计时器
private void Timer()
{// 如果发现玩家,则重置计时器if (FoundPlayer()){lostTimeCounter = 0f;}else{if (lostTimeCounter >= lostTime){lostTimeCounter = lostTime;}else{lostTimeCounter += Time.deltaTime;}}
}

修改BoarChaseState

public override void LogicUpdate()
{// 如果超过等待时间,切换为默认巡逻状态if (currentEnemy.lostTimeCounter >= currentEnemy.lostTime){currentEnemy.SwitchState(EnemyState.Patrol);}//...}

修改BoarPatrolState,速度改回默认速度

public override void OnEnter(Enemy enemy)
{currentEnemy = enemy;currentEnemy.currentSpeed = currentEnemy.normalSpeed;
}

配置丢失目标时间
在这里插入图片描述
效果
在这里插入图片描述

野猪朝我们冲锋时,正面受到攻击 无法击退 背面受到攻击又会击退很远

因为冲锋的力也有一个向前的力

修改Enemy ,击退前先把敌人x轴的力停下来

//受伤
public void OnTakeDamage(Transform attackTrans)
{// 。。。//受伤被击退Vector2 dir = new Vector2(transform.position.x - attackTrans.position.x, 0).normalized;rb.velocity = new Vector2(0, rb.velocity.y);//先取消刚体x轴的力rb.AddForce(dir * hurtForce, ForceMode2D.Impulse);//等待切换回正常状态StartCoroutine(OnWaitHit());
}

效果
在这里插入图片描述

制作多个敌人

制作多个敌人可以参考前面的方法,继承Enemy,重新定义各种状态即可,比如巡逻状态,追击状态

源码

源码不出意外的话我会放在最后一节

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

在这里插入图片描述

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

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

相关文章

基于微信小程序+JAVA Springboot 实现的【智慧乡村旅游服务平台】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 基于微信小程序的智慧乡村旅游服务平台的设计与实现 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; Java SSM框架数据库&#xff1a; MySQL前端技术&#xff1a; 微信开发者工具、uni-app其他技术&#xff1a…

8B10B编码(高速收发器五)

1、8B10B解决的问题 8B10B编码是1983年IBM公司提出的传输编码标准&#xff0c;通常用于高速收发器中&#xff0c;常见的JESD204B、SATA等接口协议&#xff0c;使用查表就可以实现编码和解码。 在这些高速收发器的接收端需要通过CDR技术去恢复时钟与数据的相位关系&#xff0c;在…

Linux day6 yum下载,systemctl,

yum命令 yum [-y] install wget 通过yum下载wget小工具 -y的意思是&#xff0c;如果有询问&#xff0c;自动确认&#xff08;总是允许&#xff09;。 yum remove wget 也可以通过这种方式卸载wget

PyQt5 中的 List View

文章目录 1. 基础概念2. 创建 List View2.1 PyQt5 中一个简单的 List View 实例2.2 代码解释2.3 运行结果 3. 数据模型3.1 标准模型3.2 自定义模型 4. 自定义 List View4.1 使用样式表 (QSS)4.2 设置项委托 (Item Delegate) 5.事件处理6. 与数据交互6.1 添加数据6.2 删除数据6.…

echers配置项:数据过多时,折叠数据缩放查看

当数据过多时&#xff0c;如上图所示的时间点&#xff0c;会自动折叠&#xff0c;此时鼠标缩放还不起作用&#xff0c;我们配置如下代码 let option {dataZoom: [{startValue: 05:00}, // 这个值需要跟 第一条 时间数据对应上{type: inside}], }配置后&#xff0c;就可以进行…

echers配置项:折线图,折现的颜色修改

如上图所示&#xff1a;红框内的折现颜色修改&#xff0c;并隐藏默认的点 series: [{data: [1, 230, 224, 218, 135, 147, 760,1500,1200,2500,2000],type: line,lineStyle: {color: #00DBFE // 折现颜色},symbol:none, // 不显示点smooth: true, // 折现角度&#xff1a;圆滑…

5W 3KVAC隔离 宽电压输入 AC/DC 电源模块——TP05AL系列

TP05AL系列产品是一款经济型开板式开关电源&#xff0c;输出功率为5W&#xff0c;具有可靠性高、小体积、性价比高等特点&#xff0c;广泛用于工控和电力仪器、仪表、智能家居等相关行业。

通过 Apple Vision Pro 释放创造力:深入研究空间计算

Apple 最新进军空间计算领域的 Apple Vision Pro,标志着重新定义我们与技术交互方式的重大飞跃。空间计算超越了传统界限,允许用户以无缝集成到物理世界的方式参与 2D 和 3D 内容。 我们可以关注两种类型的体验: 在空间中渲染 2D 内容。这涉及将现有设备窗口投影到空间领域…

通过C++和libcurl下载网易云音乐音频文件的5个简单步骤

概述 在网络编程中&#xff0c;使用C和libcurl库下载文件是一项常见的任务。网易云音乐作为中国领先的在线音乐服务平台之一&#xff0c;以其丰富的音乐资源、优质的音质和智能推荐系统而广受欢迎。由于其平台提供了大量的正版音乐资源&#xff0c;用户在下载音频文件时可能会…

开源发布:JAVA版低代码报文网关-通过简单配置快速对接银行渠道

大家好&#xff0c;我是隐墨星辰&#xff0c;自从《百图解码支付系统设计与实现》专栏中的文章《图解支付报文网关&#xff1a;一种低代码报文网关的设计思路与核心代码实现》发表以来&#xff0c;不少同学留言或私信问我如何实现&#xff0c;说是虽然看懂了思路&#xff0c;但…

pycharm 里面安装 codeium 插件的时候,不能够弹出登录界面

pycharm 里面安装 codeium 插件的时候&#xff0c;不能够弹出登录界面 pycharm 里面安装 codeium 插件的时候&#xff0c;不能够弹出登录界面--解决如下A pycharm 里面安装 codeium 插件的时候&#xff0c;不能够弹出登录界面–解决如下 #踩坑/pycharm/codeium插件无法登录 安…

制氧机负离子的作用与好处深度解析

随着现代生活节奏的加快&#xff0c;空气质量逐渐下降&#xff0c;人们对健康生活的追求也日益增强。在这样的背景下&#xff0c;制氧机负离子功能因其多重健康效益而备受关注。本文将深入探讨制氧机负离子的作用与功效&#xff0c;帮助大家更好地了解并应用这一健康科技。 我们…

单片机烧录程序时“DTR的低电平复位,RTS高电平进入bootloader”有关的串口Modem联络信号

烧录程序时常见DTR和RTS引脚 参考&#xff0c;参考视频 因为常常使用的都是串口下载程序&#xff0c;常用的芯片CH340系列&#xff0c;下图中标红的引脚是MODEM联络信号&#xff0c;其中常见的DTR和RTS就是常见的串口Modem网络输出信号&#xff0c;也就是通过烧录软件控制的接…

深入解析Wireshark1:从捕获到分析,一网打尽数据包之旅

目录 1 认识 Wireshark 1.1 选择网卡界面 1.2 捕获数据包界面 1.3 常用按钮功能介绍 1.4 数据包列表信息 1.5 数据包详细信息 2 数据包案例分析 Frame: 物理层的数据帧概况 Ethernet II: 数据链路层以太网帧头部信息 Internet Protocol Version 4 (IPv4): 互联网层IP…

Git系列:git restore 高效恢复代码的技巧与实践

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

AndroidStudio集成高德地图后出现黑屏并报错

报错内容为&#xff1a;No implementation found for void com.autonavi.base.ae.gmap.GLMapEngine.nativeMainThreadTrigger(int, long) (tried Java_com_autonavi_base_ae_gmap_GLMapEngine_nativeMainThreadTrigger and Java_com_autonavi_base_ae_gmap_GLMapEngine_nativeM…

爱吃香蕉的珂珂

题目链接 爱吃香蕉的珂珂 题目描述 注意点 piles.length < h < 10^9如果某堆香蕉少于k根&#xff0c;将吃掉这堆的所有香蕉&#xff0c;然后这一小时内不会再吃更多的香蕉返回可以在 h 小时内吃掉所有香蕉的最小速度 k&#xff08;k 为整数&#xff09; 解答思路 二…

数据分析实例——搭建电商的指标体系||对应功能开发需要接入的电商API接口说明

前言&#xff1a; 在日常工作中&#xff0c;数据分析中常常涉及搭建指标体系&#xff0c;搭建电商需要接入的电商API接口本文主要以电商为案例&#xff0c;来讲讲如何搭建指标体系。 指标体系的定义&#xff1a; 指标体系是由一系列指标组成的&#xff0c;这些指标是基于不同的…

React 第三十六章 Scheduler 任务调度

Scheduler 用于在 React 应用中进行任务调度。它可以帮助开发人员在处理复杂的任务和操作时更好地管理和优化性能。 关于 Scheduler 在React 如何渲染的可以参考 React 第三十四章 React 渲染流程 下面我们根据流程图先简单的了解 Scheduler 的调度过程 Scheduler 维护两个队…

C++入门系列-赋值运算符重载

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 赋值运算符重载 运算符重载 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊函数名的函数&#xff0c;也具有其返回值类型&#xff0c;函数名字以及参…