Unity3D学习FPS游戏(4)重力模拟和角色跳跃
前言:前面两篇文章,已经实现了角色的移动和视角转动,但是角色并没有办法跳跃,有时候还会随着视角移动跑到天上。这是因为缺少重力系统,本篇将实现重力和角色跳跃功能。觉得有帮助的话可以点赞收藏支持一下!
重力模拟和角色跳跃
- 问题-太空人
- 地面检测
- 重力模拟
- 跳跃
- 完整代码
- 效果
- 补充知识
- Property Attributes自定义属性
- Time.fixedDeltaTime
问题-太空人
回到我们第二篇讲角色控制的三种方法中,提到了CharacterController虽然有碰撞但是是没有力的作用的,也就意味着没有重力效果。
地面检测
可以利用CharacterController.isGrounded来判断是否碰到地面。
但是要注意一下函数的功能定义:
isGrounded: Was the CharacterController touching the ground during the last move?
意思是判断的是上一次调用CharacterController.Move时有没有触地。
如果遇到isGrounded如果恒为false可能要注意,判断之前是不是还没有调用过Move。
重力模拟
非常简单,利用学过物理基本的公式a*t=v(加速度*时间=速度)、v*t=s(速度*时间=距离),就可以模拟出来。
新增重力加速度playerGravity和垂直速度verticalVelocity,当碰到地面时候垂直速度是0;当没有碰到地面的时候,垂直速度会随着受力一直变化,速度+=加速度*单位时间。在空中只有重力,对应代码就是verticalVelocity-=playerGravity*Time.fixedDeltaTime,为什么是减号因为重力是向下的,有方向。
最后把因为重力导致位移变化也一起Move就可以了。
public float playerGravity = 9.8F;// 重力加速度
public float verticalVelocity = 0;// 垂直速度
public void PlayerMovement()
{Vector3 moveDirection = Vector3.zero;// 获取键盘输入:Horizontal左右移动;Vertical前后移动// 加入自身tranform方向moveDirection = Vector3.zero;moveDirection += transform.forward * Input.GetAxis("Vertical");moveDirection += transform.right * Input.GetAxis("Horizontal");moveDirection *= Time.deltaTime * moveSpeed;// 重力if (!m_Controller.isGrounded)verticalVelocity -= playerGravity * Time.fixedDeltaTime;// a*t=velseverticalVelocity = 0.0F;moveDirection.y += verticalVelocity * Time.fixedDeltaTime;// v*t=s// 移动m_Controller.Move(moveDirection);
}
由于涉及到了物理模拟,所以时间增量都改用了Time.fixedDeltaTime,并在FixedUpdate更新。这个使用Time.fixedDeltaTime具体原因在补充知识中有详细说明。
跳跃
有了重力,跳跃才有作用。
简单跳跃
跳跃的思路,首先不能多段跳,就是要碰到地面才能响应跳跃按键,跳跃后角色会上升一定高度。
添加一个玩家跳跃高度参数jumpHeight,直接让角色位移到jumpHeight,就能实现一个简单的跳跃效果
public float jumpHeight = 2F;
public void PlayerMovement()
{Vector3 moveDirection = Vector3.zero;// 获取键盘输入:Horizontal左右移动;Vertical前后移动// 加入自身tranform方向moveDirection = Vector3.zero;moveDirection += transform.forward * Input.GetAxis("Vertical");moveDirection += transform.right * Input.GetAxis("Horizontal");moveDirection *= Time.deltaTime * moveSpeed;// 重力if (!m_Controller.isGrounded)verticalVelocity -= playerGravity * Time.fixedDeltaTime;// a*t=velseverticalVelocity = 0.0F;moveDirection.y += verticalVelocity * Time.fixedDeltaTime;// v*t=s// 跳跃if (Input.GetButton("Jump")){// 得在地面才能跳if (m_Controller.isGrounded){moveDirection.y += jumpHeight;}}// 移动m_Controller.Move(moveDirection);
}
跳跃优化
上面简单的跳跃,虽然能够实现跳跃功能,但是非常不自然,就是一下子跳到最高,又慢慢下来。
实际游戏中,我们的跳跃真正其实是一个抛物线。
也就向上跳到最顶的时候,也有个速度变化。
跳起来的时候会有一个向上的速度,之后不触地都是只受到重力作用了。所以点击跳跃按钮后,我们只需要算出这个跳起来一瞬间的向上速度是多少就行了。
还是最基础的物理公式推导:
a*t=v(加速度*时间=速度)、v*t=s(速度*时间=距离),设定跳跃的最高的高度h(jumpHeight)。
从最低点到最高点,通过h=0.5*a*t2,可以把总共的时长算出来,由于受力只有重力,通过重力加速度*总时长=初始向上速度。
verticalVelocity = Mathf.Sqrt(jumpHeight * 2 / playerGravity) * playerGravity;// 初始向上速度
于是新的代码就是:
public float jumpHeight = 2F;
public float verticalVelocity = 0;// 垂直速度
public void PlayerMovement()
{Vector3 moveDirection = Vector3.zero;// 获取键盘输入:Horizontal左右移动;Vertical前后移动// 加入自身tranform方向moveDirection = Vector3.zero;moveDirection += transform.forward * Input.GetAxis("Vertical");moveDirection += transform.right * Input.GetAxis("Horizontal");moveDirection *= Time.fixedDeltaTime * moveSpeed;// 重力if (!m_Controller.isGrounded)verticalVelocity -= playerGravity * Time.fixedDeltaTime;// a*t=velseverticalVelocity = 0.0F;// 跳跃if (Input.GetButton("Jump")){// 得在地面才能跳if (m_Controller.isGrounded){verticalVelocity = Mathf.Sqrt(jumpHeight * 2 / playerGravity) * playerGravity;// 初始向上速度}}moveDirection.y += verticalVelocity * Time.fixedDeltaTime;// v*t=s// 移动m_Controller.Move(moveDirection);
}
完整代码
具有角色移动、视角、重力和跳跃的完整PlayerController代码。
public class PlayerController : MonoBehaviour
{[Header("Unity组件")]public CharacterController m_Controller;public Transform playerCamera;[Header("玩家数值")]public float moveSpeed = 6.0F;public float mouseSensitivity = 1000.0F;public float playerGravity = 9.8F;public float jumpHeight = 2F;public float verticalVelocity = 0;// 垂直速度private float x_RotationOffset = 0;// 累计x旋转private float y_RotationOffset = 0;// 累计y旋转void Start(){m_Controller = this.GetComponent<CharacterController>();Cursor.lockState = CursorLockMode.Locked;// 鼠标锁定}private void FixedUpdate(){PlayerRotation();PlayerMovement();}// 控制角色移动public void PlayerMovement(){Vector3 moveDirection = Vector3.zero;// 获取键盘输入:Horizontal左右移动;Vertical前后移动// 加入自身tranform方向moveDirection = Vector3.zero;moveDirection += transform.forward * Input.GetAxis("Vertical");moveDirection += transform.right * Input.GetAxis("Horizontal");moveDirection *= Time.fixedDeltaTime * moveSpeed;// 重力if (!m_Controller.isGrounded)verticalVelocity -= playerGravity * Time.fixedDeltaTime;// a*t=velseverticalVelocity = 0.0F;// 跳跃if (Input.GetButton("Jump")){// 得在地面才能跳if (m_Controller.isGrounded){verticalVelocity = Mathf.Sqrt(jumpHeight * 2 / playerGravity) * playerGravity;// 初始向上速度}}moveDirection.y += verticalVelocity * Time.fixedDeltaTime;// v*t=s// 移动m_Controller.Move(moveDirection);}// 控制角色视角private void PlayerRotation(){// 获取鼠标移动x_RotationOffset += Input.GetAxis("Mouse X")* Time.fixedDeltaTime * mouseSensitivity;// 水平方向y_RotationOffset += Input.GetAxis("Mouse Y")* Time.fixedDeltaTime * mouseSensitivity;// 垂直方向// 限制垂直旋转角度y_RotationOffset = Mathf.Clamp(y_RotationOffset, -45f, 45f);// 旋转transform.rotation = Quaternion.Euler(new Vector3(0, x_RotationOffset, 0));// Player旋转playerCamera.localRotation= Quaternion.Euler(new Vector3(y_RotationOffset, playerCamera.localEulerAngles.y, playerCamera.localEulerAngles.z));// Camera旋转}
}
效果
简单跳跃。
优化后的跳跃。
补充知识
Property Attributes自定义属性
我们写代码的时候,会写一些属性在Inspector中也能修改,方便查看不同值的表现效果。
例如我们现在PlayerController中的moveSpeed和playerGravity等,但是要定义为Public。
Property Attributes提供了很多内置属性,方便Inspector查看自定义的属性和修改。
常用的有:
- [Header(“xxx”)]给变量在Inspector中添加标题头
- [Space(xx)]在Inspector中添加间隔
- [Range(xx, xx)]在Inspector中变量为滑动条范围
- [Tooltip(“xxx”)]为变量在Inspector中添加说明(像可以在Inspector查看的注释)
里面的文本文字可以是中文。
有这些能让我们代码更加优雅😀,也方便和别人共事的时候更好阅读使用我们的代码。
Time.fixedDeltaTime
fixedDeltatime是一个固定的时间增量不会随着帧率变换而变化,要在FixedUpdate中使用。
通常来说fixedDeltatime固定是0.02s,在主菜单的Edit→Project Settings→Time可以修改。
之前我们用的帧率相关的增量时间,但是现在开始已经涉及到了物理模拟了,物理更新对时间是非常敏感的,稍微差一点都不行。如果用在按帧率更新,可能由于主机差异帧率不稳定,0.5秒子弹到达敌人,帧率不稳定可能会变成0.8s。
相关文章:
Unity3D学习FPS游戏(4)重力模拟和角色跳跃
前言:前面两篇文章,已经实现了角色的移动和视角转动,但是角色并没有办法跳跃,有时候还会随着视角移动跑到天上。这是因为缺少重力系统,本篇将实现重力和角色跳跃功能。觉得有帮助的话可以点赞收藏支持一下!…...
C#基础知识-枚举
目录 枚举 1.分类 1.1普通枚举 1)默认情况 2)指定起始值 1.2标志枚举(Flag Enum) 位运算符与标志枚举 1)组合标志 2)检查标志 2.枚举与不同类型之间的转换 1)枚举->整型 2&#…...
系统架构设计师教程 第2章 2.1-2计算机系统及硬件 笔记
2.1计算机系统概述 ★☆☆☆☆ 计算机系统 (Computer System) 是指用于数据管理的计算机硬件、软件及网络组成的系统。 一般指由硬件子系统和软件子系统组成的系统,简称为计算机。 将连接多个计算机以实现计算机间数据交换能力的网络设备,称为计算机网…...
通过使用Visual Studio将你的程序一键发布到Docker
通过使用Visual Studio将你的程序一键发布到Docker 代码 阿里云容器镜像服务 https://www.aliyun.com/product/acr 添加Docker CE阿里云镜像仓库 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 安装Docker CE、Doc…...
vue2和vue3动态引入路由,权限控制
后端返回的路由结构(具体路由可以本地模拟) // 此路由自己本地模拟即可 const menus [{"title": "动态路由","meta": "{\"title\":\"动态路由\",\"noCache\":true}","component": "/t…...
Spring Boot:植物健康的智能守护者
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
红黑树 学习笔记
目录 1.红黑树的概念 1.1红黑树的规则 1.2红黑树的效率 2.红黑树的实现 2.1红黑树的大致结构 2.2红黑树的插入 2.2.1红黑树插入的大致过程 2.2.2情况1:变色 2.2.3情况2:单旋+变色 2.2.4情况3:双旋变色 2.3红黑树的查找…...
linux更改系统时间
测试环境和生产环境代码完全一致,但是生产环境代码碰到了问题,报错类似time expired,猜测和系统时间有关系,修改之后确实好了。测试如下: 参考:centos7时间同步教程_centos7 时间同步,如果遇到…...
B站C#刘铁猛笔记
C#——刘铁猛笔记 类、名称空间(简述) 类(class)是构成程序的主体 名称空间(namespace)以树形结构组织类(其他类型) 名称空间:名称空间是用来组织和管理类、接口、结构…...
如何使用信号发生器产生正弦波并用数字示波器进行测量
使用信号发生器产生正弦波并用数字示波器进行测量的步骤如下: 1. 准备工作 所需设备 信号发生器数字示波器探头(通常为10X衰减探头)BNC电缆和适配器(如果需要) 2. 设置信号发生器 连接 使用BNC电缆将信号发生器的…...
XJ04、消费金融|授信基本概念及其流程设计
银行是经营风险的特殊行业,而银行授信则与银行业务和风险天然相伴。它是银行与客户建立业务关系的起点,也是银行风险管理的关键环节和核心要素。若要了解银行业务,就得先了解银行的授信业务;若要理解银行经营,就得先理…...
儿童预防接种预约微信小程序springboot+论文源码调试讲解
2相关技术 2.1微信小程序 小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。尤其拥抱微信生态圈,让微信小程序更加的如虎添翼,发展迅猛。 2.2 MYSQL数据…...
nginx 修改配置
如果你的后端服务在不同的端口上运行,但静态资源访问路径相同,你可以使用 Nginx 的 location 配置来将请求转发到不同的后端服务,同时处理静态文件。这里有几种常见的方式: 方案 1: 基于路径的配置 如果所有服务的静态资源路径相…...
孤岛架构在安全性方面
孤岛架构在安全性方面的考虑主要涉及如何确保每个孤岛的安全性,同时维护整个系统的安全。 关键的安全性考虑: 1. 数据隔离和访问控制 数据隔离:每个孤岛应该有独立的数据存储,以确保数据隔离。这有助于防止数据泄露和未经授权的…...
COSCon'24 志愿者招募令:共创开源新生活!
亲爱的开源爱好者们, 第九届中国开源年会(COSCon24)即将在北京中关村国家自主创新示范区会议中心于2024年11月2日至3日隆重举行。今年的主题是“Open Source, Open Life|开源新生活”,旨在探索开源技术如何在各个领域推…...
vscode使用make编译c的问题
问题1:makefile:2: *** missing separator. Stop vscode的配置问题,看这哥们的文章即可:https://blog.csdn.net/m0_57464986/article/details/134220676 问题2:创建makefile文件 直接创建文件名为“makefile”的文件即可&#x…...
管家婆财贸ERP BB019.操作员制单日期控制
最低适用版本: 财贸系列 20.0 插件简要功能说明: 定制操作员权限功能,根据服务器日期控制系统单据新增和修改更多细节描述见下方详细文档 插件操作视频: 进销存类定制插件--操作员制单日期控制 插件详细功能文档: …...
从 Vue 2 到 Vue 3:全面升级指南
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Vuet篇专栏内容:Vue-从 Vue 2 到 Vue 3:全面升级指南 前言 随着前端技术的不断发展,Vue.j…...
Apache paimon表操作实战-5
维表Join Paimon支持Lookup Join语法,它用于从 Paimon 查询的数据来补充维度字段。要求一个表具有处理时间属性,而另一个表由查找源连接器支持。 Paimon 支持 Flink 中具有主键的表和append-only的表查找联接。以下示例说明了此功能。 USE CATALOG fs_catalog; CREATE TABL…...
阿里云用STS上传oss的完整程序执行流程图 和前端需要哪些参数uniapp
H5 微信小程序可用的前端直传阿里云OSS(STS临时凭证前端签名)直接下载插件 下面是原理说明: 明白了,我来详细说明前端上传文件到阿里云OSS需要携带的具体参数: 从服务器获取的 STS 凭证: // 这些参数需要从你的后端服务器获…...
决策树方法根据指定条件筛选方案
代码功能说明 条件类:Condition 类用于定义每个条件的范围,并提供一个方法 is_satisfied 来检查输入值是否满足该条件。 算法选择器类:AlgorithmSelector 类负责应用条件并记录不满足的条件。它提供方法 apply_condition 用于更新可用算法&a…...
多特征变量序列预测(四) Transformer-BiLSTM风速预测模型
往期精彩内容: 时序预测:LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较 全是干货 | 数据集、学习资料、建模资源分享! EMD、EEMD、FEEMD、CEEMD、CEEMDAN的区别、原理和Python实现(一)EMD-CSDN博客 EMD、EEM…...
【开源免费】基于SpringBoot+Vue.JS蜗牛兼职平台 (JAVA毕业设计)
本文项目编号 T 034 ,文末自助获取源码 \color{red}{T034,文末自助获取源码} T034,文末自助获取源码 目录 一、系统介绍1.1 平台架构1.2 管理后台1.3 用户网页端1.4 技术特点 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景…...
Ajax笔记
介绍 Ajax是一种网页开发技术,全称是Asynchronous JavaScript and XML(异步JavaScript和XML)。作用如下: 数据交换:可以通过Ajax给服务器发送请求,并获取服务器响应的数据。即前端动态的发送Ajax到服务器端…...
软考:缓存分片和一致性哈希
缓存分片技术是一种将数据分散存储在多个节点上的方法,它在分布式缓存系统中尤为重要。这项技术的核心目的是提高系统的性能和可扩展性,同时确保数据的高可用性。以下是缓存分片技术的一些关键点: 数据分片:缓存分片涉及将数据分成…...
3109 体验积分值
经验值:1200 时间限制:1000毫秒 内存限制:128MB 合肥市第34届信息学竞赛(2017年) 不许抄袭,一旦发现,直接清空经验! 题目描述 Description 卡卡西和小朋友们做完了烧脑的数字游…...
初识jsp
学习本章节前建议先安装Tomcat web服务器:tomcat下载安装及配置教程_tomcat安装-CSDN博客 1、概念 我的第一个JSP程序: 在WEB-INF目录之外创建一个index.jsp文件,然后这个文件中没有任何内容。将上面的项目部署之后,启动服务器…...
Ansible 的脚本 --- playbooks剧本
playbooks 本身由以下各部分组成 (1)Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行 (2)Vars:变量 (3)Templates:模板 &a…...
Windows 死机时 系统错误日志分析与故障排除
目录 前言正文 前言 对于服务器异常重启,推荐阅读:详细分析服务器自动重启原因(涉及Linux、Window) 以下主要做一个总结梳理 正文 查看系统事件日志: 可以查看系统事件日志,找出可能导致系统崩溃的错误…...
基于pytorch搭建CNN
先上代码 import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torchvision import datasets, transforms import matplotlib.pyplot as plt import numpy as np import pandas as pd import matplotlibmatplotlib.use(tkA…...
wordpress中文别名分类目录/seow
根据于渊老师的《Orange’s 一个操作系统的实现》我开始了操作系统的制作 首先进行了helloworld的编写,大体过程是: 1.了解什么语言编写操作系统 书中给出:汇编与c,但是helloworld编写仅仅是汇编,我也看不懂 直接复…...
台州做鞋子网站/站长查询站长工具
点击上方“计算机视觉life”,选择“星标”快速获得最新干货全国SLAM技术论坛由中国图象图形学学会主办,每年举办一届,邀请学术界和企业届的专家围绕SLAM技术的研究、发展以及产业化应用作技术分享。本文整理自浙江大学刘勇教授在第二届全国SL…...
西乡做网站公司/查域名注册详细信息查询
小目录链接题目描述样例输入样例输出思路代码链接 YbtOJ高效进阶 哈希-1 题目描述 如题,给定 N个字符串(字符串内包含数字、大小写英文字母),请求出 N个字符串中共有多少个不同的字符串。 样例输入 5 abc aaaa abc abcc 1234…...
简单网站建设公司/百度贴吧首页
原标题:谈谈学plc好还是数控好这两个的差别还是蛮大的虽说都是做编程的,一个是plc系统的编程,一个是CNN系统的。相比较而言plc学习掌握的东西比较多,强电、弱电以及最基本的电工基础是必须的,而数控则偏向于机械这方面…...
陇西学做网站/搜狗seo培训
由于昨天在一个大公司面试,被c#中的一个interface给难住了,所以回来以后我就找了这些资料看了一下,有了一点感觉。记录下来,方便以后使用。 c# interface定义:就是以前使用的类似于 API 的东西,别人告诉你一…...
做网站别名解析的目的是什么/西藏自治区seo 标题 关键词优化
作者介绍Scott Meyers,C顶级权威之一,为世界各地客户提供培训和咨询服务。出版有畅销的Effective C系列图书(《Effective C》、《More Effective C》和《Effective STL》),设计了创新型的Effective C CD,Ad…...