文章目录

  • 一,什么是FPS游戏
  • 二,功能实现思路与过程
    • (1)新建角色
    • (2)实现移动功能的思路
    • (3)实现旋转功能的思路
    • (4)实现推进上升功能的思路
    • (5)具体代码
    • (5)脚本的使用方法
    • (6)最终效果

一,什么是FPS游戏

第一人称射击类游戏,FPS(First-person shooting game), 严格来说第一人称射击游戏属于ACT类游戏的一个分支,但和RTS类游戏一样,由于其在世界上的迅速风靡,使之发展成了一个单独的类型。
FPS(First-person Shooting game)第一人称视角射击游戏顾名思义就是以玩家的主观视角来进行射击游戏。玩家们不再像别的游戏一样操纵屏幕中的虚拟人物来进行游戏,而是身临其境的体验游戏带来的视觉冲击,这就大大增强了游戏的主动性和真实感。早期第一人称类游戏所带给玩家的一般都是的屏幕光线的刺激,简单快捷的游戏节奏。随着游戏硬件的逐步完善,以及各种游戏的不断结合。第一人称射击类游戏提供了更加丰富的剧情以及精美的画面和生动的音效。

二,功能实现思路与过程

(1)新建角色

新建项目,载入或者新建角色模型与枪械模型,另外,由于项目视角是第一人称,所以建议将枪械设为摄像头的子物体,并为了以后的对战功能的开发,同样建议将完成之后的角色模型集合以预制体的方式保存,完成之后的效果图如下

(2)实现移动功能的思路

要实现键盘输入控制移动功能,首先必须对键盘的输入进行实时获取,获取的方法,是在脚本的Update()中进行获取(PS:Update(): 当游戏正在运行,同时脚本是可用的,这个方法会在每帧刷新时调用),获取用户的输入,得到用户移动矢量的模(移动矢量的模即移动距离)。

/**获取用户移动矢量的模的代码如下**/
float _xMov = Input.GetAxisRaw("Horizontal");//获取水平方向输入
float _zMov = Input.GetAxisRaw("Vertical");//获取垂直方向输入

再乘以用户移动矢量的标准矢量(PS:transform.right,transform.forward本质为标准矢量,且根据矢量的概念,一个非零矢量除以它的模,可得所需标准矢量。从而反推移动矢量的标准矢量乘以移动矢量的模可得出移动矢量),获取移动矢量,考虑到玩家的移动受垂直与水平两个移动矢量的影响,玩家运动的简易模型如下图

根据矢量三角形法则可知,玩家移动矢量等于水平矢量+垂直矢量(法则简略图如下)

  /**水平矢量,垂直矢量与玩家移动矢量的计算代码如下**/
Vector3 _moveHoruzontal = transform.right * _xMov;//水平移动矢量=水平方向标准矢量*水平方向移动矢量的模(键盘水平方向输入)
Vector3 _moveVertical = transform.forward * _zMov;//垂直移动矢量=垂直方向标准矢量*垂直方向移动矢量的模(键盘垂直方向输入)
Vector3 _velocity = (_moveHoruzontal + _moveVertical).normalized * speed;//将玩家移动矢量归一化为标准矢量,在乘以

然后将玩家移动矢量归一化(normalized)为标准矢量,在将归一化的标准矢量乘以速度矢量的模,获取玩家速度矢量,最后将速度矢量乘以时间加上当前玩家刚体的位置,得出玩家最后应该移动到的位置。

(3)实现旋转功能的思路

同理在脚本的Update()中进行获取用户的鼠标输入,将获取的鼠标X,Y轴移动角度乘以用户视野旋转速度,得到摄像头与玩家刚体旋转角度

(4)实现推进上升功能的思路

同理在脚本的Update()中进行获取用户的键盘输入,当监听到用户输入空格的时候,让角色刚体像正上方移动。

(5)具体代码

PlayerMoter.cs(代码如下)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerMoter : MonoBehaviour
{[SerializeField]private Camera cam;//摄像头private Vector3 velocity = Vector3.zero;private Vector3 rotation = Vector3.zero;private float cameraRotationX = 0f;private float currentCamerRotationX = 0f;private Vector3 thrusterForce = Vector3.zero;[SerializeField]private float cameraRotationLimit = 85f;private Rigidbody rb;void Start(){rb = GetComponent<Rigidbody>();//获取刚体}public void Move(Vector3 _velocity)//移动{velocity = _velocity;}public void Rotate(Vector3 _rotation)//旋转{rotation = _rotation;}// Update is called once per framevoid Update(){}private void FixedUpdate(){PerformMovement();PeformRotation();}public void RotarCamera(float _cameraRotation)//摄像头旋转{cameraRotationX = _cameraRotation;}public void ApplyThruster(Vector3 _thrusterForce)//应用推进力{thrusterForce = _thrusterForce;}void PerformMovement()//移动{if(velocity!=Vector3.zero){rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);//}if(thrusterForce!=Vector3.zero){rb.AddForce(thrusterForce * Time.fixedDeltaTime,ForceMode.Acceleration);}}void PeformRotation()//旋转{rb.MoveRotation(rb.rotation * Quaternion.Euler(rotation));if(cam!=null){currentCamerRotationX -= cameraRotationX;currentCamerRotationX = Mathf.Clamp(currentCamerRotationX,-cameraRotationLimit,cameraRotationLimit);cam.transform.localEulerAngles = new Vector3(currentCamerRotationX, 0f, 0f);}}
}

PlayerControl.cs(代码如下)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(ConfigurableJoint))]
[RequireComponent(typeof(PlayerMoter))]
public class PlayerControl : MonoBehaviour
{[SerializeField]private float speed = 5f;private PlayerMoter moter;[SerializeField]private float lookSensitivity = 3f;//视角旋转速度[SerializeField]private float thrustserForce = 1000f;//推进速度[Header("Spring setting")][SerializeField]private JointDriveMode jointMode=JointDriveMode.Position;[SerializeField]private float jointSpring = 20f;[SerializeField]private float jointMaxForce = 40f;private PlayerMoter motor;private ConfigurableJoint joint;// Start is called before the first frame updatevoid Start(){moter = GetComponent<PlayerMoter>();joint = GetComponent<ConfigurableJoint>();}// Update is called once per framevoid Update(){float _xMov = Input.GetAxisRaw("Horizontal");//获取水平方向输入float _zMov = Input.GetAxisRaw("Vertical");//获取垂直方向输入//transform.right,transform.forward本质为标准矢量,即有方向且模为1的矢量Vector3 _moveHoruzontal = transform.right * _xMov;//水平移动矢量=水平方向标准矢量*水平方向移动矢量的模(键盘水平方向输入)Vector3 _moveVertical = transform.forward * _zMov;//垂直移动矢量=垂直方向标准矢量*垂直方向移动矢量的模(键盘垂直方向输入)Vector3 _velocity = (_moveHoruzontal + _moveVertical).normalized * speed;//将玩家移动矢量归一化为标准矢量,在乘以moter.Move(_velocity);float _yRot = Input.GetAxisRaw("Mouse X");//获取鼠标X轴移动Vector3 _rotation = new Vector3(0f, _yRot, 0f) * lookSensitivity;moter.Rotate(_rotation);float _xRot = Input.GetAxis("Mouse Y");//获取鼠标Y轴移动float _cameraRotation = _xRot * lookSensitivity;moter.RotarCamera(_cameraRotation);Vector3 _thrusterForce = Vector3.zero;if(Input.GetButton("Jump")){_thrusterForce = Vector3.up * thrustserForce;//SetJointSettings(0f);}else{SetJointSettings(jointSpring);}moter.ApplyThruster(_thrusterForce);}private void SetJointSettings(float _jointSpring){joint.yDrive = new JointDrive {mode = jointMode,positionSpring= _jointSpring,maximumForce=jointMaxForce};}
}

PlayerScript.cs(代码如下)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerScript : MonoBehaviour
{private const int Player_Up = 0;private const int Player_Right = 1;private const int Player_Down = 2;private const int Player_Left = 3;private int state = 0;public int moveSpeed = 2;void Awake(){state = Player_Up;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){float KeyVertical = Input.GetAxis("Vertical");float KeyHorizontal = Input.GetAxis("Horizontal");if(KeyVertical==-1){setPlayerState(Player_Down);}else if(KeyVertical==1){setPlayerState(Player_Up);}if(KeyHorizontal==1){setPlayerState(Player_Right);}else if(KeyHorizontal==-1){setPlayerState(Player_Left);}}void setPlayerState(int NewState){int rotateValue = (NewState - state) * 90;Vector3 transformValue = new Vector3();switch(NewState){case Player_Up:transformValue = Vector3.forward * Time.deltaTime;break;case Player_Down:transformValue = (-Vector3.forward) * Time.deltaTime;break;case Player_Left:transformValue = Vector3.left * Time.deltaTime;break;case Player_Right:transformValue = (-Vector3.left) * Time.deltaTime;break;}transform.Rotate(Vector3.up, rotateValue);transform.Translate(transformValue * moveSpeed, Space.World);state = NewState;}
}

(5)脚本的使用方法

将PlayerScript.cs与PlayerControl.cs绑定在玩家角色对象上,并给PlayerControl脚本绑定摄像头(如下图)

(6)最终效果


【1】参考教程 https://www.bilibili.com/video/BV1Hz4y1R7ZY

[Unity学习笔记:FPS游戏制作(1)]角色的移动,旋转与推进上升————(2021.6.13学习笔记)相关推荐

  1. [Unity学习笔记:FPS游戏制作(2)] 发射子弹————(2021.6.20学习笔记)

    往期博客 [Unity学习笔记:FPS游戏制作(1)]角色的移动,旋转与推进上升----(2021.6.13学习笔记) 文章目录 一,实现思路 二,实现代码 三,脚本的使用方法 四,最终效果 一,实现 ...

  2. [Unity学习笔记:FPS游戏制作(3)]子弹拖尾,碰撞与枪口火焰效果

    往期博客[Unity学习笔记:FPS游戏制作(2)] 发射子弹----(2021.6.20学习笔记) 文章目录 一,实现思路 二,粒子效果的实现 (1)子弹拖尾特效的实现 (2)枪口火焰特效的实现 ( ...

  3. 【Unity】U3D TD游戏制作实例(一)创建敌人、加载预制件

    文章目录 前言 本章实现效果 场景和敌人 文件目录结构 场景层次结构(Hierarchy) 处理模型 指定GameScript脚本 运行游戏 前言 TD(炮台防守)类游戏是比较经典的游戏类型,当年在 ...

  4. 【笔记】游戏制作技巧——3

    自动瞄准机制 准星辅助 准星接近的时候自动瞄准 或者是接近后进行标记 标记后一定时间范围内自动追踪 通过显示一部分的身体动作特征来表达动作 更加准确直观 如跑步时枪支的晃动幅度 滑动时镜头中出现脚 要 ...

  5. 笔记-【游戏制作教程】30分钟制作一款游戏 (1)【Unity】

    本文只记录重要知识点以及涉及到的脚本 API,详细教学过程:视频链接 . 本文中大量关于 API 的描述来自 Unity 官方文档 . 另:学完之后发现这个教程非常非常像这个 Unity 官方教程 . ...

  6. 【Unity】U3D TD游戏制作实例(三)相机管理器、生成敌人优化、敌人血槽小组件

    文章目录 相机管理器 调整相机 敌人类优化 融合导航测试代码 敌人移动速度 销毁对象 加载敌人配置 敌人生成方式优化 血槽组件 相机管理器 调整相机 首先将主相机调整为正交镜头,这样可以防止模型畸变. ...

  7. 【unity】快速了解游戏制作流程-制作九宫格简单游戏demo

    前言 hi~大家好呀!欢迎来到我的unity学习笔记系列~,本篇我会简单的记录一下游戏流程并且简单上手一个通过九宫格移动到指定位置的小游戏,话不多说,我们直接开始吧~ 本篇源自我看B站一位up主的视频 ...

  8. 【Unity】U3D TD游戏制作实例(四)建造防御塔:防御塔生成器、一个int代表多选框,圆上任意点位的坐标计算、制作防御塔预制件

    文章目录 本章内容介绍 制作生成器 生成器Hierarchy 高亮显示生成器 制作箭塔菜单 将创建菜单对齐到选中的生成器 动态生成按钮 动态计算按钮坐标 制作预制件 最终运行效果 本章内容介绍 由于目 ...

  9. 2021/12/13 学习笔记:外部表不是预期的格式

    终于把所有的数据都按城市和季节处理完了,老师提出了新的想法: 把所有结果合并起来展示一下吧!(内心os:emm所以我为什么要按城市和季节处理呢?) 不过老师肯定有他的考虑,而且非常细心的给我提供了教程 ...

最新文章

  1. pytorch model.train() 开启batchnormalize 和 dropout model.eval() 则会关闭dropout
  2. 一步一步 Mac OS X 与 Windows 7 双系统共存 的“黑苹果” 电脑 安装 入门
  3. 基于RDP开源许可rdesktop基本介绍
  4. Python的random
  5. PHP PDO 预处理语句与存储过程
  6. 为什么越来越多的开发者选择使用Spring Boot
  7. 互联网商业模式:增值还是减值?
  8. unity现代人物含代码动画_Unity Animation--动画系统概述
  9. 如何在生产环境排查 Rust 内存占用过高问题
  10. 博信医药系统连接不到服务器,博信医药管理系统
  11. val什么意思vb中的属性值_VB语言中的val()函数是什么意思?如何使用?
  12. C语言 常量和宏定义
  13. P2员工月度工作P160-P163
  14. Win10在线升级Win11(绕过TPM2.0)
  15. MAIGO的同济题解2
  16. python insertLink 链表前中后插入
  17. devexpress gridview代码设置
  18. IDEA中使用Git Reset进行回退
  19. VS2013 + Qt 配置指南
  20. Python | 使用 Python 分析《我不是药神》豆瓣电影短评

热门文章

  1. PHP_保留两位小数并且四舍五入_保留两位小数并且不四舍五入
  2. C++ day24 继承(四)抽象基类,纯虚函数,protected
  3. 数字图像处理:(2)一阶微分和二阶微分在数字图像处理中的应用
  4. 加州理工学院宋飏老师招收机器学习全奖博士生|2023秋季
  5. 入职快手半年工作小结
  6. Android Studio 4.1.2 自定义 APP 启动图标样式步骤【APP开发之入门四】
  7. 【CS231n】五、卷积神经网络简介CNN学习笔记_一只神秘的大金毛_新浪博客
  8. 苹果6换android系统更新不了,iPhone6的手机系统是什么?iPhone6能升级安卓4.4吗?...
  9. 阿拉伯数字和中文大写形式的相互转换
  10. android 编辑说说页面,QQ说说已经发表了怎么修改?