Unity -车辆控制效果的实现

前言:

  • 无论是专门的赛车游戏、还是像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);
        }*/
    }
}


posted @ 2020-11-30 21:47  心之凌儿  阅读(2577)  评论(0编辑  收藏  举报