当前位置: 首页 > news >正文

第十五章 角色移动旋转实例

本章节我们创建一个“RoleDemoProject”工程,然后导入我们之前创建地形章节中的“TerrainDemo.unitypackage”资源包,这个场景很大,大家需要调整场景视角才能看清。

接下来,我们添加一个人物模型,操作方式就是将模型文件目录复制到“Assets”下

然后Unity会自动同步该文件,我们查看Project面板

在“Alita”目录下有两个文件:“Alita.fbx”和“alita_d.png”。前者是模型文件,后者是贴图文件。我们接下来要做的就是,将“Alita.fbx”模型文件拖拽到场景中。由于我们的场景太大了,可能无法方便的看到模型。我们这样操作,我们可以在Hierarchy层次面板中找到这个游戏对象(“Alita”),然后我们将鼠标“移动到(不要点击)”到场景视图中,然后按下“F”键就可以在场景视图中显示这个游戏对象了。

当然,我们最好再调整一下这个模型,然其站立到地面上。在移动模型的时候,注意保持模型轴心和本地坐标系的选择。如下所示

当我们切换轴心之后,我们发现模型身上的坐标系指示箭头移动到了模型脚底。一般情况下,人物模型的轴心就是在脚底(本地坐标系的原点)。如果我们是“Center”状态的话,坐标系指示箭头会在模型的中心位置。

我们能够看到模型的下半部分位于地形的下面,我们向上移动一下。

接下来,我们要做的是,让相机跟随模型一起移动和旋转。如果使用代码来完成的话,其原理就是模型如何移动和旋转,就同步调整相机如何移动和旋转。这里介绍一种更加简单的方式,就是将相机设置为模型的子游戏对象。操作非常简单,就是在Hierarchy层次面板中,拖动“Main Camera”到“Alita”上面即可。

拖拽后的样子

这样做的目的,就是“Alita”移动旋转的时候,子对象“Main Camera”自动移动旋转。当然,我们还需要进一步调整相机的位置,让其放置到“Alita”的后上方。首先,我们将相机的Position和Rotation数值清零,如下所示

 

请注意,此时的相机位于模型的脚下。在Unity中,子游戏对象的移动和旋转都是相对于父对象而言的。我们将相机的Position数值清零,并不是将相机放置到世界坐标系的原点,而是放置到了父对象“Alita”的原点。接下来,我们调整相机的位置,

 

我们将相机放置到人物模型的后上方,类似于第三人称视角。

接下来,我们保持相机选中状态,我们点击菜单栏“GameObject”->“Align View to Selected”

在之前的移动和旋转案例中,我们忽略了一个重要的特性:时间(Time.deltaTime)。游戏对象的移动有三个因素决定,一个方向,一个是速度,另一就是时间。其中方向和速度可以由向量表示(向量的长度代表速度,方向还是方向),而时间就是Time.deltaTime为什么时间是Time.deltaTime呢?因为游戏对象是在每一次update方法调用的时候才会进行移动,而两次移动之间的时间就是两个update方法调用的时间差,也就是我们的Time.deltaTime值。因此Translate方法里面第一个参数应该是方向*速度*时间

接下来,我们来控制角色的前后左右移动。我们创建一个“RoleController.cs”脚本文件,并且附加到“Alita”上面。我们目前使用WASD键来控制角色前后左右移动,代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RoleController : MonoBehaviour
{// 移动速度private float moveSpeed = 10.0f;// Update is called once per framevoid Update(){// 向前移动if (Input.GetKeyDown(KeyCode.W)){transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime, Space.Self);}// 向后移动if (Input.GetKeyDown(KeyCode.S)){transform.Translate(Vector3.back * moveSpeed * Time.deltaTime, Space.Self);}// 向左移动if (Input.GetKeyDown(KeyCode.A)){transform.Translate(Vector3.left * moveSpeed * Time.deltaTime, Space.Self);}// 向右移动if (Input.GetKeyDown(KeyCode.D)){transform.Translate(Vector3.right * moveSpeed * Time.deltaTime, Space.Self);}}
}

这里我们使用的是本地坐标系进行移动,大部分游戏开发中,也都是这么做的。

接下来,我们Play当前工程,查看运行后的Gif图

由于我们使用的是GetKeyDown方法,因此每按下一次键盘,才会移动一段距离。如果我们需要长按键盘进行移动的话,可以换成GetKey方法。当我们移动过程中,发现一个小问题,就是我们没有考虑地形的高度。也就是说,模型在移动过程中,可能会移动到地形之下或者地形之上。我们后续在解决这个问题。接下来,我们添加旋转的代码,如下所示。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RoleController : MonoBehaviour
{// 旋转速度private float rotationSpeed = 20.0f;// Update is called once per framevoid Update(){// 向左旋转if (Input.GetKeyDown(KeyCode.Q)){transform.Rotate(Vector3.down * rotationSpeed * Time.deltaTime, Space.Self);}// 向右旋转if (Input.GetKeyDown(KeyCode.E)){transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.Self);}}
}

上面我们忽略了移动的代码。为什么左右旋转使用的是Vector3.up和Vector3.down呢,不应该是Vector3.left和Vector3.right吗?很简单,我们所谓的左右旋转类似于“左右扭头”,它实际上就是围绕Y轴进行旋转的,所以是Vector3.up和Vector3.down上下方向的Y轴。接下来,我们Play当前工程,查看运行Gif效果图

接下来,我们来解决地形高度问题。我们需要借助一个“角色控制器”的组件。我们选中“Alita”,然后在Inspector检视面板中点击“Add Component”按钮。

 

在弹出的搜索框中输入“ch”,然后在下拉框中选中“Character Controller”角色控制器组件。

此时,在场景中的“Alita”会覆盖一个胶囊体的线框。

这个胶囊体的线框是用来做“碰撞检测”的,因此它最好能够“包裹”住我们的人物模型。当然,默认情况下,它基本上就能够自动“包裹”我们的人物模型。但是,有一个非常重要的注意点,就是胶囊体的线框不能“陷入”到地形的下面。因此,我们需要编辑胶囊体的线框,它的参数调节我们直接给出,大家可以自己修改其中某些值查看效果

 

接下来,我们还需要修改角色移动代码,如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RoleController : MonoBehaviour
{// 移动速度private float moveSpeed = 10.0f;// 旋转速度private float rotationSpeed = 100.0f;// 角色控制器组件private CharacterController cc;// Start is called before the first frame updatevoid Start(){// 获取角色控制器组件cc = GetComponent<CharacterController>();}// Update is called once per framevoid Update(){// 前后左右方向float v = Input.GetAxis("Vertical");float h = Input.GetAxis("Horizontal");Vector3 direction = new Vector3(h, 0, v);// 前后左右移动cc.SimpleMove(transform.TransformDirection(direction) * moveSpeed);// 向前移动if (Input.GetKeyDown(KeyCode.W)){//transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime, Space.Self);}// 向后移动if (Input.GetKeyDown(KeyCode.S)){//transform.Translate(Vector3.back * moveSpeed * Time.deltaTime, Space.Self);}// 向左移动if (Input.GetKeyDown(KeyCode.A)){//transform.Translate(Vector3.left * moveSpeed * Time.deltaTime, Space.Self);}// 向右移动if (Input.GetKeyDown(KeyCode.D)){//transform.Translate(Vector3.right * moveSpeed * Time.deltaTime, Space.Self);}// 向左旋转,替换GetKey方法if (Input.GetKey(KeyCode.Q)){transform.Rotate(Vector3.down * rotationSpeed * Time.deltaTime, Space.Self);}// 向右旋转,替换GetKey方法if (Input.GetKey(KeyCode.E)){transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.Self);}}
}

上面获取键盘输入的代码是:Input.GetAxis("Vertical/Horizontal") ,这个代码兼容WASD键的输入获取。然后使用CharacterController组件的SimpleMove方法进行移动。我们就不过多解释上面的代码了,直接Play运行查看Gif效果图吧。

 

相关文章:

第十五章 角色移动旋转实例

本章节我们创建一个“RoleDemoProject”工程&#xff0c;然后导入我们之前创建地形章节中的“TerrainDemo.unitypackage”资源包&#xff0c;这个场景很大&#xff0c;大家需要调整场景视角才能看清。 接下来&#xff0c;我们添加一个人物模型&#xff0c;操作方式就是将模型文…...

数据湖Data Lakehouse支持行级更改的策略:COW、MOR、Delete+Insert

COW:写时复制,MOR:读时合并,Delete+Insert:保证同一个主键下仅存在一条记录,将更新操作转换为Delete操作和Insert操作 COW和MOR的对比如下图,而Delete+Insert在StarRocks主键模型中用到。 目前COW、MOR在三大开源数据湖项目的使用情况,如下图。 写入时复制【Copy-On…...

双亲委派机制的原理和作用

双亲委派机制&#xff0c;就必须弄清楚Java的类加载器。 什么是类加载器 Java类加载器(ClassLoader)是Java运行时环境(JRE)的一部分&#xff0c;负责动态的将Java类加载到Java虚拟机的内存空间。 类加载器有哪些 主要有三个&#xff1a; 引导类加载器(Bootstrap ClassLoade…...

mac免费杀毒软件哪个好用?如何清理mac系统需要垃圾

CleanMyMac x是一款功能强大的Mac系统优化清理工具&#xff0c;使用旨在帮助用户更加方便的清理您系统中的所有垃圾&#xff0c;从而加快电脑运行速度&#xff0c;保持最佳性能&#xff0c;更加稳定、流畅、快速&#xff01;&#xff01;&#xff01; CleanMyMac X无疑是目前m…...

css 实现太极效果

目录 一、简述二、太极效果制作 一、简述 本次主要介绍::after&#xff0c;::before&#xff0c;box-shadow这三个属性。 ::after&#xff0c;::before这两个是伪类选择器&#xff0c;box-shaow是用来设置元素的阴影效果 before:向选定的元素前插入内容 after:向选定的元素后插…...

【前端基础知识】Vue中的变量不是响应式的吗?属性赋值后视图不变化的原因是什么?

目录 &#x1f914;问题&#x1f4dd;回答&#x1f3a8;使用场景动态添加属性动态添加数组元素 ❌注意事项$set只能在响应式对象上使用$set不能用于根级别的属性$set的性能问题 &#x1f4c4;总结 &#x1f914;问题 Vue是一款在国内非常流行的框架&#xff0c;采用MVVM架构&a…...

如何完全卸载linux下通过rpm安装的mysql

卸载linux下通过rpm安装的mysql 1.关闭MySQL服务2.使用 rpm 命令的方式查看已安装的mysql3. 使用rpm -ev 命令移除安装4. 查询是否还存在遗漏文件5. 删除MySQL数据库内容 1.关闭MySQL服务 如果之前安装过并已经启动&#xff0c;则需要卸载前请先关闭MySQL服务 systemctl stop…...

[渗透教程]-004-长城防火墙GFW的原理

文章目录 1. baidu.com 请求过程2. GFW原理2.1 GFW拦截方法1:DNS渲染2.2 通过IP黑名单2.3 VPN阻断1. baidu.com 请求过程 家庭的路由器具备了交换机的功能.域名–>ip,优先检测本地的缓存,没有的话就查找DNS服务器,传输层对应该层的数据进行封装增加了端口的信息,网络层对传输…...

LaTeX基础文本排版命令

LaTeX基础文本排版命令 1. 字体大小2. 字体的粗体与斜体2.1. 粗体2.2 斜体2.3 同时启用粗体和斜体 3. 空格长度4. 高度与宽度尺寸 在LaTeX中&#xff0c;文本排版可以通过简单的命令实现&#xff0c;这些命令可以控制字体大小、粗体与斜体、空格、行高和宽度等方面&#xff0c;…...

PLC模糊控制模糊PID(梯形图实现+算法分析)

博途PLC的模糊PID控制详细内容请查看下面的博客文章: Matlab仿真+博途PLC模糊PID控制完整SCL源代码参考(带模糊和普通PID切换功能)_博途怎么实现模糊pid_RXXW_Dor的博客-CSDN博客模糊PID的其它相关数学基础,理论知识大家可以参看专栏的其它文章,这里不再赘述,本文就双容…...

线程池在Java多线程中的应用

前言 随着计算机硬件和软件技术的不断发展&#xff0c;多线程编程在软件开发中变得越来越常见。然而&#xff0c;使用多线程编程时必须小心谨慎&#xff0c;以确保正确性和可维护性。在这个过程中&#xff0c;线程池成为了一个至关重要的工具。本文将介绍其应用场景、注意事项…...

1997-2021年全国30省技术市场成交额(亿元)

1997-2021年全国30省技术市场成交额 1、时间&#xff1a;1997-2021年 2、范围&#xff1a;30省不含西藏 3、来源&#xff1a;国家统计J 4、指标&#xff1a;技术市场成交额 5、缺失情况说明&#xff1a;无缺失 6、指标解释及用途&#xff1a; 技术市场成交额是一个客观、…...

【C++】面向对象之多态

文章内的所有调试都是在vs2022下进行的&#xff0c; 部分小细节可能因编译器不同存在差异。 文章目录 多态的定义和实现概念引入多态的构成条件虚函数重写通过基类的指针或者引用调用虚函数 override和final 抽象类概念实现继承和接口继承 虚函数表单继承中的虚表打印虚表多继…...

卡尔曼滤波器简介——多维卡尔曼滤波

原文&#xff1a;多维卡尔曼滤波 (kalmanfilter.net) 目录 前言 基本背景 状态外推方程 示例 - 飞机 - 无控制输入 示例 - 带控制输入的飞机 示例 – 坠落物体 状态外推方程维度 线性时不变系统 线性动态系统建模 状态外推方程的推导 状态空间表示形式 示例 - 等速…...

如何用 GPT-4 帮你写游戏?

你知道的&#xff0c;GPT-4 发布了。 目前你想要用上 GPT-4&#xff0c;主要的渠道是 ChatGPT Plus 。作为交了订阅费的用户&#xff0c;你可以在对话的时候选择模型来使用。 另一种渠道&#xff0c;就是申请官方 API 的排队。我在申请 New Bing Chat 的时候&#xff0c;耐心被…...

R语言的贝叶斯时空数据模型实践技术应用

时间&#xff0d;空间数据&#xff08;以下简称“时空数据”&#xff09;是最重要的观测数据形式之一&#xff0c;很多科学研究的数据都以时空数据的形式得以呈现&#xff0c;而科学研究目的可以归结为挖掘时空数据中的规律。另一方面&#xff0c;贝叶斯统计学作为与传统统计学…...

Lazysysadmin靶机渗透过程

准备工作 下载好靶机到本地后 VMware导入OVA 启动靶机 扫描信息 首先扫描整个C段发现主机 进一步扫描端口 从扫描结果可知&#xff1a; Samba服务MySQLSSH端口网站端口 先对网站进行目录遍历 发现有wordpress网站和phpmyadmin管理系统 出现了非常多遍My name is togie.可能…...

为什么网络安全缺口很大,招聘却很少?

2020年我国网络空间安全人才数量缺口超过了140万&#xff0c;就业人数却只有10多万&#xff0c;缺口高达了93%。这里就有人会问了&#xff1a; 1、网络安全行业为什么这么缺人&#xff1f; 2、明明人才那么稀缺&#xff0c;为什么招聘时招安全的人员却没有那么多呢&#xff1…...

SpringBoot手册

目录 依赖管理关于各种的 start 依赖关于自动配置关于约定大于配置中的配置SpringBoot 整合 SpringMVC定制化 SpringMVC静态资源处理对上传文件的处理对异常的处理Web原生组件注入&#xff08;Servlet、Filter、Listener&#xff09;Interceptor 自定义拦截器DispatcherServlet…...

【Linux】如何实现单机版QQ,来看进程间通信之管道

学会了管道&#xff0c;就可以实现简单的qq哦~ 文章目录 前言一、匿名管道总结 前言 为什么要进行进程间通信呢&#xff1f;因为需要以下这些事&#xff1a; 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 …...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

npm安装electron下载太慢,导致报错

npm安装electron下载太慢&#xff0c;导致报错 背景 想学习electron框架做个桌面应用&#xff0c;卡在了安装依赖&#xff08;无语了&#xff09;。。。一开始以为node版本或者npm版本太低问题&#xff0c;调整版本后还是报错。偶尔执行install命令后&#xff0c;可以开始下载…...