【制作100个unity游戏之31】用unity制作一个爬坡2d赛车小游戏

最终效果

【制作100个unity游戏之31】用unity制作一个爬坡2d赛车小游戏

前言

今天用unity制作一个简单的爬坡2d赛车小游戏

素材

https://www.spriters-resource.com/mobile/hillclimbracing/

拼装车素材

在这里插入图片描述

车身添加碰撞体,摩檫力0

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

轮胎添加碰撞体和刚体,摩檫力设置为2

在这里插入图片描述

在这里插入图片描述

整个车加刚体,修改质量为2

在这里插入图片描述

车新增两个Wheel Joint 2组件,分别绑定前后两个车轮刚体

在这里插入图片描述

将锚点移动到车车轮中心
在这里插入图片描述

修改参数
在这里插入图片描述

运行效果,高频会让你的悬架保持紧密
在这里插入图片描述

让车开起来

新增DriveCar 代码

public class DriveCar : MonoBehaviour
{[SerializeField] private Rigidbody2D _frontTireRB; // 前轮刚体[SerializeField] private Rigidbody2D _backTireRB; // 后轮刚体[SerializeField] private float _speed = 150f; // 车辆速度private float _moveInput; // 移动输入值// 每帧更新private void Update(){_moveInput = Input.GetAxisRaw("Horizontal"); // 获取水平输入}// 固定帧更新private void FixedUpdate(){// 给前轮和后轮施加扭矩,控制车辆运动_frontTireRB.AddTorque(-_moveInput * _speed * Time.fixedDeltaTime);_backTireRB.AddTorque(-_moveInput * _speed * Time.fixedDeltaTime);}
}

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

在这里插入图片描述

我们还希望当汽车在空中时能够控制它的旋转

修改DriveCar

[SerializeField] private Rigidbody2D _carRB; // 车刚体
[SerializeField] private float _rotationSpeed = 500f; // 旋转速度// 固定帧更新
private void FixedUpdate()
{//..._carRB.AddTorque(-_moveInput * _rotationSpeed * Time.fixedDeltaTime);
}

配置
在这里插入图片描述

效果
在这里插入图片描述

让我们把司机的头弄得摇摇晃晃的

在身体上添加一个2d碰撞体
在这里插入图片描述

给头添加碰撞体
添加Hinge Joint 2D 链接组件,链接车,锚点设置在脖子处
并开启限制Use Limits(使用限制 ),限制头在一定范围内摆动
在这里插入图片描述

效果
在这里插入图片描述

添加

添加Sprite Shape Profile图片形状轮廓
在这里插入图片描述

在这里插入图片描述
其实效果就是地面旋转超过一定角度后,草地就消失了
在这里插入图片描述

应用Sprite Shape Profile图片形状轮廓配置

场景添加ClosedShape组件
在这里插入图片描述
配置
在这里插入图片描述
可以看到草默认没有露出来,我们需要编辑样条,使左上角点和右上角点立即线性
在这里插入图片描述
在这里插入图片描述

绘制地形

我们可以手动绘制地形,但是工作量太大
在这里插入图片描述

我们可以选择用代码控制生成,新增EnvironmentGenerator

using UnityEngine;
using UnityEngine.U2D;[ExecuteInEditMode]
public class EnvironmentGenerator : MonoBehaviour
{[SerializeField] private SpriteShapeController _spriteShapeController; // Sprite Shape 控制器[SerializeField, Range(3f, 100f)] private int _levelLength = 50; // 环境长度[SerializeField, Range(1f, 50f)] private float _xMultiplier = 2f; // X 倍增量[SerializeField, Range(1f, 50f)] private float _yMultiplier = 2f; // Y 倍增量[SerializeField, Range(0f, 1f)] private float _curveSmoothness = 0.5f; // 曲线平滑度[SerializeField] private float _noiseStep = 0.5f; // 噪声步长[SerializeField] private float _bottom = 10f; // 底部高度private Vector3 _lastPos; // 上一个位置public void OnValidate(){_spriteShapeController.spline.Clear(); // 清空曲线for (int i = 0; i < _levelLength; i++){_lastPos = transform.position + new Vector3(i * _xMultiplier, Mathf.PerlinNoise(0, i * _noiseStep) * _yMultiplier, 0f); // 计算当前位置_spriteShapeController.spline.InsertPointAt(i, _lastPos); // 在曲线中插入点if (i != 0 && i != _levelLength - 1){_spriteShapeController.spline.SetTangentMode(i, ShapeTangentMode.Continuous); // 设置切线模式为连续_spriteShapeController.spline.SetLeftTangent(i, Vector3.left * _xMultiplier * _curveSmoothness); // 设置左切线_spriteShapeController.spline.SetRightTangent(i, Vector3.right * _xMultiplier * _curveSmoothness); // 设置右切线}}_spriteShapeController.spline.InsertPointAt(_levelLength, new Vector3(_lastPos.x, transform.position.y - _bottom, 0f)); // 在最后添加底部左侧点_spriteShapeController.spline.InsertPointAt(_levelLength + 1, new Vector3(transform.position.x, transform.position.y - _bottom, 0f)); // 在最后添加底部右侧点}
}

配置,调整参数配置,绘制地形
在这里插入图片描述

地面添加碰撞体

新增Edge Collider 2D碰撞体
在这里插入图片描述

可以看到默认是一条线,点击Sprite Shape Controller组件的更新碰撞体取消勾选再打开,就刷新了
在这里插入图片描述
这样碰撞就与地面匹配了
在这里插入图片描述

但是我们不希望碰撞体在草地之上,可以点击细微调整碰撞体
在这里插入图片描述

效果
在这里插入图片描述

添加虚拟相机摄像头跟随

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

添加燃料条

绘制UI
在这里插入图片描述
在这里插入图片描述

新增FuelController

using UnityEngine;
using UnityEngine.UI;public class FuelController : MonoBehaviour
{public static FuelController instance;[SerializeField] private Image _fuelImage; // 显示燃料的图像[SerializeField, Range(0.1f, 5f)] private float _fuelDrainSpeed = 1f; // 燃料消耗速度范围[SerializeField] private float _maxFuelAmount = 100f; // 最大燃料量private float _currentFuelAmount; // 当前燃料量private void Awake(){if (instance == null)instance = this; // 单例模式,确保只有一个实例}private void Start(){_currentFuelAmount = _maxFuelAmount; // 初始时燃料量等于最大燃料量UpdateUI(); // 更新UI显示}private void Update(){_currentFuelAmount -= Time.deltaTime * _fuelDrainSpeed; // 每帧消耗燃料UpdateUI(); // 更新UI显示}private void UpdateUI(){_fuelImage.fillAmount = (_currentFuelAmount / _maxFuelAmount); // 更新燃料图像的填充量}
}

配置
在这里插入图片描述

效果
在这里插入图片描述

按颜料剩余量显示不同的颜色变化

修改FuelController

[SerializeField] private Gradient _fueleGradient;//颜色参数private void UpdateUI()
{_fuelImage.fillAmount = (_currentFuelAmount / _maxFuelAmount); // 更新燃料图像的填充量_fuelImage.color = _fueleGradient.Evaluate(_fuelImage.fillAmount);//修改颜色变化
}

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

燃料耗尽结束游戏和重新开始游戏

简单绘制游戏结束UI
在这里插入图片描述

新增GameManager

using UnityEngine;
using UnityEngine.SceneManagement;public class GameManager : MonoBehaviour
{public static GameManager instance;[SerializeField] private GameObject _gameOverCanvas; // 游戏结束时显示的画布private void Awake(){if (instance == null)instance = this; // 单例模式,确保只有一个实例Time.timeScale = 1f; // 时间缩放设为正常时间}public void GameOver(){_gameOverCanvas.SetActive(true); // 显示游戏结束画布Time.timeScale = 0f; // 暂停游戏时间}public void RestartGame(){SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); // 重新加载当前场景}
}

配置
在这里插入图片描述

配置重新开始游戏按钮事件
在这里插入图片描述
修改FuelController,调用游戏结束事件

private void Update()
{//...//燃料耗尽结束游戏if(_currentFuelAmount <= 0f){GameManager.instance.GameOver();}
}

效果
在这里插入图片描述

玩家头部撞地结束游戏

添加在头上脚本,记得配置地面标签

public class DriverDeathFromHead : MonoBehaviour
{private void OnCollisionEnter2D(Collision2D other) {if(other.gameObject.CompareTag("Ground")){GameManager.instance.GameOver();}}
}

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

加油

修改FuelController

//加油
public void FillFuel(){_currentFuelAmount = _maxFuelAmount;UpdateUI();
}

新增CollectFuel ,油脚本

public class CollectFuel : MonoBehaviour
{private void OnTriggerEnter2D(Collision2D other) {if(other.gameObject.CompareTag("Player")){FuelController.instance.FillFuel();Destroy(gameObject);}}
}

配置
在这里插入图片描述

效果
在这里插入图片描述

显示行驶距离

新增DisplayDistanceText

public class DisplayDistanceText : MonoBehaviour
{[SerializeField] private Text _distanceText; // 显示距离的TextMeshProUGUI组件[SerializeField] private Transform _playerTrans; // 玩家的Transform组件private Vector2 _startPosition; // 起始位置private void Start(){_startPosition = _playerTrans.position; // 记录玩家的初始位置}private void Update(){Vector2 distance = (Vector2)_playerTrans.position - _startPosition; // 计算玩家相对于起始位置的距离distance.y = 0f; // 只关心水平方向的距离if (distance.x < 0){distance.x = 0; // 距离不会为负数,最小为0}_distanceText.text = distance.x.ToString("F0") + "m"; // 更新显示距离的文本,保留0位小数并添加单位“m”}
}

配置
在这里插入图片描述

效果
在这里插入图片描述

轮胎凹陷问题

比如这样
在这里插入图片描述
你可以选择修改阻尼比和增大频率的值,使其更加稳定,比如这里改成0.3和5
在这里插入图片描述

把轮胎往下移
在这里插入图片描述

别忘记重新定位锚点到中心
在这里插入图片描述

最终效果

参考

https://www.youtube.com/watch?v=E8lR59Yb2A0

源码

很遗憾源码我并不想免费分享,我也建议大家能自己手动去敲代码,逐步实现和理解每一块功能。项目实现所涉及的主要功能思路和代码我也已经毫无保留的分享在文章中了,当然,如果你真的需要的话,源码我也放出来了,收个辛苦费,就当作你对我不断创作的支持。力量随微,心暖人。您的每一次支持都是我创作的最大动力!!!

https://gf.bilibili.com/item/detail/1106249120

完结

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

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

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

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

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

相关文章

【VSCode实战】Golang无法跳转问题竟是如此简单

上一讲【VSCode实战】Go插件依赖无法安装 – 经云的清净小站 (skycreator.top)&#xff0c;开头说到了在VSCode中Golang无法跳转的问题&#xff0c;但文章的最后也没给出解决方案&#xff0c;只解决了安装Go插件的依赖问题。 解决了插件依赖问题&#xff0c;无法跳转的问题也离…

苍穹外卖 02

1.新增员工 controller&#xff1a; EmployeeServiceImpl&#xff1a; 实现controller里的save方法&#xff0c;要调用到mapper层的insert方法 因为员工登录成功后&#xff0c;会将id封装进jwt令牌,并响应给前端 所以后续请求中前端会携带jwt令牌。通过令牌可解析出被封装的…

C++:平衡搜索二叉树(AVL)

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;平衡搜索二叉树&#xff08;AVL&#xff09;》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 文章目录 :maple_leaf:AVL树:maple_leaf:…

大学计算机专业主要课程及概要介绍

大学计算机专业主要课程及概要介绍 大学计算机专业是一门涵盖广泛领域的学科&#xff0c;旨在培养学生在计算机科学与技术方面的理论知识与实践能力。该专业课程设置丰富多样&#xff0c;涵盖了从基础理论到高级应用的多个方面。以下是一些主要的课程及其概要介绍&#xff1a;…

【H.264】H.264详解(二)—— H264视频码流解析示例源码

文章目录 一、前言二、示例源码【1】目录结构【2】Makefile源码【3】h264parser.c源码【4】编译运行【5】源码下载地址 声明&#xff1a;此篇示例源码非原创&#xff0c;原作者雷霄骅。雷霄骅&#xff0c;中国传媒大学通信与信息系统专业博士生&#xff0c;在此向雷霄骅雷神致敬…

OpenHarmony 开发

本心、输入输出、结果 文章目录 OpenHarmony 开发前言JonathanOpenHarmony 并不是 AndroidOpenHarmony 应用迁移OpenHarmony 的开发流程OpenHarmony 开发 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csdn.net/qq_15071263 如果觉得本文对你有帮助,欢迎点赞、收藏、评…

2023IMO预选题几何第6题

锐角 △ A B C \triangle ABC △ABC 的外接圆为 ω \omega ω, 圆 I I I 与 ω \omega ω 内切于 A A A, 且与 B C BC BC 切于点 D D D. 设直线 A B AB AB, A C AC AC 分别与 I I I 交于点 P P P, Q Q Q, 点 M M M, N N N 在直线 B C BC BC 上, 满足 B B B 是 …

CeoMax总裁主题最新3.8.1破解免授权版/WordPress付费资源素材下载主题

CeoMax总裁主题最新3.8.1破解免授权版&#xff0c;一套WordPress付费资源素材下载的主题&#xff0c;感觉这是做资源站唯一一个可以和ripro媲美甚至超越的模板&#xff0c;UI很美&#xff0c;功能也很强大&#xff0c;有想学习的可下载搭建学习一下&#xff0c;仅供学习研究借鉴…

仿学校网页

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0"><title>学校网页</title> <style>.WebTop{backg…

誉天网络安全课程怎么样

学员服务质量保障讲师团队&#xff1a;平均5年课程交付经验&#xff0c;授课质量有保障辅导团队&#xff1a;实验论述辅导讲师&#xff0c;实验备考环境复刻&#xff0c;备考资料完善&#xff0c;及时更新就业服务&#xff1a;简历制作培训&#xff0c;面试技巧培训&#xff0c…

昇思MindSpore学习入门-轻量化数据处理

在资源条件允许的情况下&#xff0c;为了追求更高的性能&#xff0c;一般使用Pipeline模式执行数据变换Transforms。 基于Pipeline模式执行的最大特点是需要使用map方法&#xff0c;如下图中将Resize、Crop、HWC2CHW交由map调度&#xff0c;由其负责启动和执行给定的Transform…

R语言统计分析——控制流

参考资料&#xff1a;R语言实战【第2版】 语句&#xff08;statement&#xff09;是一条单独的R语言或一组复合语言&#xff08;包含在花括号{}中的一组R语言&#xff0c;使用分号分隔&#xff09; 条件&#xff08;cond&#xff09;是一条最终被解析为真&#xff08;TRUE&…

python黑马笔记

运算符&#xff1a; 算术运算符&#xff1a; 加 - 减 * 乘 / 除 // 整除 % 取余 ** 求平方 除法计算得出的结果都是小数 赋值运算符&#xff1a; 标准赋值&#xff1a; 复合赋值&#xff1a; 、 - 、 * 、 / 、// 、 ** 字符串&#xff1a; 字符串拓展内容&#xf…

护网紧急情况应对指南:Linux 应急响应手册

继上一篇&#xff1a;护网紧急情况应对指南&#xff1a;Windows版v1.2全新升级版 之后 收到小伙伴后台要Linux应急手册&#xff0c;今天给大家安排上。 《Linux应急手册》是一本为Linux系统管理员和运维工程师量身打造的实用指南&#xff0c;旨在帮助他们快速应对各种突发状况…

基于FFMPEG和SDL的音视频解码播放的实现过程与相关细节

目录 1、视频播放器原理 2、FFMPEG解码 2.1 FFMPEG库 2.2、数据类型 2.3、解码 2.3.1、接口函数 2.3.2、解码流程 3、SDL播放 3.1、接口函数 3.2、视频播放 3.3、音频播放 4、音视频的同步 4.1、获取音频的播放时间戳 4.2、获取当前视频帧时间戳 4.3、获取视…

MATLAB仿真:数字信号处理用FFT对信号分析

目录 1.实验目的 2 实验原理 3.实验仪器及设备 4.实验步骤及内容 (1)对以下序列进行谱分析。 (2)对以下周期序列进行谱分析。 (3)对模拟周期信号进行谱分析 1.实验目的 学习用 FFT 对连续信号和时域离散信号进行谱分析的方法,了解可能出现的分析误差及其原因,…

CAS算法

CAS算法 1. CAS简介 CAS叫做CompareAndSwap&#xff0c;比较并交换&#xff0c;主要是通过处理器的指令来保证操作的原子性。 CAS基本概念 内存位置 (V)&#xff1a;需要进行CAS操作的内存地址。预期原值 (A)&#xff1a;期望该内存位置上的旧值。新值 (B)&#xff1a;如果旧…

The Llama 3 Herd of Models.Llama 3 模型论文全文

现代人工智能(AI)系统是由基础模型驱动的。本文提出了一套新的基础模型,称为Llama 3。它是一组语言模型,支持多语言、编码、推理和工具使用。我们最大的模型是一个密集的Transformer,具有405B个参数和多达128K个tokens的上下文窗口。本文对Llama 3进行了广泛的实证评价。我们…

DNS 污染/毒化——华为ensp

实验原理:1&#xff0c;用户正常访问 Web页面&#xff0c;会查询本地DNS服务器&#xff0c;一般情况下&#xff0c;本地DNS服务器会设置为 网关地址。2&#xff0c; 攻击者在 用户和网关之间&#xff0c;开启ARP攻击即可&#xff0c;这样&#xff0c;就可以让 用户访问本地DNS服…

【Ant Design Pro】快速上手

初始化 初始化脚手架&#xff1a;快速开始 官方默认使用 umi4&#xff0c;这里文档还没有及时更新&#xff08;不能像文档一样选择 umi 的版本&#xff09;&#xff0c;之后我选择 simple。 然后安装依赖。 在 package.json 中&#xff1a; "start": "cross-e…