当前位置:网站首页>第一人称视角的角色移动
第一人称视角的角色移动
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);
}
}
四、完成效果
边栏推荐
- (5) Introduction to R language bioinformatics -- ORF and sequence analysis
- 编译原理:源程序的预处理及词法分析程序的设计与实现(含代码)
- Talking about the startup of Oracle Database
- Database table splitting strategy
- Who says that PT online schema change does not lock the table, or deadlock
- Fairygui character status Popup
- Theoretical derivation of support vector machine
- idea中导包方法
- FairyGUI人物状态弹窗
- 2021.11.10汇编考试
猜你喜欢
单片机蓝牙无线烧录
Database course design: college educational administration management system (including code)
[Clickhouse kernel principle graphic explanation] about the collaborative work of partitioning, indexing, marking and compressed data
CUDA C programming authoritative guide Grossman Chapter 4 global memory
(三)R语言的生物信息学入门——Function, data.frame, 简单DNA读取与分析
Force buckle 1189 Maximum number of "balloons"
FairyGUI复选框与进度条的组合使用
JS regular expression basic knowledge learning
Page performance optimization of video scene
Learning notes of JS variable scope and function
随机推荐
Unity3D制作注册登录界面,并实现场景跳转
基于Redis的分布式ID生成器
(课设第一套)1-4 消息传递接口 (100 分)(模拟:线程)
(课设第一套)1-5 317号子任务 (100 分)(Dijkstra:重边自环)
[offer9]用两个栈实现队列
Database course design: college educational administration management system (including code)
Who says that PT online schema change does not lock the table, or deadlock
[leetcode15] sum of three numbers
Detailed explanation of truncate usage
(the first set of course design) sub task 1-5 317 (100 points) (dijkstra: heavy edge self loop)
Redis cache update strategy, cache penetration, avalanche, breakdown problems
SVN更新后不出现红色感叹号
FairyGUI摇杆
[899]有序队列
PR 2021 quick start tutorial, first understanding the Premiere Pro working interface
MySQL时间、时区、自动填充0的问题
[leetcode19]删除链表中倒数第n个结点
FairyGUI按钮动效的混用
Acwing-116 pilot brother
Pytorch: tensor operation (I) contiguous