当前位置: 首页 > news >正文

Unity教程(九)角色攻击的改进

Unity开发2D类银河恶魔城游戏学习笔记

Unity教程(零)Unity和VS的使用相关内容
Unity教程(一)开始学习状态机
Unity教程(二)角色移动的实现
Unity教程(三)角色跳跃的实现
Unity教程(四)碰撞检测
Unity教程(五)角色冲刺的实现
Unity教程(六)角色滑墙的实现
Unity教程(七)角色蹬墙跳的实现
Unity教程(八)角色攻击的基本实现
Unity教程(九)角色攻击的改进

Unity教程(十)Tile Palette搭建平台关卡


如果你更习惯用知乎
Unity开发2D类银河恶魔城游戏学习笔记目录


文章目录

  • Unity开发2D类银河恶魔城游戏学习笔记
  • 前言
  • 一、概述
  • 二、基础攻击的改进
    • (1)调整动画提升流畅度
    • (2)解决攻击时滑动的问题
    • (3)解决两次攻击间角色移动的问题
    • (4)攻击间移动
    • (5)添加攻击方向
    • (6)加速操作(不需要做)
  • 三、代码整理
  • 总结 完整代码
    • Player.cs
    • PlayerPrimaryAttackState.cs
    • PlayerIdleState.cs


前言

本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记,如有错误,欢迎指正。

本节进行角色基本攻击的改进。
对应b站视频:
【Unity教程】从0编程制作类银河恶魔城游戏P40
【Unity教程】从0编程制作类银河恶魔城游戏P41


一、概述

本节主要进行角色基本攻击的改进。
空闲状态到移动状态之间的转换添加条件 ! isBusy
在这里插入图片描述
本节改进了基本攻击的小问题,添加了攻击移动和攻击方向,提升了动画流畅度。在最后对代码进行了一些整理。整体结构如下:
在这里插入图片描述


二、基础攻击的改进

(1)调整动画提升流畅度

调整三个攻击动画的采样率,并且将最后一个攻击动画事件提前。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)解决攻击时滑动的问题

现在我们攻击时角色会来回滑动,因为我们的角色还保持着移动的速度但已经播放攻击动画了。
在这里插入图片描述
这里教程中的解决方式是在攻击时将角色速度置为0。
但我个人感觉这种处理方式会让攻击缺少一些灵活性。但如果想实现边移动边攻击就需要有另外的动画和另外的逻辑来实现,需要另行设计,所以在此先按教程中的实现。
此外,我们可以在进入时给stateTimer赋一个值,让角色停顿一下再攻击,做出惯性的效果。
在PlayerPrimaryAttack中修改:

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);stateTimer = 0.1f;}// 更新public override void Update(){base.Update();if (stateTimer < 0)rb.velocity = new Vector2(0, 0);if(triggerCalled)stateMachine.ChangeState(player.idleState);}

在这里插入图片描述

(3)解决两次攻击间角色移动的问题

我依然认为这种处理方法缺乏灵活性,但可以先学习一下他的处理方式。
如果需要解决这个问题,我们可以使用协程。我参照了以下文章的讲解:
进程、线程和协程之间的区别和联系
Unity 协程(Coroutine)原理与用法详解
Unity官方手册

协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义。

启动协程:
StartCoroutine(IEnumerator routine:通过方法形式调用
StartCoroutine(string methodName,object values):带参数的通过方法名进行调用

停止携程:
StopCoroutine(string methodName:通过方法名(字符串)来进行
StopCoroutine(IEnumerator routine:通过方法形式来调用
StopCoroutine(Coroutine routine):通过指定的协程来关闭

yield方法:
yield return null; 暂停协程等待下一帧继续执行
yield return 0或其他数字; 暂停协程等待下一帧继续执行
yield return new WairForSeconds(时间); 等待规定时间后继续执行
yield return StartCoroutine(“协程方法名”); 开启一个协程(嵌套协程)

在Player中创建一个参数isBusy,并定义BusyFor函数

    public bool isBusy { get; private set; }public IEnumerator BusyFor(float _seconds){isBusy = true;yield return new WaitForSeconds(_seconds);isBusy = false;}

在每次攻击结束时调用,在PlayerPriamaryAttack

    //退出public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", 0.15f);comboCounter++;lastTimeAttacked = Time.time;}

然后给空闲状态转到移动状态添加一个 ! Busy 的条件:

    //更新public override void Update(){base.Update();//切换到移动状态if(xInput!=0 && !player.isBusy)stateMachine.ChangeState(player.moveState);}

在攻击期间即使我一直按着移动键,角色也不能移动了,效果如下:
在这里插入图片描述

(4)攻击间移动

给连击中的每一段设置一个位移。
在Player中添加变量攻击位移数组

    [Header("Attack details")]public float[] attackMovement;

在开始攻击时设置位移

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);player.SetVelocity(player.attackMovement[comboCounter] * player.facingDir, rb.velocity.y);stateTimer = 0.1f;}

给数列赋值,调整数值直到你想要的效果
在这里插入图片描述
在这里插入图片描述

(5)添加攻击方向

现在的攻击还有一个小问题,在攻击后马上按相反方向键向角色身后攻击,我们会发现角色完全没有转向。
因为我们在攻击时始终是向着角色面向的方向,没有翻转。
我们在PlayerPrimaryAttack中添加这个功能:

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);float attackDir = player.facingDir;if (xInput != 0)attackDir = xInput;player.SetVelocity(player.attackMovement[comboCounter].x * attackDir, player.attackMovement[comboCounter].y);stateTimer = 0.1f;}

当没有输入时,向角色面向方向攻击;当有输入时,向输入方向攻击。现在角色可以迅速回身攻击了。
在这里插入图片描述

(6)加速操作(不需要做)

教程中顺便讲到了使所有动画加速的操作。这个操作可以实现不同武器不同攻速等操作,或者实现整体加速。
用player.anim.speed 进行实现,在进入攻击状态时加速,在退出时恢复原速。

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);player.anim.speed = 3.0f;player.SetVelocity(player.attackMovement[comboCounter].x * player.facingDir, player.attackMovement[comboCounter].y);stateTimer = 0.1f;}//退出public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", 0.15f);player.anim.speed = 1.0f;comboCounter++;lastTimeAttacked = Time.time;}

为了效果明显,我调了三倍速。
在这里插入图片描述

三、代码整理

速度置零的操作,我们在Player中写一个函数ZeroVelocity()用来调用

    //速度置零public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);

在PlayerPrimaryAttack中改为调用函数

//PlayerPrimaryAttackState:基本攻击状态// 更新public override void Update(){base.Update();if (stateTimer < 0)player.ZeroVelocity();if(triggerCalled)stateMachine.ChangeState(player.idleState);}

Player中代码划分区域
速度设置

    #region 速度设置//速度置零public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);//设置速度public void SetVelocity(float _xVelocity, float _yVelocity){rb.velocity = new Vector2(_xVelocity, _yVelocity);FlipController(_xVelocity);}#endregion

翻转

    #region 翻转//翻转实现public void Flip(){facingDir = -1 * facingDir;facingRight = !facingRight;transform.Rotate(0, 180, 0);}//翻转控制public void FlipController(float _x){if (_x > 0 && !facingRight)Flip();else if(_x < 0 && facingRight)Flip();}#endregion

碰撞

    #region 碰撞//碰撞检测public bool isGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);public bool isWallDetected() => Physics2D.Raycast(wallCheck.position,Vector2.right * facingDir,wallCheckDistance,whatIsGround);//绘制碰撞检测private void OnDrawGizmos(){Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x+ wallCheckDistance, wallCheck.position.y));}#endregion

在这里插入图片描述
给PlayerPrimaryAttack改名为PlayerPrimaryAttackState
右键状态名->重命名->Enter
在这里插入图片描述
在这里插入图片描述

总结 完整代码

Player.cs

添加攻击位移变量
添加isBusy和协程

//Player:玩家
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour
{[Header("Attack details")]public Vector2[] attackMovement;public bool isBusy { get; private set; }[Header("Move Info")]public float moveSpeed = 8f;public int facingDir { get; private set; } = 1;private bool facingRight = true;public float jumpForce = 12f;[Header("Dash Info")][SerializeField] private float dashCoolDown;private float dashUsageTimer;public float dashSpeed=25f;public float dashDuration=0.2f;public float dashDir {  get; private set; }[Header("Collision Info")][SerializeField] private Transform groundCheck;[SerializeField] private float groundCheckDistance;[SerializeField] private Transform wallCheck;[SerializeField] private float wallCheckDistance;[SerializeField] private LayerMask whatIsGround;#region 组件public Animator anim { get; private set; }public Rigidbody2D rb { get; private set; }#endregion#region 状态public PlayerStateMachine StateMachine { get; private set; }public PlayerIdleState idleState { get; private set; }public PlayerMoveState moveState { get; private set; }public PlayerJumpState jumpState { get; private set; }public PlayerAirState airState { get; private set; }public PlayerDashState dashState { get; private set; }public PlayerWallSlideState wallSlideState { get; private set; }public PlayerWallJumpState wallJumpState { get; private set; }public PlayerPrimaryAttack primaryAttack { get; private set; }  #endregion//创建对象private void Awake(){StateMachine = new PlayerStateMachine();idleState = new PlayerIdleState(StateMachine, this, "Idle");moveState = new PlayerMoveState(StateMachine, this, "Move");jumpState = new PlayerJumpState(StateMachine, this, "Jump");airState = new PlayerAirState(StateMachine, this, "Jump");dashState = new PlayerDashState(StateMachine, this, "Dash");wallSlideState = new PlayerWallSlideState(StateMachine, this, "WallSlide");wallJumpState = new PlayerWallJumpState(StateMachine, this, "Jump");primaryAttack = new PlayerPrimaryAttack(StateMachine, this, "Attack");anim = GetComponentInChildren<Animator>();rb = GetComponent<Rigidbody2D>();}// 设置初始状态private void Start(){StateMachine.Initialize(idleState);}// 更新private void Update(){StateMachine.currentState.Update();CheckForDashInput();}public IEnumerator BusyFor(float _seconds){isBusy = true;yield return new WaitForSeconds(_seconds);isBusy = false;}//设置触发器public void AnimationTrigger() => StateMachine.currentState.AnimationFinishTrigger();//检查冲刺输入public void CheckForDashInput(){dashUsageTimer -= Time.deltaTime;if (Input.GetKeyDown(KeyCode.LeftShift) && dashUsageTimer<0){dashUsageTimer = dashCoolDown;dashDir = Input.GetAxisRaw("Horizontal");if (dashDir == 0)dashDir = facingDir;StateMachine.ChangeState(dashState);}}#region 速度设置//速度置零public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);//设置速度public void SetVelocity(float _xVelocity, float _yVelocity){rb.velocity = new Vector2(_xVelocity, _yVelocity);FlipController(_xVelocity);}#endregion#region 翻转//翻转实现public void Flip(){facingDir = -1 * facingDir;facingRight = !facingRight;transform.Rotate(0, 180, 0);}//翻转控制public void FlipController(float _x){if (_x > 0 && !facingRight)Flip();else if(_x < 0 && facingRight)Flip();}#endregion#region 碰撞//碰撞检测public bool isGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);public bool isWallDetected() => Physics2D.Raycast(wallCheck.position,Vector2.right * facingDir,wallCheckDistance,whatIsGround);//绘制碰撞检测private void OnDrawGizmos(){Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x+ wallCheckDistance, wallCheck.position.y));}#endregion
}

PlayerPrimaryAttackState.cs

攻击时速度置零
添加协程
添加攻击位移
添加攻击方向

//PlayerPrimaryAttackState:基本攻击状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerPrimaryAttackState : PlayerState
{private int comboCounter;private float lastTimeAttacked;private float comboWindow = 2;public PlayerPrimaryAttackState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName){}//进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);float attackDir = player.facingDir;if (xInput != 0)attackDir = xInput;player.SetVelocity(player.attackMovement[comboCounter].x * attackDir, player.attackMovement[comboCounter].y);stateTimer = 0.1f;}//退出public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", 0.15f);comboCounter++;lastTimeAttacked = Time.time;}// 更新public override void Update(){base.Update();if (stateTimer < 0)player.ZeroVelocity();if(triggerCalled)stateMachine.ChangeState(player.idleState);}
}

PlayerIdleState.cs

修改转到移动状态的条件

//PlayerIdleState:空闲状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;public class PlayerIdleState : PlayerGroundedState
{//构造函数public PlayerIdleState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName){}//进入public override void Enter(){base.Enter();player.SetVelocity(0, rb.velocity.y);}//退出public override void Exit(){base.Exit();}//更新public override void Update(){base.Update();//切换到移动状态if(xInput!=0 && !player.isBusy)stateMachine.ChangeState(player.moveState);}
}

相关文章:

Unity教程(九)角色攻击的改进

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…...

宠物空气净化器真的能除毛吗?有哪些选购技巧和品牌推荐修改版

夏日炎炎&#xff0c;有猫超甜。作为一名资深铲屎官&#xff0c;家里养有猫让我倍感幸福&#xff0c;夏天里有空调、有西瓜、有猫&#xff0c;这几个搭配在一起真的是超级爽。但在这么高温的夏天&#xff0c;家里养有宠物还是有不少烦恼的。比如家里的浮毛一直飘&#xff0c;似…...

Qt自定义注释

前言 是谁在Qt中编写代码&#xff0c;函数注释&#xff0c;类注释时&#xff0c;注释符号一个一个的敲&#xff1f; comment注释brief简洁的 Detailed详细的 第一步&#xff1a; 打开Qt 工具->选项->文本编辑器->片段 第二步&#xff1a; 点击添加 然后点击OK…...

【模电笔记】——信号的运算和处理电路(含电压比较器)

tips&#xff1a;本章节的笔记已经打包到word文档里啦&#xff0c;建议大家下载文章顶部资源&#xff08;有时看不到是在审核中&#xff0c;等等就能下载了。手机端下载后里面的插图可能会乱&#xff0c;建议电脑下载&#xff0c;兼容性更好且易于观看&#xff09;&#xff0c;…...

Java之 equals()与==

目录 运算符用途&#xff1a;用于比较两个引用是否指向同一个对象。比较内容&#xff1a;比较的是内存地址&#xff08;引用&#xff09;。适用范围&#xff1a;适用于基本数据类型和对象引用 equals() 方法用途&#xff1a;用于比较两个对象的内容是否相同。比较内容&#xf…...

Ubuntu20.04 运行深蓝路径规划hw1

前言 环境&#xff1a; ubuntu 20.04 &#xff1b; ROS版本&#xff1a; noetic&#xff1b; 问题 1、出现PCL报错&#xff1a;#error PCL requires C14 or above catkin_make 编译时&#xff0c;出现如下错误 解决&#xff1a; 在grid_path_searcher文件夹下面的CMakeLis…...

企业如何组建安全稳定的跨国通信网络

当企业在海外设有分公司时&#xff0c;如何建立一个安全且稳定的跨国通信网络是一个关键问题。为了确保跨国通信的安全和稳定性&#xff0c;可以考虑以下几种方案。 首先&#xff0c;可以在分公司之间搭建虚拟专用网络。虚拟专用网络通过对传输数据进行加密&#xff0c;保护通信…...

WordPress原创插件:Download-block-plugin下载按钮图标美化

WordPress原创插件&#xff1a;Download-block-plugin下载按钮图标美化 https://download.csdn.net/download/huayula/89632743...

前端【详解】缓存

HTTP 缓存 https://blog.csdn.net/weixin_41192489/article/details/136446539 CDN 缓存 CDN 全称 Content Delivery Network,即内容分发网络。 用户在浏览网站的时候&#xff0c;CDN会选择一个离用户最近的CDN边缘节点来响应用户的请求 CDN边缘节点的缓存机制与HTTP 缓存相同…...

P5821 【LK R-03】密码串匹配

[题目通道](【L&K R-03】密码串匹配 - 洛谷) 一道神题。 如果没有修改操作&#xff0c;翻转A数组或B数组后就是裸的FFT了 如果每次操作都暴力修改FFT时间复杂度显然爆炸 如果每次操作都不修改&#xff0c;记下修改序列&#xff0c;询问时加上修改序列的贡献&#xff0c;…...

httpx,一个网络请求的 Python 新宠儿

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 一个简单的库&#xff0c;也许能够开启我们的智慧之门&#xff0c; 一个普通的方法&#xff0c;也许能在危急时刻挽救我们于水深火热&#xff0c; 一个新颖的思维方式&#xff0c;也许能…...

计算机网络408考研 2014

1 计算机网络408考研2014年真题解析_哔哩哔哩_bilibili 1 111 1 11 1...

JavaScript 资源大全中文版

目录 JavaScript资源大全中文版 包管理器加载器组件管理器打包工具测试框架QA工具MVC 框架和库基于 Node 的 CMS 框架模板引擎文章和帖子数据可视化 时间轴电子表格 编辑器文档工具 文件函数式编程响应式编程数据结构日期字符串数字存储颜色国际化和本地化控制流路由安全性日志…...

如何获取能直接在浏览器打开的播放地址?

背景&#xff1a;需要在浏览器上直接打开设备的画面&#xff0c;但又不想二次开发 本文介绍一种极简的取流方式&#xff0c;不需要掌握前端开发知识&#xff0c;按照本文档拼接就能得到设备的播放地址 一、准备工作 1.将设备接入到萤石账号下。萤石设备接入指南&#xff1a;h…...

如何用 LangChain 实现一个Zero Shot智能决策器(附源码)

写在前面 最近一直在研究Agent和Tool的使用&#xff0c;今天给大家带来一篇何枝大佬&#xff08;知乎何枝&#xff09;的文章《如何用LangChain实现一个Zero Shot智能决策器》&#xff0c;并附上源码。 知乎&#xff1a;https://zhuanlan.zhihu.com/p/627333499LangChain是当…...

读完这本书,我终于搞懂了Transformer、BERT和GPT!【附PDF】

前言 《Transformer、BERT和GPT: 包括ChatGPT和提示工程》 是一本深入浅出地介绍自然语言处理领域前沿技术的专著&#xff0c;全书一共379页PDF&#xff0c;是截止到目前比较系统介绍NLP和GPT融合领域的书籍。 全书共十章&#xff0c;内容丰富&#xff0c;结构清晰&#xff0c…...

仿RabbitMq简易消息队列基础篇(Muduo库的使用)

TOC Muduo库简介 Muduo由陈硕⼤佬开发&#xff0c;是⼀个基于⾮阻塞IO和事件驱动的C⾼并发TCP⽹络编程库。他是一款基于主从Reactor模型的网络库&#xff0c;其使用的线程模型是one loop per thread, 所谓 one loop per thread 指的是&#xff1a; 一个线程只能有一个事件循…...

.net SqlSugarHelper

NuGet安装&#xff1a; SqlSugarCore using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Namespace {public class SqlSugarHelper{public string _connectionString Custom…...

“AI能不能代替某某职业”,到底谁在破防?

前几天&#xff0c;公司在午间分享时谈到一个有趣的辩题&#xff1a;“AI能不能代替产品经理”&#xff0c;不仅双方辩手打了个你来我往&#xff0c;就连下面的吃瓜群众也进入红温状态。 “AI能不能代替xx”已经成为一个普遍的话题&#xff0c;在某乎上随手一刷就是不同的职业…...

智慧图书馆:构建高效视频智能管理方案,提升图书馆个性化服务

一、背景分析 随着信息技术的飞速发展&#xff0c;智慧图书馆作为现代公共文化服务的重要载体&#xff0c;正逐步从传统的纸质阅读空间向数字化、智能化方向转型。其中&#xff0c;视频智能管理方案作为智慧图书馆安全管理体系的重要组成部分&#xff0c;不仅能够有效提升图书…...

React快速开发框架

本框架主要用于快速搭建项目 使用的基本库&#xff1a;webpackreactreact-routertypescript ps&#xff1a;有不足之处请多多包涵&#xff0c;提出意见或者建议 目的&#xff1a; 前端开发大多数时间是基于市面上比较流行的成品框架开始进行开发&#xff0c;途中遇到的问题大…...

【前端】记录各种控制台警告/bug

一、Element Plus 1、控制台警告&#xff1a;“Runtime directive used on component with non-element root node. The directives will not function as intended.” 错误原因&#xff1a;在 Vue 组件上使用了运行时指令&#xff08;指那些在运行时动态绑定到 DOM 元素上的指…...

猫咪掉毛严重怎么办?铲屎官家庭必备清理工具——宠物空气净化器

“毛&#xff0c;毛&#xff0c;毛&#xff0c;还是毛&#xff01;”铲屎官们每天都离不开和猫毛斗智斗勇&#xff0c;家里的每个角落都成了“战场”&#xff0c;掉毛的严重程度超乎想象。有时也在后悔当初怎么不养只无毛猫&#xff0c;而是把毛孩子接了回来&#xff0c;世上没…...

顺序表的实现——数据结构

线性表 文章目录 线性表线性表的定义和基本操作线性表的定义线性表的基本操作 线性表的顺序表示顺序表的定义顺序表的实现——静态分配顺序表的实现——动态分配顺序表的特点 线性表的定义和基本操作 线性表的定义 线性表&#xff08;Linear List&#xff09;的定义 ​ 线性…...

【模块化】CommonJS,AMD规范,CMD规范,ES6模块化

1. CommonJS Node.js基于CommonJS规范应运而生 1.1 commonjs规范语法导出模块 module.exports { a, b }1.2 commonjs规范语法引入模块 const mod require(./导出模块name)2. AMD 规范 RequireJS 是AMD规范的实现。是js文件和模块的加载器。 在没有单页应用&#xff08;angu…...

3.js - 顶点着色器、片元着色器的联系

1、定义与功能 顶点着色器 顶点着色器&#xff0c;是图形渲染管线中的第一个可编程阶段&#xff0c;它的主要任务是&#xff0c;处理从CPU发送到GPU的顶点数据&#xff0c;包括&#xff1a;1、顶点位置的变换&#xff08;如&#xff1a;模型空间 -> 世界空间 -> 视图控件…...

kotlin简介

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言&#xff0c;被称之为 Android 世界的Swift&#xff0c;由 JetBrains 设计开发并开源。 Kotlin 可以编译成Java字节码&#xff0c;也可以编译成 JavaScript&#xff0c;方便在没有 JVM 的设备上运行。 在Google I/O 2017…...

Mintegral出海系列:解锁全球应用商店新增长路径

在全球化竞争的浪潮中&#xff0c;面对打法各异的应用和游戏品类&#xff0c;以及全球数百个环境不同的国家和地区&#xff0c;开发者们正面临着前所未有的挑战。Mintegral「出海ing」系列专题内容&#xff0c;助力出海开发者选准赛道探索新的增长路径。 据近期数据显示&#x…...

Qt 哈希加密之 QCryptographicHash

【写在前面】 QCryptographicHash 是 Qt 框架中提供的一个类&#xff0c;它用于实现加密散列函数&#xff0c;也就是我们常说的哈希函数。哈希函数能够将任意长度的数据转换为固定长度的哈希值&#xff0c;这个哈希值通常用于数据的完整性校验、密码存储等场景。 什么是哈希函数…...

渗透第二次作业

目录 简述rce漏洞 可能产生rce漏洞的函数 RCE代码执行漏洞示例 贷齐乐系统多处SQL注入漏洞 ​编辑 爆出库名 爆出表名 爆出表下的列名 查flag数据 简述rce漏洞 ​ rce漏洞&#xff0c;即远程代码执行和远程命令执行漏洞。这种漏洞允许攻击者在后台服务器上远程注入操作…...