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

news2024/9/20 22:01:11

最终效果

【制作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.coloradmin.cn/o/1940518.html

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

相关文章

CVE-2020-7248 OpenWRT libubox堆栈溢出漏洞复现(更新中)

提要 该文档会一直处于更新当中&#xff0c;当状态为完毕后&#xff0c;才是更新完成。由于网络上关于该漏洞原理的分析文档和资源实在是太少&#xff0c;而本人关于该方向也才是刚入门&#xff0c;能力有限&#xff0c;所以复现需要的时间较长&#xff0c;需要补充和学习的东西…

《从C/C++到Java入门指南》- 9.字符和字符串

字符和字符串 字符类型 Java 中一个字符保存一个Unicode字符&#xff0c;所以一个中文和一个英文字母都占用两个字节。 // 计算1 .. 100 public class Hello {public static void main(String[] args) {char a A;char b 中;System.out.println(a);System.out.println(b)…

Spring通过工厂方法进行配置

在Spring的世界中&#xff0c; 我们通常会利用 xml配置文件 或者 annotation注解方式来配置bean实例&#xff01; 在第一种利用 xml配置文件 方式中&#xff0c; 还包括如下三小类 反射模式&#xff08;我们前面的所有配置都是这种模式&#xff09;工厂方法模式Factory Bean模…

跳妹儿学编程之ScratchJr(10):结束积木篇—放学回家

博主资深软件架构师&#xff0c;拥有13年大型软件与互联网系统开发、设计和架构经验&#xff0c;曾就职于华为&#xff0c;现任职于国内知名互联网公司。平时在家教咱家“跳妹儿”编程&#xff0c;并将心得和过程记录下来。希望可以帮助更多对编程感兴趣的家庭。 前言 继上一篇…

FastDFS分布式存储

文章目录 FastDFS原理FastDFS架构文件的上传文件的下载 FastDFS原理 FastDFS架构 Tracker server 跟踪服务器主要做挑度工作,起到均衡的作用,负责管理所有的Storage server和group Storage server 储服务器&#xff0c;主要提供容量和备份服务&#xff1b;以group为单位&…

VMware虚拟机下安装Ubuntu(详细教程,最小系统的安装,含VMware Tools)

1.VM的下载安装 VMware的下载安装教程_vm16 pro下载-CSDN博客 2. Ubuntu 下载 在官网或者镜像站下载所需版本的.ios镜像&#xff0c;这个镜像在接下来的步骤中会用到&#xff1a; Ubuntu 22.04.4 LTS 下载 和 清华大学开源软件镜像站 - Ubuntu 22.04.4 下载 3. 创建虚拟机 […

【开发实战】QT5 + OpenCV4 开发环境配置应用演示

前言 作为深度学习算法工程师&#xff0c;必须要掌握应用开发技能吗&#xff1f;搞工程肯定是必须要会界面开发&#xff0c;QT就是一个很不错的选择。本文以QT5.15 OpenCV4.8 OpenVINO2023为例&#xff0c;搭建应用开发环境&#xff0c;演示深度学习模型的QT应用案例。 开发…

重拾CSS,前端样式精读-函数(颜色,计算,图像和图形)

前言 本文收录于CSS系列文章中&#xff0c;欢迎阅读指正 在计算机编程中&#xff0c;函数有着重要的作用和意义&#xff0c;它可以实现封装&#xff0c;复用&#xff0c;模块化&#xff0c;参数等功能效果&#xff0c;在如何在CSS中写变量&#xff1f;一文带你了解前端样式利…

聊聊HuggingFace Transformer

项目组件 一个完整的transformer模型主要包含三部分&#xff1a;Config、Tokenizer、Model。 Config 用于配置模型的名称、最终输出的样式、隐藏层宽度和深度、激活函数的类别等。 示例&#xff1a; {"architectures": ["BertForMaskedLM"],"atte…

蓝屏死机不再怕!CrowdStrike故障修复指南中心上线!

系统之家于7月22日发出最新报道&#xff0c;安全公司CrowdStrike因其Windows更新引发全球 850 万台电脑蓝屏死机问题后&#xff0c;上线了全新的“修复和指南中心”&#xff08;Remediation and Guidance Hub&#xff09;&#xff0c;该中心汇集了与其错误更新相关的详细信息&a…

昇思25天学习打卡营第25天 | RNN实现情感分类

学习心得&#xff1a;RNN实现情感分类 在自然语言处理&#xff08;NLP&#xff09;的领域中&#xff0c;情感分类是一个极具挑战性的任务&#xff0c;它要求模型能够准确地从文本中识别出情感倾向。通过使用MindSpore框架和RNN模型进行情感分类&#xff0c;我获得了许多有关构…

【QT】定时器事件 - QTimerEvent QTimer

qt 系统 - 定时器 定时器1. QTimerEvent2. QTimer3. 获取系统日期及时间 定时器 Qt 中在进行窗口程序的处理过程中&#xff0c;经常要周期性的执⾏某些操作&#xff0c;或者制作⼀些动画效果&#xff0c;使用定时器就可以实现。所谓定时器就是在间隔⼀定时间后&#xff0c;去执…

《python语言程序设计》第6章第1题数,数学方面:五角数n(3n-1)/2 前100个五角数

第4次做第6章 def getPentagonalNumber(n):count 0for i in range(1, n):count 1pen_num round(i * ((3 * i) - 1) / 2)print(f"{pen_num}", end" ")if count % 10 0:print()getPentagonalNumber(100)

Java语言程序设计基础篇_编程练习题**15.15 (几何问题:添加或删除点)

**15.15 (几何问题:添加或删除点) 请编写一个程序&#xff0c;让用户在面板上单击以自动创建或移去点(参见15-28a)。当用户左击鼠标时(主按钮)&#xff0c;就创建一个点并且显示在鼠标的位置&#xff0c;用户还可以将鼠标移到一个点上&#xff0c;然后右击鼠标(次按钮)以移去这…

C语言-网络编程-UDP通信创建流程

UDP 通信创建流程 UDP 是⼀个传输层的⽆连接的协议&#xff0c;我们编写代码⼀般是分为两个端。⼀个我们称之为发送端&#xff0c;另⼀ 个我们称之为接收端。正常⼀般是接收端先运⾏&#xff0c;然后等待结束发送端发送过来的数据。 创建套接字 首先&#xff0c;我们需要创建…

JDK8升级到JDK17,报错Error:java:错误:不支持的发行版本5

1 问题描述&#xff1a; 我原来用到是JDK8,后来重新安装了JDK17后&#xff0c;并更换了JAVA_HOME的配置&#xff0c;在CDM上面查看JAVA版本确认安装无误。 当我打开IDEA运行代码时&#xff0c;就报错java&#xff1a;错误&#xff1a;不支持的发行版本5&#xff0c;至始至终我都…

Leetcode509. 斐波那契数(递归和常规两种写法)

问题描述&#xff1a; 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;…

Python酷库之旅-第三方库Pandas(037)

目录 一、用法精讲 116、pandas.Series.div方法 116-1、语法 116-2、参数 116-3、功能 116-4、返回值 116-5、说明 116-6、用法 116-6-1、数据准备 116-6-2、代码示例 116-6-3、结果输出 117、pandas.Series.truediv方法 117-1、语法 117-2、参数 117-3、功能 …

C语言编译报错:error: expected declaration or statement at end of input(缺了括号)

文章目录 报错信息分析解决步骤&#xff1a; 排查 报错信息 /userdata/testOtherPrj/20240715_box_circuit_breaker/test/external/modbus_vendorA/src/vendor_a_modbus.c: In function ‘VendorA_PowerStop’: /userdata/testOtherPrj/20240715_box_circuit_breaker/test/exte…

25届近4年电子科技大学自动化考研院校分析

电子科技大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近4年考研分数情况 四、近4年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定教…