《游戏-02_2D-开发》

基于《游戏-01_2D-开发》,

继续制作游戏:

首先给人物添加一个2D重力效果

在编辑的项目设置中,

可以看出unity默认给的2D重力数值是-9.81,模拟现实社会中的重力效果

下方可以设置帧率

而Gravity Scale代表 这个数值会 * 重力 

还需要将玩家添加碰撞器Collider,而一般人物均添加胶囊碰撞器Capsule Collider 2D

在编辑场景中人物身上的绿色圆圈就是碰撞范围,我们进行修改

修改成与人物差不多大小

Shift + F 可以快速帮我们找到需要用到的物体

在场景中找到这个物体

添加不规则复合碰撞器有三步

勾选合成为1块 Used By Composite

最后将场景重力效果设置为静态

我们在运行测试前拖动玩家位置

运行可见玩家通过重力落在了地面

我们避免人物因为场景碰撞体的不均匀而摔倒,需要冻结玩家屏幕z坐标

我们还可以通过设置Mass来设定玩家的质量,如果玩家的质量大于怪物就可以撞开怪物

在重力设置中可以在碰撞检测方式上不选间歇性Discrete 而选择持续Continuous

运行即下落

接下来我们开始配置新输入系统

在编写代码之前,我们首先在项目管理中创建两个文件夹,

表示脚本下的玩家文件夹

在玩家管理文件夹中创建一个代码

命名为PlayerController

旧输入系统已经淘汰,因为移植性不好,跨平台性差,例如移植到手机或xbox平台很复杂

所以我们需要用到新输入系统

打开项目设置

找到Other Settings

我们可以修改Api,.NET Framework可以让我们利用更多的c#特性

【切记】:接下来我们要保存好项目,因为接下来的设置新输入系统会自动重启unity项目

我们在Player 的 Other Settings 的 Active Input Handing 中将输入管理Old设置为Both

注意:在点击Apply之前一定要先保存好项目

更新成新输入系统后我们开始使用新输入系统

我们在Windows下的Package Manager下找到新输入系统

选择Unity Registry 在右侧输入Input 即可看到新输入系统点击下载

创建文件夹

创建Input Actions

命名为InputControls

双击我们就可以打开新输入系统了

将新输入系统放置Scene右侧便于操作,创建一个Action map

Action Maps提供选择控制哪些物品操作的途径,

命名为运动Movement

设置

添加 上/下/左/右 绑定

删除无功能选项

设置

重命名WASD

键盘设置完成之后如果还想设置手柄操作的话

可以继续设置

这样就成功实现了两种输入系统

当然除了手动设置新操作系统也可以系统默认生成

首先在Player下增加组件Player Input

点击新建新输入系统

选择刚刚设置好的路径

选择替换

再次双击打开就可以看见系统为我们创建的新输入系统了

节省了很多设置操作

当然我们需要修改这些系统生成的设置比如,

确认设置成了Any  后面会修改它的设置

创建好新输入系统后我们就可以把Player Input这个组件删除了 ,因为我们想通过生成代码的方式实现

要求系统自动生成代码

双击打开代码

编写代码,

这里InputControls 类型 应与自定义新输入系统名字相符合

注意:

函数周期表,

awake > enable > start > physicsUpdate > Update > fixedUpdate > diable > destroy 

人物在编辑场景取消右上角显示勾选时,就会执行OnDisable()函数

勾选启动时就会执行OnEnable()这个函数

编写代码,

代码中的inputDirection可以存储一个新输入系统中设定的Vector2变量,从而代码控制新输入系统

编写代码:

定义公开变量inputControl用来存储我们在

下的【InputControls【自定义新输入系统类型】】,

定义公开变量rb存储用来控制玩家移动的【Rigidbody2D【刚体类型】】,

定义公开变量inputDirection存储用来二维转向的【Vector2【二维向量类型】】,

定义公开变量speed存储用来控制移动速度的【float【字符类型】】,

最先调用Awake()函数创建new新输入系统类型内存,再获取刚体组件分别分配给inputControl与rb变量,

然后调用OnEnable()函数与OnDisable()函数中的inputControl的Enabe()与Disable区别是否持续按键,

然后调用Update()函数,获取新输入系统中的二维向量读值,

最后调用FixedUpdate()函数中的Moved函数

Moved()函数中(int)transform.locakScale.x是将transform变量转换成int值

其.locakScale.x即

语句int faceDir = (int)transform.localScale.x; 即将x的缩放比例转换成值存储到faceDir变量中

因为键盘判断左方向与右方向是通过1与-1设定的所以通过

transform.localScale = new Vector3(facwDir,1,1);

其中

是根据

而设定的

根据逻辑判断设定转向

if(inputDirection.x > 0)

    faceDir = 1;

if(inputDirection.x < 0)

    faceDir = -1;

最后设定刚体的速度

rb.velocity = new Vector2(inputDirection.x * speed * Time.deltaTime,rb.velocity.y);

using UnityEngine;
public class PlayerController : MonoBehaviour{
    public  InputControls inputControl;
    public Rigidbody2D rb;
    public Vector2 inputDirection;
    public float speed;
    private void Awake(){
        inputControl = new InputControls();
        rb = GetComponent<Rigidbody2D>(); 
    }
    private void OnEnable(){
        inputControl.Enable();
    }
    private void OnDisable(){
        inputControl.Disable();
    }
    private void Update(){
        inputDirection = inputControl.Player.Move.ReadValue<Vector2>();
    }
    private void FixedUpdate(){
        Moved();
    }
    private void Moved() {
        int faceDir = (int)transform.localScale.x;
        if (inputDirection.x > 0)
            faceDir = 1;
        if (inputDirection.x < 0)
            faceDir = -1;
        transform.localScale = new Vector3(faceDir, 1, 1);
        //键盘
        rb.velocity = new Vector2(inputDirection.x * speed * Time.deltaTime,rb.velocity.y);
    }
}
注意这里

先判断转向,再进行翻转

运行即完成了翻转及水平移动

接下来要完成跳跃同样,我们需要在新输入系统中自己设定

修改代码,为代码在unity中易读,可在代码中添加特性

保存代码我们在unity中即可看到显示中文 

我们首先添加一个 float类型 的 跳跃力 字段

我们想对纵轴施加一个 jumpForce跳跃力

我们需要修改代码:

using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour{
    public  InputControls inputControl;
    public Rigidbody2D rb;
    public Vector2 inputDirection;
    [Header("基本参数")]
    public float speed;
    public float jumpForce;
    private void Awake(){
        inputControl = new InputControls();
        rb = GetComponent<Rigidbody2D>();
        inputControl.Player.Jump.started += Jump;
    }
    private void Jump(InputAction.CallbackContext obj){
        rb.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
    }

    private void OnEnable(){
        inputControl.Enable();
    }
    private void OnDisable(){
        inputControl.Disable();
    }
    private void Update(){
        inputDirection = inputControl.Player.Move.ReadValue<Vector2>();
    }
    private void FixedUpdate(){
        Moved();
    }
    private void Moved() {
        int faceDir = (int)transform.localScale.x;
        if (inputDirection.x > 0)
            faceDir = 1;
        if (inputDirection.x < 0)
            faceDir = -1;
        transform.localScale = new Vector3(faceDir, 1, 1);
        rb.velocity = new Vector2(inputDirection.x * speed * Time.deltaTime,rb.velocity.y);
    }
}
【解析】:

        玩家输入系统中我们添加了公开的float类型字段用来存储一个跳跃时纵方向获取的数值,

在调用Awake()函数时 首先获取新输入系统的Jump 然后 打点. 获取 Jump下的 started,

注意:按住可以执行 performed ,为了快速很精准执行一次 我们采取用started 表示按键按下的那一刻 执行了

一般对于单次执行的函数我们放进started中进行,因为started是一个事件方法,所以我们需要添加一个事件注册函数,而注册的内容 就用 += 加号等号 这个符号进行注册,

inpitControl.Player.Jump.started += Jump;

意思就是把 Jump这个函数 添加到 started 按键按下的那一刻来执行,

然后我们可以看到Jump报红,

我们选中Jump 按Alt + Enter 键即可弹出选项我们点击生成Jump方法

即可生成一个带参数的Jump函数我们修改函数中的内容

表示这个Jump函数在按键按下要被执行时 利用刚体rb 打点. 添加一个力,因为这个rb刚体的类型是 Rigidbody2D 所以括号中有两个参数,其中transform.up 表示 世界坐标的上方向,我们通过 * 乘以这个跳跃数值,第二个参数ForceMode2D.Impulse 代表 这个力是瞬时的

Impulse 瞬时力

写好代码,我们通过unity场景中的Player公开的跳跃力字段输入合适的值进行设定找到一个舒服合理的跳跃程度

运行实现跳跃

但这其中还有很多不合理的地方,比如跳跃后松手就会垂直下落,跳跃中前方有障碍物会卡住,在跳跃中可以持续跳跃等,

接下来我们在代码中进行修改,完善成合理的跳跃逻辑

首先我们先解决连续跳跃的问题:

我们新建脚本 物理检查PhysicsCheck.cs

编写代码:

using UnityEngine;
public class PhysicsCheck : MonoBehaviour{
    public bool isGround;
    public float checkRadius;
    public LayerMask groundLayer;
    private void Update(){
        Check();
    }
    public void Check(){
        isGround = Physics2D.OverlapCircle(transform.position, checkRadius, groundLayer);
    }
}
【解析】:

        定义一个公开bool类型变量存储到 isGround 变量中,用来判断是否接触到地面,

定义一个公开float类型变量存储到 checkRadius 变量中,用来表示碰撞范围,

定义一个公开 LayerMask层级面具变量存储到 groundLayer 变量中,用来表示对哪个层进行操作,

这里需要在unity场景中手动添加Layer 层:

保存代码后,在unity场景中可见

这两部分的层级是相同的,

我们首先添加层级

设置层级

设置作用层级

这样通过代码就可以影响 被设置的Ground层级的 地面了

语句表示 将进行物理2D 的 OverlapCircle 叠层圆形 检测

检测三个方面 

transform.position 检测点

checkRadius 检测范围

groundLayer 检测层级

这样我们回到unity中将检测半径设为 0.2

再将监测点设为脚下

运行即可看到 跳跃前 接触地面的选项被自动 勾选

跳跃后 接触地面的选项被自动 取消

PhysicsCheck脚本写好之后我们进行组合,

用到写好的类PhyisicsCheck脚本这个类型 就可以拿到这个类的所有公开变量与公开方法

【很重要】:拿到之后需要在Awake()函数中激活,

using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour{
    public  InputControls inputControl;
    public Rigidbody2D rb;
    public Vector2 inputDirection;
    public PhysicsCheck physicsCheck;
    [Header("基本参数")]
    public float speed;
    public float jumpForce;
    private void Awake(){
        inputControl = new InputControls();
        rb = GetComponent<Rigidbody2D>();
        inputControl.Player.Jump.started += Jump;

        physicsCheck = GetComponent<PhysicsCheck>();

    }
    private void Jump(InputAction.CallbackContext obj){
        if(physicsCheck.isGround)
            rb.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
    }
    private void OnEnable(){
        inputControl.Enable();
    }
    private void OnDisable(){
        inputControl.Disable();
    }
    private void Update(){
        inputDirection = inputControl.Player.Move.ReadValue<Vector2>();
    }
    private void FixedUpdate(){
        Moved();
    }
    private void Moved() {
        int faceDir = (int)transform.localScale.x;
        if (inputDirection.x > 0)
            faceDir = 1;
        if (inputDirection.x < 0)
            faceDir = -1;
        transform.localScale = new Vector3(faceDir, 1, 1);
        rb.velocity = new Vector2(inputDirection.x * speed * Time.deltaTime,rb.velocity.y);
    }
}

我们回到unity场景中运行游戏,即可发现连续跳跃问题解决了

当然我们的触碰范围 = 0.2 没有在unity中显示,我们可以自己用代码画出来

using UnityEngine;
public class PhysicsCheck : MonoBehaviour{
    public bool isGround;
    public float checkRadius;
    public LayerMask groundLayer;
    public Vector2 bottomOffset;
    private void Update(){
        Check();
    }
    public void Check(){
        isGround = Physics2D.OverlapCircle(
            (Vector2)transform.position + bottomOffset, checkRadius, groundLayer);
    }
    private void OnDrawGizmosSelected(){
        Gizmos.DrawWireSphere(
            (Vector2)transform.position + bottomOffset, checkRadius
        );
    }
}

调用OnDrawGizmosSelected()函数将以

为中心点  以

为半径在人物脚下显示碰撞范围

【解析】

定义一个公开 Vector2二维向量类型的变量存储到 bottomOffset变量中,用作偏移量

在Check()检测函数中 将偏移量bottomOffset 与 检测点位置相加,

注意:因为检测点是三维向量 所以 二维向量 与 三维向量相加需要用到强制转换 (Vector2) 强制转换为二维向量Vector2类型

最后通过OnDrawGizmosSelected()函数将 检测点画出来

注意:Gizmos就是辅助线等小控件可以选择是否显示

这里调用OnDrawGizmosSelected()函数就是选择性将小控件的哪个控件画出来,

显而易见

Gizmos.DrawWireSphere(
            (Vector2)transform.position + bottomOffset, checkRadius
        );

我们画出来的是 检测范围

在unity场景中通过改变位移差值x/y可以改变检测范围的位置

接下来我们优化跳跃中不会贴在前方障碍物这个问题,

首先在unity场景中创建一个文件夹PhysicsMaterials,

然后创建一个光滑的材质,

起名为Normal

这里表示摩擦力是0.4

我们只需要把摩擦力改为0,就创建了一个光滑的材质

将光滑材质放进玩家的 胶囊碰撞器组件 的 Material框选中

即解决了跳跃中贴前方障碍物的问题

最后运行

实现完整的逻辑跳跃

End

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git将某个文件合并到指定分支

企业开发中&#xff0c;经常会单独拉分支去做自己的需求开发&#xff0c;但是某些时候一些公共的配置我们需要从主线pull&#xff0c;这时候整个分支merge显然不合适 1.切换至待合并文件的分支 git checkout <branch>2.将目标分支的单个文件合并到当前分支 git checkou…

maven 基本知识/1.17

maven ●maven是一个基于项目对象模型(pom)的项目管理工具&#xff0c;帮助管理人员自动化构建、测试和部署项目 ●pom是一个xml文件&#xff0c;包含项目的元数据&#xff0c;如项目的坐标&#xff08;GroupId,artifactId,version )、项目的依赖关系、构建过程 ●生命周期&…

Servlet系列:两种创建方式(xml,注解)

一、使用web.xml的方式配置&#xff08;Servlet2.5之前使用&#xff09; 在早期版本的Java EE中&#xff0c;可以使用XML配置文件来定义Servlet。在web.xml文件中&#xff0c;可以定义Servlet的名称、类名、初始化参数等。然后&#xff0c;在Java代码中实现Servlet接口&#x…

第三课:GPT

文章目录 第三课&#xff1a;GPT1、学习总结&#xff1a;GPT出现的原因GPT的方法原理目前存在的问题无监督的预训练优化目标模型结构 监督微调课程ppt及代码地址 2、学习心得&#xff1a;3、经验分享&#xff1a;4、课程反馈&#xff1a;5、使用MindSpore昇思的体验和反馈&…

Pyro —— Flames

目录 Differences with legacy pyro Lifespan Outputs flame场是火和爆炸模拟的重要部分&#xff0c;存储反应物&#xff08;如fuel&#xff09;剩余寿命&#xff1b;该场可通过发射源补充&#xff0c;解算器会减少其值并生成对应输出&#xff08;如smoke、temperature&…

C#,入门教程(23)——数据类型转换的一点基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(22)——函数的基础知识https://blog.csdn.net/beijinghorn/article/details/124181689 先简单回顾一下&#xff0c;C#的数据类型大致有这样一些&#xff1a; &#xff08;1&#xff09;原始类型&#xff1a;byte, bool, int, doubl…

学习笔记——克里金插值

有一篇大神的文章写得非常的具体&#xff0c; https://xg1990.com/blog/archives/222 下面写下一些学习笔记&#xff1a; 1、关于克里金插值的基本原理 克里金插值来源于地理学&#xff0c;它的前提是地理学第一定律&#xff1a;所有事物都与其他事务相关&#xff0c;但是近…

Python爬蟲海外動態IP防止被封的方法 - okey proxy

在使用Python進行網路爬蟲過程中&#xff0c;我們常遇到一個問題&#xff0c;就是如何防止我們的爬蟲被目標網站封禁&#xff1f;其中一種有效的方法是使用海外動態IP代理。 代理伺服器就像是你和目標網站之間的中間人。而動態IP代理則意味著&#xff0c;每次連接都會使用一個…

Docker(四)操作容器

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 操作 Docker 容器 容器是 Docker 又一核心概念。 简单的说&#xff0c;容器是独立运行的一个或一组应用&#xff0c;以及它们的运行态环境…

5G基站节能及数字化管理解决方案

截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5G基站的能耗成为…

使 a === 1 a === 2 a === 3 为 true 的几种“下毒“方法

前言 这算得上是近些年的前端网红题了&#xff0c;曾经对这种网红题非常抵触&#xff0c;认为非常没有意义。 看到了不少人有做分享&#xff0c;有各种各样的方案&#xff0c;有涉及到 JS 非常基础的知识点&#xff0c;也不得不感叹解题者的脑洞之大。 但是&#xff0c;拿来…

redis远程连接不上解决办法

问题描述&#xff1a; redis远程服务端运行在192.168.3.90计算机上&#xff0c;客户端计算机&#xff08;ip:192.168.3.110&#xff09;通过redsi-cli.exe客户端工具连接时&#xff0c;没有反应&#xff0c;连接不上。 如图所示&#xff1a; 解决步骤&#xff1a; 步骤一&…

UE5 植物生长材质_树根像目标缠绕(记录备忘)

需要在三维软件中将树根缠绕物体的形态预先做好&#xff0c;将管状树根uv方形排布&#xff0c;模型默认材质为渐变上黑下白&#xff0c;导入引擎&#xff0c;注意制作树根尖端需要将左侧Masked数值由0.333修改为0

Java根据模板文件生成excel文件,同时将excel文件转换成图片

需求 需要将指定数据导出成表格样式的图片&#xff0c;如图 业务拆解 定义一个导出模板将得到的数据填入模板中&#xff0c;生成excel文件将ecxel文件转换成png格式的图片 代码实现 需要引入的依赖 <dependency><groupId>cn.hutool</groupId><artif…

6、梯度提升XGBoost(eXtreme Gradient Boosting)

XGBoost梯度提升 结构化数据最精确的建模技术。 在本节课中,我们将学习如何使用梯度增强来构建和优化模型。这种方法在Kaggle的许多竞争中占据主导地位,并在各种数据集上获得了最先进的结果。 本课程所需数据集夸克网盘下载链接:https://pan.quark.cn/s/9b4e9a1246b2 提取码…

JavaScript之ES6新特性02

模板字符串 模板字符串&#xff08;template string&#xff09;是增强版的字符串&#xff0c;用反引号&#xff08;&#xff09;标识。它可以当作普通字符串使用&#xff0c;也可以用来定义多行字符串&#xff0c;或者在字符串中嵌入变量 。 模版字符串特点 内容中可以直接…

【机器学习】调配师:咖啡的完美预测

有一天&#xff0c;小明带着一脸期待找到了你这位数据分析大师。他掏出手机&#xff0c;屏幕上展示着一份详尽的Excel表格。“看&#xff0c;这是我咖啡店过去一年的数据。”他滑动着屏幕&#xff0c;“每个月的销售量、广告投入&#xff0c;还有当月的气温&#xff0c;我都记录…

【C++提高编程(二)】

一、STL初识 1.1、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作 为了建立数据结构和算法的一套标…

如何自学Python:一份详细的指南

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;有感而谈⛺️稳中求进&#xff0c;晒太阳 引言 Python是一种广泛使用的高级编程语言&#xff0c;以其简洁明了的语法和强大的功能而受到许多程序员的喜爱。无论是数据分析、网络开发&#…

【教程】React-Native代码规范与加固详解

引言 React Native 是一种跨平台的移动应用开发框架&#xff0c;由 Facebook 推出。它可以让我们使用 JavaScript 和 React 语法编写原生应用&#xff0c;大大提高了移动应用的开发效率。但是&#xff0c;对于开发人员来说&#xff0c;代码规范和安全性也是非常重要的问题。本…