unity之跳一跳(完整版)

2023-11-15

1.场景

(1)creat->3D objict->plane 并重命名为ground,做为地面(如下图)图一
(2)并调整颜色,大小至适合(如下图)
调正颜色:创建material(project:creat->Material)用与当作groud的材质,调整颜色,并赋到ground上
在这里插入图片描述
在这里插入图片描述

2.制作模型(即预制体:prefab)

(1)创建盒子:creat,调整盒子大小及位置,并将其拖入到事先建立好的prefabs文件夹中,使之作为一个预制体
在这里插入图片描述
(2)创建人物:
建立一个空物体(Creat empty),并将其重命名为player
在这里插入图片描述
在player里建立一个圆柱和球体,给player添加刚体组件,调正颜色(过程和标题1中ground的调色差不多),调正大小比例使其形成下图模样(图中transform参数可作为参考)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
至此我们游戏所需模型制作完毕

3.生成第二个盒子

创建Scripts文件夹,在其中创建C#脚本(C# Script)
在这里插入图片描述
打开编辑(话不多说,上代码)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class player : MonoBehaviour
{
    public float maxDis;//生成盒子与上一个盒子的最大距离
    public GameObject _box;//获取生成的盒子对应的预制体
    

    private Vector3 _dir = new Vector3(1, 0, 0);//生成第二个盒子的方向变量
    private Rigidbody rig1;//获取player刚体组件
    // Start is called before the first frame update
    void Start()
    {
        rig1 = GetComponent<Rigidbody>();//获取player的Rigidbody组件,因为此脚本挂在player上,所以默认获取player的刚体组件,可以查资料学习一下怎样获取指定物体组件
        putBox();//调用生成盒子函数
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void putBox()
    {
        var box = Instantiate(_box);//实例化盒子
        box.transform.position = _box.transform.position + _dir * Random.Range(3f, maxDis);//设置盒子位置
        var a = Random.Range(1f, 2);//生成一个随机数
        box.transform.localScale = new Vector3(a, 1.108432f, a);//改变盒子scale(尺寸)中的x(长)与z(宽)全部为生成的随机数
    }

    void Random_dir()//随机盒子生成方向
    {
        var a = Random.Range(0, 2);//随机生成0,1两个数
        if (a == 0)
        {
            _dir = new Vector3(1, 0, 0);
        }
        else
        {
            _dir = new Vector3(0, 0, 1);
        }
    }
}

编辑完后 ctrl+s保存,返货到unity界面执行下面操作
在这里插入图片描述
运行结果如图
在这里插入图片描述
至此我们完成了生成盒子的操作

4.使player能够完成跳动

在脚本中updata中添加如下代码

if (Input.GetKeyDown(KeyCode.Space))//判断是否按下space
        {
            start_time = Time.time;//记录按下space的时间
        }

        if (Input.GetKeyUp(KeyCode.Space))//判断是否松开按键
        {
            var time = Time.time - start_time;//计算按键时间
            jump(time);
        }

创建使player跳跃函数

void jump(float time)
    {
        //给player添加瞬间力
        //Factor为控制player跳跃速度的控制基数
        rig1.AddForce((new Vector3(0, 2, 0) + _dir) * time * Factor, ForceMode.Impulse);
    }

5.调整player的重心

我们发现此实player跳跃后容易摔倒,所以我们要经过下面操作调整player重心,使其不倒

首先在player上建立空物体,并将其位置移动到player最低端在这里插入图片描述

然后通过代码调正重心
在这里插入图片描述
在这里插入图片描述

6.实现盒子及player按下space时的动画

在这里插入图片描述
将updata中代码改成这样

if (Input.GetKeyDown(KeyCode.Space))//判断是否按下space
        {
            _head = head.transform.localPosition;//记录缩放前头部位置
            _body = body.transform.localScale;//记录缩放前身体大小
            _stand_box = stand_box.transform.localScale;//记录盒子大小
            start_time = Time.time;//记录按下space的时间
        }

        if (Input.GetKeyUp(KeyCode.Space))//判断是否松开按键
        {
            var time = Time.time - start_time;//计算按键时间
            jump(time);
            body.transform.localScale = _body;//身体还原
            head.transform.localPosition = _head;
            stand_box.transform.localScale = _stand_box;//盒子还原
        }
        if (Input.GetKey(KeyCode.Space))
        {

            head.transform.localPosition += new Vector3(0, -1, 0) * 0.1f * Time.deltaTime;//头动画缩小
            body.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//身体动画缩小

            stand_box.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//盒子动画缩小

        }

7.当player跳落在盒子上生成下一个盒子以及销毁前一个盒子

当判断player落在盒子上时,要使用碰撞事件函数,而碰撞事件函数的基条件是存在碰撞器,所以我们要在player和盒子上添加碰撞器(collider)
在这里插入图片描述
然后调成碰撞其大小及位置使其将player完全笼罩
(盒子碰撞器添加方法和player相似 在此不多说,注意:盒子添加完碰撞器后要将prefab中的盒子替换

然后我们需要添加碰撞事件的函数

  void OnCollisionEnter(Collision collision)//碰撞事件函数
    {
        Debug.Log(collision.gameObject.name);//打印与player碰撞的物体的名字
        Collider collider_box = stand_box.GetComponent<Collider>();//获取player原来所在盒子的碰撞器
        if (collision.gameObject.name.Contains("Cube") && collider_box != collision.collider)//判断是否与盒子碰撞且碰撞的盒子是否不同于上一个盒子
        {
            GameObject destory_box = stand_box;//定义将要销毁的盒子
            stand_box = new_box;//将player所在盒子进行刷新
            putBox();//生成新的盒子
            Destroy(destory_box);

        }
        if (collision.gameObject.name == "ground")
        {
            SceneManager.LoadScene(0);//重新开始游戏,需要引入头文件:using UnityEngine.SceneManagement;
        }
    }

同时需要将原来的代码进行少许改动
在这里插入图片描述
在这里插入图片描述

运行了一下,发现盒子生成时可能会产生bug:盒子会形成相互重叠,原因是盒子大小和生成距离的范围有关,自行进行调整即可
在这里插入图片描述
在这里插入图片描述

还有一个bug就是盒子总是按照一个方向生成,原因是在生成盒子函数中未调用随机生成方向函数,自己填补即可

8.实现相机跟随

首先需要定义一个相机的位置的公共变量和一个相机与player位之差的常量
在这里插入图片描述
然后在脚本执行开始时计算相机与player的位置差
在这里插入图片描述
随后添加相机移动函数

void MoveCamera()//相机跟随函数
    {
        Camera.position = transform.position + _cameraRelativeTranfrom;//移动相机:相机位置等于小人目前位置加相对位置
    }

9.分数显示

创建text 并将其位置进行调整,然后在属性栏中进行自适应(途中将其设置为左上角显示)
自适应之后无论装口大小怎样改变,其位置依然在左上角
在这里插入图片描述
添加下面两个变量
在这里插入图片描述
在start中初始化
在这里插入图片描述
在成功跳跃后分数加一
在这里插入图片描述

10.蓄力效果

在player中添加例子特效(如图),并对其在属性栏中进行大小形状设置
在这里插入图片描述

在代码中定义public Object lizi;

开启代码:lizi.SetActive(true);
关闭代码:lizi.SetActive(false);

整个程序源码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class player : MonoBehaviour
{
    public GameObject stand_box;//当前player所在盒子
    public float maxDis;//生成盒子与上一个盒子的最大距离
    public GameObject _box;//获取生成的盒子对应的预制体
    public float Factor;//实现速度基数
    public Transform transform1;//获取player中空物体的位置
    public Transform head;//记录player的头部位置
    public Transform body;//记录player的身体位置
    public Transform Camera;//相机位置,实现相机跟随时用到
    public Text sco;//记录分数,需要添加:using UnityEngine.UI;
    public GameObject lizi;//例子特效


    private Vector3 _dir = new Vector3(1, 0, 0);//生成第二个盒子的方向变量
    private Rigidbody rig1;//获取player刚体组件
    private float start_time;//记录按下开始space的时间
    private GameObject new_box;//新生成的盒子
    private static Vector3 _cameraRelativeTranfrom;//相机需要移动距离
    //记录player位置和大小及当前盒子大小
    Vector3 _head = new Vector3(0, 0, 0);
    Vector3 _body = new Vector3(0, 0, 0);
    Vector3 _stand_box = new Vector3(0, 0, 0);
    private int _sco;

    // Start is called before the first frame update
    void Start()
    {
        lizi.SetActive(false);//默认粒子特效为关闭状态
        _sco = 0;//分数初始化
        sco.text = _sco.ToString();//分数更新
        _cameraRelativeTranfrom = Camera.position - transform.position;//计算相机对于player的相对位置
        rig1 = GetComponent<Rigidbody>();//获取player的Rigidbody组件,因为此脚本挂在player上,所以默认获取player的刚体组件,可以查资料学习一下怎样获取指定物体组件
        rig1.centerOfMass = transform1.localPosition;//将物体重心放在playwe中空物体的位置
        putBox();//调用生成盒子函数
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))//判断是否按下space
        {
            lizi.SetActive(true);//开启粒子特效
            _head = head.transform.localPosition;//记录缩放前头部位置
            _body = body.transform.localScale;//记录缩放前身体大小
            _stand_box = stand_box.transform.localScale;//记录盒子大小
            start_time = Time.time;//记录按下space的时间
        }

        if (Input.GetKeyUp(KeyCode.Space))//判断是否松开按键
        {
            lizi.SetActive(false);//关闭粒子特效
            var time = Time.time - start_time;//计算按键时间
            jump(time);
            body.transform.localScale = _body;//身体还原
            head.transform.localPosition = _head;
            stand_box.transform.localScale = _stand_box;//盒子还原
        }
        if (Input.GetKey(KeyCode.Space))
        {

            head.transform.localPosition += new Vector3(0, -1, 0) * 0.1f * Time.deltaTime;//头动画缩小
            body.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//身体动画缩小

            stand_box.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//盒子动画缩小

        }
    }

    void putBox()
    {
        Random_dir();//调用随机生成盒子方向函数
        new_box = Instantiate(_box);//实例化盒子
        new_box.transform.position = stand_box.transform.position + _dir * Random.Range(4.5f, maxDis);//设置盒子位置
        var a = Random.Range(1f, 2);//生成一个随机数
        new_box.transform.localScale = new Vector3(a, 1.108432f, a);//改变盒子scale(尺寸)中的x(长)与z(宽)全部为生成的随机数
    }

    void Random_dir()//随机盒子生成方向
    {
        var a = Random.Range(0, 2);//随机生成0,1两个数
        if (a == 0)
        {
            _dir = new Vector3(1, 0, 0);
        }
        else
        {
            _dir = new Vector3(0, 0, 1);
        }
    }

    void jump(float time)
    {
        //给player添加瞬间力
        //Factor为控制player跳跃速度的控制基数
        rig1.AddForce((new Vector3(0, 2, 0) + _dir) * time * Factor, ForceMode.Impulse);
    }

    void OnCollisionEnter(Collision collision)//碰撞事件函数
    {
        Debug.Log(collision.gameObject.name);//打印与player碰撞的物体的名字
        Collider collider_box = stand_box.GetComponent<Collider>();//获取player原来所在盒子的碰撞器
        if (collision.gameObject.name.Contains("Cube") && collider_box != collision.collider)//判断是否与盒子碰撞且碰撞的盒子是否不同于上一个盒子
        {
            _sco++;//分数加一
            sco.text = _sco.ToString();//将分数更新
            MoveCamera();
            GameObject destory_box = stand_box;//定义将要销毁的盒子
            stand_box = new_box;//将player所在盒子进行刷新
            putBox();//生成新的盒子
            Destroy(destory_box);

        }
        if (collision.gameObject.name == "ground")
        {
            SceneManager.LoadScene(0);//重新开始游戏,需要引入头文件:using UnityEngine.SceneManagement;
        }
    }

    void MoveCamera()//相机跟随函数
    {
        Camera.position = transform.position + _cameraRelativeTranfrom;//移动相机:相机位置等于小人目前位置加相对位置
    }
}

工程下载地址:链接:https://pan.baidu.com/s/16_drASFV6Fk5ILGQU5QGlA
提取码:ew0g

unity开发跳一跳至此告一段落
留给大家些许bug,评论区见,欢迎大家前来指点

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

unity之跳一跳(完整版) 的相关文章

  • 从 Makefile 中的 C++FLAGS 中删除一个标志?

    我有一个 Makefile 其中包含另一个设置了很多默认值的 makefile 我无法编辑包含的 makefile 并且我想更改 makefile 中 C FLAGS 的值 即使它是在包含的 makefile 中设置的 具体来说 每当 de
  • 如何将动态数据写入 MVC 3 Razor 中的页面布局?

    我有带有 Razor 引擎的 MVC 3 C 项目 将动态数据写入 Layout cshtml 的方法和最佳实践是什么 例如 也许我想在网站的右上角显示用户名 该名称来自会话 数据库或基于用户登录的任何内容 更新 我也在寻找将某些数据渲染到
  • ptrace和waitpid有什么关系?

    我正在练习使用ptrace但我不太了解它和之间的关系waitpid 这是我的测试程序 int main int argc char argv pid t pid 22092 if ptrace PTRACE ATTACH pid NULL
  • 这种对有效类型规则的使用是否严格遵守?

    C99和C11中的有效类型规则规定 没有声明类型的存储可以用任何类型写入 并且存储非字符类型的值将相应地设置存储的有效类型 抛开 INT MAX 可能小于 123456789 的事实不谈 以下代码对有效类型规则的使用是否严格符合 inclu
  • 如何进行Visual Studio格式字典初始化?

    所有 Visual Studio 也包括 2012 不格式化以下内容 messageProcessor new Dictionary
  • 如何使用 libclang 判断成员函数是 const 还是 volatile?

    我有一个实例CXCursor同类CXCursor CXXMethod 我想知道这个函数是否是const or volatile 例如 class Foo public void bar const void baz volatile voi
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • 使用正则表达式解析日志文件

    我目前正在为我们的内部日志文件 由 log4php log4net 和 log4j 生成 开发一个解析器 到目前为止 我有一个很好的正则表达式来解析日志 除了一个烦人的一点 一些日志消息跨越多行 我无法正确匹配 我现在的正则表达式是这样的
  • 我们什么时候应该在.NET中使用NativeMemory.Alloc()? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 NET6 C 引入NativeMemory类 但我不知道什么时候应该使用NativeMemory Alloc 而不是普通的数组实例化
  • 无法在 Visual Studio 和 vcpkg 中构建 cmake 项目(致命错误 C1083)

    我今天安装了vcpkg 启用了与Visual Studio的集成 即 vcpkg集成安装 并开始安装库 我基本上安装了 cpprestsdk 并触发了 boost 库的安装 然后我在 Visual Studio CMake 中打开该项目 当
  • C# 中不区分大小写的替换不使用正则表达式?

    有没有一种方法可以在不使用 C 中的正则表达式的情况下对字符串进行不区分大小写的替换 像这样的东西 string x Hello x x Replace hello hello world 你可以尝试类似的东西 string str Hel
  • 我如何模拟 UserManager 和 RoleManager 进行单元测试

    我模拟了抽象类来测试类的具体方法 如下所示 var mock new Mock
  • 使用 ClosedXML 附加到 excel 文件

    我需要将新数据附加到使用 ClosedXML 创建的现有 Excel 文件中 如何使用 ClosedXML 附加到 Excel 文件 如何获取最后一条记录的行号并将其附加到该行号上 或者还有其他内容 Thanks 打开现有工作簿 然后使用L
  • 没有 FPU 的处理器中的浮点计算

    是否可以在没有浮点单元的嵌入式处理器中执行浮点运算 是的 您只需要在软件中完成即可 你的编译器可能会提供支持 http gcc gnu org onlinedocs gccint Soft float library routines ht
  • 在 C++ 中什么时候首选传递指针而不是引用传递?

    我可以想象一种情况 其中输入参数可以为 NULL 以便首选传递指针而不是传递引用 有人可以添加更多案例吗 在传递的对象实际上将被修改的情况下 有些人更喜欢传递指针 当对象通过引用传递时 它们使用 pass by const referenc
  • 为什么 getch 不可移植?

    是什么使得 getch 本质上无法作为标准 C 函数包含在内 对于控制台界面来说 它是如此直观和优雅 如果没有它 要求输入单个字符总是会产生误导 因为用户可以输入多个键 更糟糕的是 您经常需要确保在读取控制台输入后清除标准输入 这甚至不是作
  • OpenCV 仅围绕大轮廓绘制矩形?

    第一次发帖 希望我以正确的方式放置代码 我正在尝试检测和计算视频中的车辆 因此 如果您查看下面的代码 我会在阈值处理和膨胀后找到图像的轮廓 然后我使用 drawContours 和矩形在检测到的轮廓周围绘制一个框 我试图在 drawCont
  • 如何在c#中获取斐波那契数

    伙计们 我有一个关于斐波那契的问题 如何获得斐波那契数列 该数字也将以用户输入结束 例如 如果我输入 21 则输出必须为 0 1 1 2 3 5 8 13 21 这是我的代码 static void Main string args int
  • 从 git 签出后 nuget dll 丢失

    I have a C solution containing different projects On those projects I have some normal nuget packages like Newtonsoft Js
  • 在地图上使用 find

    如何使用 find 和 aconst iterator如果你有一个地图定义为 typedef std pair

随机推荐

  • 2017校招Java开发笔试题集

    美丽联合 二分查找要求结点 A 有序 顺序存储 B 有序 链接存储 C 无序 顺序存储 D 无序 链接存储 答案选 A 引入线索二叉树的目的是 A 加快查找结点的前驱或后继结点的速度 B 为了能在二叉树中方便插入和删除 C 为了能方便找到双
  • 使用STM32CubeMx配置STM32输入捕获功能

    输入捕获原理 在输入捕获模式下 当检测到ICx信号上相应的边沿后 计数器的当前值被锁存到捕获 比较寄存 器 TIMx CCRx 中 当发生捕获事件时 相应的CCxIF标志 TIMx SR寄存器 被置1 如果开放 了中断或者DMA操作 则将产
  • tools:context=".MainActivity的作用

    http blog csdn net caiwenfeng for 23 article details 8373569
  • Spring AOP 的搭建与源码分析

    AOP 面向切面编程 一 AOP 概述 AOP 的实现步骤 示例 二 通过 EnableAspectJAutoProxy 了解 AOP 原理 1 分析 EnableAspectJAutoProxy 2 复习 Spring 容器启动后 bea
  • Jq手搓一个简易版分页器

    分页器的效果如下 1 分页器dom结构 前面要有你将渲染列表的dom结构 这里省略 div class news trends fy div class left img src imags nof icon left png 左箭头 di
  • python异步爬虫

    本文主要包括以下内容 线程池实现并发爬虫 回调方法实现异步爬虫 协程技术的介绍 一个基于协程的异步编程模型 协程实现异步爬虫 线程池 回调 协程 我们希望通过并发执行来加快爬虫抓取页面的速度 一般的实现方式有三种 线程池方式 开一个线程池
  • 2023华为od机试统一考试B卷【雨花石难题】

    题目描述 MELON是一个热爱雨花石的人 他拥有一堆数量为n的精美雨花石 每块石头的重量都不相同 现在 MELON想要将这些雨花石平均分给他的朋友S和W 以使两人所得到的石头的重量相等 你需要设计一个程序 来帮助MELON确认是否可以实现这
  • 近期思维片段

    1 感觉360这样的公司就是让少数明眼人讨厌 让大多数人不知不觉接受 2 点子 lt 我买了 gt 购物分享 把自己买过的经验分享出来 3 不要负面思维 No negative thinking 4 突然想起几年前那些熟悉的名字 现在都没有
  • js匹配数组中对应的值_JS 数组中查找符合条件的数据索引

    日常工作中经常会需要我们前端获取后端为我们传递的数据放在页面中渲染的问题 大批量的数据后端会根据具体的情况来放在数组中传递给我们 但是如果遇到数组中有需要特殊需要处理的数据怎么办 原来100个数据 渲染规则完全一致 这个时候我们用一个循环就
  • 阿里云服务器安装宝塔面板图文教程

    购买完云服务器ECS后 对于新手而言如何搭建Web环境是比较棘手的 分享一款简单易用的主机面板 宝塔面板 分享阿里云服务器安装宝塔面板图文教程 本文以 Linux云服务器 CentOS 7 4 64位系统为例 一 开放安全组端口 什么是安全
  • 【已解决】使用pyaudio内录声卡声音及相关问题

    使用pyaudio内录声卡声音及相关问题解决 目录 使用pyaudio内录声卡声音及相关问题解决 1 实现代码 1 1 Recorder类 1 2 调用方法 2 问题一 选择设备实现内录 外录 解决报错 OSError Errno 9999
  • java中的异常

    throw和throws的区别 相同 都是用于做异常的抛出处理的 不同点 使用的位置 throws 使用在函数上 throw使用在函数内 后面接受的内容的个数不同 throws 后跟的是异常类 可以跟多个 用逗号隔开 throws只声明异常
  • python中rsa解密_python中的RSA加密和J中的解密

    我对密码学完全陌生 我想从服务器端生成RSA密钥对并将其发送到所有客户端 浏览器 但在此之前 我只需在python中加密数据并发送到索引 html文件 并尝试用JavaScript解密 问题是当我通过random generator Ran
  • CMake 用法导览

    原文地址 http www cnblogs com coderfenghc archive 2013 01 20 2846621 html Preface 本文是CMake官方文档CMake Tutorial http www cmake
  • Unity中定时器的简易使用

    定时器写法1 float total time void Update this total time Time deltaTime if total time gt 5 5秒后停止 return 定时器写法2 void Hello thi
  • Linux部署Tomcat无法访问

    前言 环境 RedHat7 0 Tomcat7 JDK7 安装配置成功之后 启动tomcat服务 然后使用本地浏览器访问http xx xx xx xx 8080 无法访问 解决过程 首先怀疑是配置问题 终端输出 echo JAVA HOM
  • Java CSV文件读取、写入及追加工具类

    Java CSV文件读取 写入及追加工具类 追加 FileOutputStream out new FileOutputStream file true 第二个参数true代表追加 CSVUtil java import lombok ex
  • 计算机毕业设计-基于微信小程序高校学生课堂扫码考勤签到系统-校园考勤打卡签到小程序

    注意 该项目只展示部分功能 如需了解 评论区咨询即可 本文目录 1 开发环境 2 系统的设计背景 3 各角色功能模块 3 1 用户 3 2 管理员 4 系统页面展示 4 1 学生端功能模块展示 4 2 教师端功能模块展示 5 更多推荐 6
  • 【JavaScript数据结构与算法】字符串类(计算二进制子串)

    个人简介 个人主页 前端杂货铺 学习方向 主攻前端方向 也会涉及到服务端 Node js 个人状态 在校大学生一枚 已拿多个前端 offer 秋招 未来打算 为中国的工业软件事业效力 n 年 推荐学习 前端面试宝典 Vue2 Vue3 Vu
  • unity之跳一跳(完整版)

    1 场景 1 creat gt 3D objict gt plane 并重命名为ground 做为地面 如下图 2 并调整颜色 大小至适合 如下图 调正颜色 创建material project creat gt Material 用与当作