如图所示,创建一个胶囊体,将其放在一个空物体下,去除胶囊体的Collider。将Camera也放在空物体下。在空物体下加上一个capsule colliderr,同时给空物体加上rigibody,freeze其x和轴的旋转。
创建脚本 FPSMouseLook,将其挂在相机上,代码内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSMouseLook : MonoBehaviour
{
//控制人物视野的脚本,挂在摄像机上
public Transform characterTransform;//人物的Transform组件
public float mouseSensitivity;
public float maxX;
public float minX;
private Vector3 cameraRotation;
void Update()
{
float mouseX = Input.GetAxis("Mouse X");
float mouseY = Input.GetAxis("Mouse Y");
cameraRotation.y += mouseX*mouseSensitivity;
cameraRotation.x -= mouseY*mouseSensitivity;
cameraRotation.x = Mathf.Clamp(cameraRotation.x, minX, maxX); //限制角色上下视野范围
transform.rotation = Quaternion.Euler(cameraRotation.x, cameraRotation.y, 0);
characterTransform.rotation = Quaternion.Euler(0, cameraRotation.y, 0);//控制角色的朝向
}
}
创建脚本FPSMove,将其挂在那个空物体下,内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSMove : MonoBehaviour
{
//控制人物视野的脚本,挂在人物上
Rigidbody characterRigidbody;
public float speed;
void Start()
{
characterRigidbody = gameObject.GetComponent<Rigidbody>();
}
void FixedUpdate()//FixedUpdate是在固定的时间间隔执行,不受游戏帧率的影响
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 currentDirection = new Vector3(h, 0, v); //当前输入所产生的方向
currentDirection = transform.TransformDirection(currentDirection);//将此方向转换为世界方向
currentDirection *= speed;//转换为速度
Vector3 currentVelocity = characterRigidbody.velocity;//获取当前的人物速度
Vector3 velocityChange = currentDirection - currentVelocity;//获得速度变化
velocityChange.y = 0;//Y轴方向速度不需要变化
characterRigidbody.AddForce(velocityChange, ForceMode.VelocityChange);//根据速度的变化添加力来控制移动
}
}
完成!进入游戏试试吧!
拓展:
利用rigibody实现移动还是有很多bug的,比如抖动就无法避免,为此我们可以给游戏物体添加一个CharacterController,并且使用以下脚本控制移动。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSCharacterMove : MonoBehaviour
{
private CharacterController characterController;
private Vector3 moveDirection;
public float walkSpeed;
public float runSpeed;
public float crouchSpeed;
public float jumpHeight;
public float gravity;
public bool isRunning;
public float currentSpeed;
public bool isCrouched;
public float crouchHeight;
public float originHeight;
private void Start()
{
characterController = gameObject.GetComponent<CharacterController>();
isRunning = false;
isCrouched = false;
currentSpeed = walkSpeed;
originHeight = characterController.height;
}
private void Update()
{
if(characterController.isGrounded)
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
//MoveDirection存储移动的方向
moveDirection = transform.TransformDirection(new Vector3(h, 0, v));
//实现跳跃
if (Input.GetKeyDown(KeyCode.Space))
moveDirection.y = jumpHeight;
//实现类似于使命召唤的按shift奔跑的效果
if (Input.GetKeyDown(KeyCode.LeftShift) && Input.GetKey(KeyCode.W))
isRunning = !isRunning;
if (Input.GetKeyUp(KeyCode.W))
isRunning = false;
//使用协程实现下蹲,并且下蹲有不同的移动速度
if (Input.GetKeyDown(KeyCode.Z))
{
float targetHeight = isCrouched ? originHeight : crouchHeight;
StartCoroutine("DoCrouch",targetHeight);
isCrouched = !isCrouched;
}
currentSpeed = isRunning ? runSpeed : walkSpeed;
currentSpeed = isCrouched ? crouchSpeed: currentSpeed;
}
//如果人物浮空,则下落
moveDirection.y -= gravity * Time.deltaTime;
//用不同的速度移动
characterController.Move(moveDirection *currentSpeed * Time.deltaTime);
}
IEnumerator DoCrouch(float targetHeight)
{
float velocity = 0;
while(Mathf.Abs(characterController.height-targetHeight)>0.1f)
{
yield return null;
characterController.height=
Mathf.SmoothDamp(characterController.height,targetHeight, ref velocity,Time.deltaTime * 5);
}
}
}