当前位置:网站首页>第一人称视角的角色移动
第一人称视角的角色移动
2022-07-06 09:18:00 【SQ刘】
第一人称视角的角色移动
一、素材下载
1、在资源商店中,搜索名字进行下载:Low-Poly Simple Nature Pack。
2、下载完毕后,直接全部导入。
二、场景部署
1、打开Demo场景,用Demo场景来做练习。
2、右击新建一个空物体,重命名为Environment。
3、将除了相机外的所有对象选中,拖入Environment中,方便管理,将它折叠起来。
4、新建一个胶囊体,重命名为Player。用它来当我们控制的角色。
5、重置Transform位置。
6、稍微调整一下Player位置,不让它卡在地里。再将Cameras移到Player中,作为子对象。重置一下Cameras的Transform。
7、场景部署完毕,接下来就是敲代码时间。
三、敲定代码
(一)为Camaras添加脚本
1、新建文件夹,重命名Scripts,存放脚本。
2、新建CameraController脚本,控制相机。将CameraController脚本拖拽到Cameras中。
3、双击打开脚本。
(1)先定义两个float类型的变量,来获得鼠标移动的值。
private float mouseX, mouseY; //获取鼠标移动的值
(2)可以给鼠标增加一个灵敏度,用来控制鼠标移动的速度。
public float mouseSensitivity; //鼠标灵敏度
(3)在Update方法中,使用输入系统中的GetAxis方法来获取鼠标移动的值,乘以鼠标灵敏度,再乘以Time.deltaTime。鼠标左右移动的值就这样得到了。
private void Update()
{
mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
}
(4)通过控制Player的旋转的方法,来控制相机视角左右移动,所以需要一个Player的Transform。
public Transform player;
(5)回到Update方法中,使用Transform的Rotate()方法来旋转Player。这个方法有6个重构,我们只需要在里面填入一个Vector3的值就可以了。我们需要控制Player的Y轴旋转,才能让它左右旋转。
player.Rotate(Vector3.up * mouseX);
(6)接下来我们要旋转相机了,使用transform.localRotation的方法,让相机上下旋转。使用localRotation就可以不被父对象的旋转影响。因为localRotation是属性,所以我们还要给它赋值。让它等于Quaternion.Euler,Euler方法中需要传入三个值,这里填入-mouseY,0,0。
transform.localRotation = Quaternion.Euler(-mouseY, 0, 0);
(7)回到Unity3D中,将需要设置的值设置上。
(8)运行时发现了一个问题,在鼠标上下移动的时候,视角一卡一卡的,并且移不动。问题出现在哪里呢?问题就在:Y轴的GetAxis方法,会返回-1到1之间的浮点数,在鼠标移动的时候,数值会随着方向的变化而变化,在鼠标不动时,数值会回弹到0。所以我们就会看见刚才那样的问题。我们只需要声明一个float变量来累加mouseY就可以了。
public float xRotation;
(9)在Update中写上:xRotation -= mouseY;,然后再把下面的-mouseY改为xRotation 。
(10)再回到Unity3D运行一下,会发现:玩家会无限制的上下旋转视角。有时候,我们需要做出一点限制,不至于让玩家呈现一种诡异的状态,再次回到代码中来。我们需要将xRotation的值限制在一个范围内,所以我们可以使用数学函数Mathf.Clamp()来限制,Clamp方法内需要填入三个值:第一个是需要限制的变量,第二个是限制的最小值,第三个是限制的最大值。
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -70f, 70f);
(11)最终CameraController 脚本代码如下。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform player;
private float mouseX, mouseY; //获取鼠标移动的值
public float mouseSensitivity; //鼠标灵敏度
public float xRotation;
private void Update()
{
mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -70f, 70f);
player.Rotate(Vector3.up * mouseX);
transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
}
}
(二)为Player添加脚本
1、新建PlayerController脚本,用来控制玩家的行动。
2、将PlayerController添加进Player对象中;删除胶囊控制器;添加角色控制器,它自带碰撞体和刚体。
3、双击打开代码。
(1)首先需要获得Player的CharacterController组件。
private CharacterController cc;
(2)定义Player的移动速度和跳跃速度。
public float moveSpeed;
public float jumpSpeed;
(3)定义获得按键值的两个变量。
private float horizontalMove, verticalMove;
(4)定义三维变量dir控制方向。
private Vector3 dir;
(5)在Start()函数中使用GetComponent方法获得CharacterController。
cc = GetComponent<CharacterController>();
(6)在Update中一样使用Input.GetAxis()方法获得按键的值。dir存储移动的方向。接下来使用CharacterController中的Move()方法来移动Player。
horizontalMove = Input.GetAxis("Horizontal") * moveSpeed;
verticalMove = Input.GetAxis("Vertical") * moveSpeed;
dir = transform.forward * verticalMove + transform.right * horizontalMove;
cc.Move(dir * Time.deltaTime);
(7)回到Unity3D,将刚才定义的变量赋值。
(8)点击运行,现在可以移动了。将Player移到空中,它没有往下掉,很明显缺少重力,CharacterController是不带物体引擎的,所以我们要手动给它写个重力。
(9)回到代码中,定义两个变量,一个是重力,一个是速度。
public float gravity;
private Vector3 velocity; //用来控制Y轴加速度
(10)在Update中,velocity.y -= gravity * Time.deltaTime;,这样每秒它就会减去重力的值不断下降。再用Move()方法来移动Y轴。
velocity.y -= gravity * Time.deltaTime; //每秒它就会减去重力的值不断下降
cc.Move(velocity * Time.deltaTime);
(11)回到Unity3D中,将Player的位置提高,点击运行查看效果。发现了一个问题:刚开始可以顺畅的掉落,过一会就会一卡一卡的提不起来呢?我们鼠标放在Inspector视图的文字上,右键Debug。
在下面,我们可以看到刚才定义的velocity的y值正在不断减小,这就是问题所在。想要让它在落地后不再减小,我们需要回到代码中来。(重力手动设置为9.8)
(12)我们只需要检测Player是否在地上就可以了,这里可以使用Physics中的CheckSphere()方法。该方法的描述是:如果定义的球体和物体发生碰撞,返回真。所以为了使用这个方法,我们需要定义几个变量。
public Transform groundCheck; //检测点的中心位置
public float checkRadius; //检测点的半径
public LayerMask groundLayer; //检测的图层
public bool isGround; //布尔值来存储Physics.CheckSphere的返回值
回到Update方法中,在最前面写代码:
isGround = Physics.CheckSphere(groundCheck.position, checkRadius, groundLayer);
if (isGround && velocity.y < 0)
{
velocity.y = -3f; //小于0旁边的数都行
}
(13)回到Unity3D,对刚刚设置的变量进行赋值。
在Player下面新建一个空对象,重命名为GroundCheck
再将它的位置拖到Player底部的位置,底部位置检测到它是否接触到地面
再将GroundCheck拖入,设置半径0.4
还有Ground Layer,可以点击右上角的Layer层,Add Layer…,自己添加一个Ground层就可以了。将Ground Layer修改为Ground。
(14)将Environment的Layer层改为Ground,然后会弹出一个对话框,直接点Yes,change children,它的子对象就会应用上Ground Layer。
(15)运行,自由落体得到了解决。现在还剩下跳跃功能没有实现。
(16)回到代码中。我们需要获取到跳跃按键的事件,所以我们使用Input系统中的GetButtonDown()方法,它会返回一个布尔值,当按下(按键)时才会返回真,其中的值Jump也可以在InputManager中查看。当按下跳跃键时,将velocity.y = jumpSpeed,这样就会在一瞬间有个向上的速度,在过程中也会随着重力慢慢下降。
if (Input.GetButtonDown("Jump") && isGround)
{
velocity.y = jumpSpeed;
}
(17)最终PlayerController脚本代码如下。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private CharacterController cc;
public float moveSpeed;
public float jumpSpeed;
private float horizontalMove, verticalMove;
private Vector3 dir;
public float gravity;
private Vector3 velocity; //用来控制Y轴加速度
public Transform groundCheck; //检测点的中心位置
public float checkRadius; //检测点的半径
public LayerMask groundLayer; //检测的图层
public bool isGround; //布尔值来存储Physics.CheckSphere的返回值
private void Start()
{
cc = GetComponent<CharacterController>();
}
private void Update()
{
isGround = Physics.CheckSphere(groundCheck.position, checkRadius, groundLayer);
if (isGround && velocity.y < 0)
{
velocity.y = -3f; //小于0旁边的数都行
}
horizontalMove = Input.GetAxis("Horizontal") * moveSpeed;
verticalMove = Input.GetAxis("Vertical") * moveSpeed;
dir = transform.forward * verticalMove + transform.right * horizontalMove;
cc.Move(dir * Time.deltaTime);
if (Input.GetButtonDown("Jump") && isGround)
{
velocity.y = jumpSpeed;
}
velocity.y -= gravity * Time.deltaTime; //每秒它就会减去重力的值不断下降
cc.Move(velocity * Time.deltaTime);
}
}
四、完成效果
边栏推荐
- [offer9]用两个栈实现队列
- [Leetcode15]三数之和
- Fairygui joystick
- idea中好用的快捷键
- What is the maximum length of MySQL varchar field
- [leetcode19]删除链表中倒数第n个结点
- (5) Introduction to R language bioinformatics -- ORF and sequence analysis
- Mysql database index
- MySQL error warning: a long semaphore wait
- Force buckle 1189 Maximum number of "balloons"
猜你喜欢
Esp8266 connect onenet (old mqtt mode)
The dolphin scheduler remotely executes shell scripts through the expect command
[Nodejs] 20. Koa2 onion ring model ----- code demonstration
JS variable types and common type conversions
Remember an experience of ECS being blown up by passwords - closing a small black house, changing passwords, and changing ports
MySQL占用内存过大解决方案
Idea problem record
Postman 中级使用教程【环境变量、测试脚本、断言、接口文档等】
(五)R语言入门生物信息学——ORF和序列分析
NRF24L01 troubleshooting
随机推荐
2021.11.10 compilation examination
Intermediate use tutorial of postman [environment variables, test scripts, assertions, interface documents, etc.]
Unity3d, Alibaba cloud server, platform configuration
[leetcode15] sum of three numbers
[offer78]合并多个有序链表
JS regular expression basic knowledge learning
MySQL time, time zone, auto fill 0
Latex learning
PT OSC deadlock analysis
(the first set of course design) 1-4 message passing interface (100 points) (simulation: thread)
Basic operations of databases and tables ----- modifying data tables
Servlet
单片机蓝牙无线烧录
数据库课程设计:高校教务管理系统(含代码)
[leetcode19]删除链表中倒数第n个结点
[offer29] sorted circular linked list
Fairygui character status Popup
Redis based distributed ID generator
NRF24L01故障排查
Derivation of logistic regression theory