前言:
- 无论是专门的赛车游戏、还是像GTA5、绝地求生这样的游戏。都有开车这样的功能,如何做出好的车辆控制手感,让玩家感受开车的乐趣呢,今天就来学习一个最简单的方式吧
首先需要设计车辆的控制逻辑,为了更真实的模拟车辆的运动方式,采用速度控制效果。主要的速度参数为:
//车辆控制速度参数
private float speedOne = 0f; //车辆实时速度
private float speedMax = 120f; //车辆最大速度
private float speedMin = -20f; //车辆最小速度(倒车最大速度)
private float speedUpA = 2f; //车辆加速加速度(A键控制)
private float speedDownS = 4f; //车辆减速加速度(S键控制)
private float speedTend = 0.5f; //无操作实时速度趋于0时加速度
private float speedBack = 1f; //车辆倒车加速度
整个车辆控制系统核心在于对speedOne的调整,具体设计方式如下:
车辆的加速减速:
当玩家按下W键并且车辆没有达到最大速度时,则车辆加速,若达到最大速度,则车辆速度保持不变。
当玩家按下S键并且车辆速度没有达到最小时,则车辆减速,并且减速速率大于加速,具体代码为:
//按下W键并且速度没达到最大,则速度增加
if (Input.GetKey(KeyCode.W) && speedOne < speedMax)
{
speedOne = speedOne + Time.deltaTime * speedUpA;
}
//按下S键并且速度没达到零,则速度减小
if (Input.GetKey(KeyCode.S) && speedOne > 0f)
{
speedOne = speedOne - Time.deltaTime * speedDownS;
}
车辆的倒车刹车:
车辆的倒车与车辆的减速相似,只是需要判断车辆是否可倒车状态,就是车辆的速度是否小于等于零,且大于最大的倒车速度,通过增加判断来实现的减速效果。
而车辆的刹车系统则采用空格来直接控制,首先就是采用Lerp获得平滑的效果:
//按下S键并且速度没有达到倒车速度最大时,且车辆处于可以倒车状态时车辆倒车
if (Input.GetKey(KeyCode.S) && speedOne > speedMax && speedOne<=0)
{
speedOne = speedOne - Time.deltaTime * speedBack;
}
//按下空格,则汽车停止
if (Input.GetKey(KeyCode.Space) && speedOne != 0)
{
speedOne = Mathf.Lerp(speedOne, 0, 0.4f);
if (speedOne < 5) speedOne = 0;
}
玩家未执行操作:
当玩家没有执行操作时 ,则车辆速度speedOne逐渐回归到零,这样可以保证汽车慢慢的停下来,模拟阻力的效果:
//没有执行速度操作并且速度大于最小速度,则缓慢操作
if (!Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S) && speedOne > 0f)
{
speedOne = speedOne - Time.deltaTime * speedTend;
}
if (!Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S) && speedOne < 0f)
{
speedOne = speedOne + Time.deltaTime * speedTend;
}
车辆转弯:
车辆的转弯效果,当有了一定的基本速度后,则可以实现转弯效果,防止原地打转的效果出现:
//使用A和D来控制物体左右旋转
if(speedOne>1f) //为了区分逻辑,直接数值表示
{
y = Input.GetAxis("Horizontal") * 60f * Time.deltaTime;
transform.Rotate(0, y, 0);
}
该系统存在问题:
很明显,车辆转弯没有漂移效果,需要进行相应的改进
- 最后附上可执行脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarCtrl : MonoBehaviour
{
private float y;
//车辆控制速度参数
private float speedOne = 0f; //车辆实时速度
private float speedMax = 120f; //车辆最大速度
private float speedMin = -20f; //车辆最小速度(倒车最大速度)
private float speedUpA = 2f; //车辆加速加速度(A键控制)
private float speedDownS = 4f; //车辆减速加速度(S键控制)
private float speedTend = 0.5f; //无操作实时速度趋于0时加速度
private float speedBack = 1f; //车辆倒车加速度
// Update is called once per frame
void Update()
{
//鼠标隐藏
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
//按下W键并且速度没达到最大,则速度增加
if (Input.GetKey(KeyCode.W) && speedOne < speedMax)
{
speedOne = speedOne + Time.deltaTime * speedUpA;
}
//按下S键并且速度没达到零,则速度减小
if (Input.GetKey(KeyCode.S) && speedOne > 0f)
{
speedOne = speedOne - Time.deltaTime * speedDownS;
}
//没有执行速度操作并且速度大于最小速度,则缓慢操作
if (!Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S) && speedOne > 0f)
{
speedOne = speedOne - Time.deltaTime * speedTend;
}
if (!Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S) && speedOne < 0f)
{
speedOne = speedOne + Time.deltaTime * speedTend;
}
//按下S键并且速度没有达到倒车速度最大时,且车辆处于可以倒车状态时车辆倒车
if (Input.GetKey(KeyCode.S) && speedOne > speedMax && speedOne<=0)
{
speedOne = speedOne - Time.deltaTime * speedBack;
}
//按下空格,则汽车停止
if (Input.GetKey(KeyCode.Space) && speedOne != 0)
{
speedOne = Mathf.Lerp(speedOne, 0, 0.4f);
if (speedOne < 5) speedOne = 0;
}
transform.Translate(Vector3.forward * speedOne * Time.deltaTime);
//使用A和D来控制物体左右旋转
if(speedOne>1f)
{
y = Input.GetAxis("Horizontal") * 60f * Time.deltaTime;
transform.Rotate(0, y, 0);
}
/* if (transform.eulerAngles.z != 0)
{
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0);
}*/
}
}