《游戏-02_2D-开发》

news2024/11/24 6:17:27

基于《游戏-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

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

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

相关文章

MySQL---多表等级查询综合练习

创建emp表 CREATE TABLE emp( empno INT(4) NOT NULL COMMENT 员工编号, ename VARCHAR(10) COMMENT 员工名字, job VARCHAR(10) COMMENT 职位, mgr INT(4) COMMENT 上司, hiredate DATE COMMENT 入职时间, sal INT(7) COMMENT 基本工资, comm INT(7) COMMENT 补贴, deptno INT…

【cucumber】cluecumber-report-plugin生成测试报告

cluecumber为生成测试报告的第三方插件&#xff0c;可以生成html测报&#xff0c;该测报生成需以本地json测报的生成为基础。 所以需要在测试开始主文件标签CucumberOptions中&#xff0c;写入生成json报告。 2. pom xml文件中加入插件 <!-- 根据 cucumber json文件 美化测…

使用docker配置semantic slam

一.Docker环境配置 1.拉取Docker镜像 sudo docker pull ubuntu:16.04拉取的为ununtu16版本镜像&#xff0c;环境十分干净&#xff0c;可以通过以下命令查看容器列表 sudo docker images 如果想删除多余的docker image&#xff0c;可以使用指令 sudo docker rmi -f <id&g…

【深度学习目标检测】十七、基于深度学习的洋葱检测系统-含GUI和源码(python,yolov8)

使用AI实现洋葱检测对农业具有以下意义&#xff1a; 提高效率&#xff1a;AI技术可以快速、准确地检测出洋葱中的缺陷和问题&#xff0c;从而提高了检测效率&#xff0c;减少了人工检测的时间和人力成本。提高准确性&#xff1a;AI技术通过大量的数据学习和分析&#xff0c;能够…

【面试】java并发编程面试题

java并发编程面试题 何为进程?何为线程?JVM拓展为什么程序计数器、虚拟机栈和本地方法栈是线程私有的呢&#xff1f;为什么堆和方法区是线程共享的呢虚拟机栈和本地方法栈为什么是私有的?一句话简单了解堆和方法区单核 CPU 上运行多个线程效率一定会高吗&#xff1f;创建线程…

【机组】存储器、总线及堆栈寄存器实验的解密与实战

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《机组 | 模块单元实验》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 ​目录 &#x1f33a;一、 实验目的 …

【力扣hot100】二分查找

文章目录 Arrays.sort()时间复杂度o(n)二分法时间复杂度o(logn) 1.搜索插入位置代码 2. 搜索二维矩阵思路&#xff1a;代码&#xff1a; 34. 在排序数组中查找元素的第一个和最后一个位置思路&#xff1a;代码&#xff1a; 153. 寻找旋转排序数组中的最小值思路&#xff1a;代码…

5.2 基于深度学习和先验状态的实时指纹室内定位

文献来源 Nabati M, Ghorashi S A. A real-time fingerprint-based indoor positioning using deep learning and preceding states[J]. Expert Systems with Applications, 2023, 213: 118889.&#xff08;5.2_基于指纹的实时室内定位&#xff0c;使用深度学习和前一状态&…

从零开始的OpenGL光栅化渲染器构建3-法线贴图和视差贴图

前言 我们可以用一张纹理贴图来表现物体表面的基础反射颜色&#xff0c;也可以用一张镜面反射贴图&#xff0c;来指派表面是否产生高光。除此之外&#xff0c;我们可以用贴图来存储表面的法线信息&#xff0c;以及高度信息&#xff0c;从而让渲染效果更加精细。 法线贴图 我…

linux下USB抓包和分析流程

linux下USB抓包和分析流程 在windows下抓取usb包时可以通过wireshark安装时安装USBpcap来实现usb抓包&#xff0c;linux下如何操作呢&#xff1f; 是基于usbmon&#xff0c;本博客简单描述基于usbmon在linux系统上对通过usb口进行发送和接收的数据的抓包流程&#xff0c;分别描…

Matplotlib Mastery: 从基础到高级的数据可视化指南【第30篇—python:数据可视化】

文章目录 Matplotlib: 强大的数据可视化工具1. 基础1.1 安装Matplotlib1.2 创建第一个简单的图表1.3 图表的基本组件&#xff1a;标题、轴标签、图例 2. 常见图表类型2.1 折线图2.2 散点图2.3 条形图2.4 直方图 3. 图表样式与定制3.1 颜色、线型、标记的定制3.2 背景样式与颜色…

Linux:使用for+find查找文件并cp到其他目录,文件名带有空格

一、场景描述 在终端窗口中&#xff0c;用shell命令&#xff0c;批量拷贝文件到指定目录。 我是在Windows系统上&#xff0c;通过git bash终端来执行shell命令的。 二、实现过程 命令1 for filepath in find /d/LearningMaterials/数学/数学/高中/一数/偏基础&#xff08;基…

Zabbix分布式监控系统概述、部署、自定义监控项、邮件告警

目录 前言 &#xff08;一&#xff09;业务架构 &#xff08;二&#xff09;运维架构 一、Zabbix分布式监控平台 &#xff08;一&#xff09;Zabbix概述 &#xff08;二&#xff09;Zabbix监控原理 &#xff08;三&#xff09;Zabbix 6.0 新特性 1. Zabbix server高可用…

用BEVformer来卷自动驾驶-4

书接前文 前文链接&#xff1a;用BEVformer来卷自动驾驶-3 (qq.com) 上文书介绍了BEVformer是个啥&#xff0c;以及怎么实现Deformable-attention 我们继续 BEVformer的输入数据格式&#xff1a; 输入张量&#xff08;batachsize&#xff0c;queue&#xff0c;cam&#xff0c;…

工厂设计模式看这一篇就够了

本文将重点介绍几种工厂设计模式&#xff1a;简单工厂、工厂方法模式、抽象工厂模式和建造者模式。这几种设计模式在生产制造的流程下层层递进&#xff0c;可以满足不同的使用场景。在实际运用时&#xff0c;没有一个万能的工厂模式可以套用&#xff0c;要结合具体业务场景选择…

【华为GAUSS数据库】IDEA连接GAUSS数据库方法

背景&#xff1a;数据库为华为gauss for opengauss 集中式数据库 IDEA提供了丰富的各类型数据库驱动&#xff0c;但暂未提供Gauss数据库。可以通过以下方法进行连接。 连接后&#xff0c; 可以自动检查xml文件中的sql语句是否准确&#xff0c;表名和字段名是否正确还可以直接在…

基于 IoT 物联网 + 5G 技术搭建 100万台电梯智能化运维平台

随着近20年我国房地产的蓬勃发展&#xff0c;电梯已经成为人们现代生活中不可或缺的一部分&#xff0c;也是城市化建设中重要的建筑设备之一。据中国电梯行业协会统计&#xff0c;截至2022年底&#xff0c;我国电梯保有量为990万台&#xff0c;电梯运营健康度&#xff0c;减少事…

Pyro —— Sparse vs dense simulations

目录 Simulation area Sparse solving Understanding resizing Simulation area 在模拟的期间&#xff0c;pyro场都在当前容器内定义&#xff1b;开始非常小&#xff0c;随模拟的进行&#xff0c;解算器会不断的对其扩展或收缩&#xff1b;为重置流体框&#xff0c;解算器会…

Android 基础技术——addView 流程

笔者希望做一个系列&#xff0c;整理 Android 基础技术&#xff0c;本章是关于 addView 在了解 addView 流程之前&#xff0c;先回答下以下几个问题&#xff1a; PhoneWindow是什么时候创建的&#xff1f; DectorView 是什么&#xff1f; DectorView 是什么时候创建的&#xf…

conda国内加速

1、配置国内源 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ 2、显示源地址 conda config --set show_channel_urls yes