基於unity3d的物理賽車驅動系統分享


最近一直在研究unity3d,很強大的一款3d引擎。本篇介紹基於此引擎的一個物理賽車驅動算法。

建模丑了點...

首先,我們需要先弄懂汽車的工作原理。每個汽車的動力來自引擎。引擎動力的量化我們用力矩來表示。引擎通過變速箱把力傳給輪子,這樣輪子就轉了起來,整個汽車就可以動了。

需要注意的有以下幾個點:

1,加減檔系統。所謂變速箱其實可以抽象為一個數組,每個數表示引擎力與輪子力的線性對應關系。汽車一般為6個檔位,那么我們數組的大小也應該是6。

動力來自引擎,通過當前檔位計算出輪子的力矩,從而使輪子轉動。

另一方面我們捕獲輪子的轉速,通過當前檔位再計算出引擎當前的轉速。我們限定了引擎的最大與最小轉速,規定:引擎達到最大轉速的時候,加檔;減速到最小轉速的時候,減檔。

這樣就實現了汽車的自動加減檔,當然也可以做成手動的。

2,unity3d的wheelCollider(輪子碰撞器)。我們可以通過給wheelCollider一個力,它就可以自動實現滾動的物理效果,同時,我們可以通過代碼捕獲它的轉速,這恰恰符合我們的要求。

更強大的是,我們可以設置輪子的橫向與縱向摩擦力,設置輪子的懸掛系統參數,通過這些設置,可以模擬汽車的避震,漂移等效果。

suspension Spring 懸掛系統;

forwardFriction 輪子的縱向摩擦力(車子前進后退方向的摩擦力);

sideWays Friction 輪子的橫向摩擦力;

Extremun Slip;Extremum Value;Asymptote Slip;Asymptote Value這四個值其實是坐標系上的兩個坐標,他們確定了一個滑動距離與摩擦力的關系曲線。

stiffness Factor可以整體調節摩擦曲線的倍數。

3,unity3d的Rigidbody(剛體)。我們可以賦予剛體質量,並且剛體是受重力影響的。車重的不同也會影響汽車的行駛效果!我們一般按真實世界的數值來,例如汽車的mass我們可以設為6000左右(單位為kg),包括模型的尺寸,也最好與真實尺寸一致(單位為米)。這樣我們才能獲得更真實的物理效果。

 

下面我們分享代碼(來源csdn):

using UnityEngine;
using System.Collections;

public class CarControl : MonoBehaviour {
    
    //操縱前輪,用於轉向
    public WheelCollider FrontLeftWheel;
    public WheelCollider FrontRightWheel;
    
    public WheelCollider BackLeftWheel;
    public WheelCollider BackRightWheel;
    
    //齒輪數組
    public float[] GearRatio;
    //當前檔位
    public int     CurrentGear=0;
    
    public float EngineTorgue=600.0f;
    public float MaxEngineRPM=3000.0f;
    public float MinEngineRPM=1000.0f;
    private float EngineRPM=0.0f;
    
    // Use this for initialization
    
    void Start () {
        //設置車的重心,使車更穩定        
        Vector3 centerOfMass=rigidbody.centerOfMass;
        centerOfMass.y=-1.5f;
        rigidbody.centerOfMass=centerOfMass;        
    }
    
    // Update is called once per frame
    void Update () {
     //限制車的最大速度,調整阻力可能不是最好的做法。但它很簡單,而且不會干擾物理系統的運行。
        rigidbody.drag=rigidbody.velocity.magnitude/250;
     //通過兩個輪子的平均rpm,計算引擎rpm,然后切換檔位
        EngineRPM=(FrontLeftWheel.rpm+FrontRightWheel.rpm)/2*GearRatio[CurrentGear];
        ShiftGears();
        
        
        //設置換檔的聲音
        audio.pitch=Mathf.Abs(EngineRPM/MaxEngineRPM)+1.0f;
        if(audio.pitch>2.0)
        {
            audio.pitch=2.0f;
        }
        
        //最后設置輪子轉動力矩。引擎力矩除以當前檔位,乘以用戶輸入值。
        //輪子力矩提供一個汽車前進的力。輪子的轉動又會提高檔位。
        BackLeftWheel.motorTorque=EngineTorgue/GearRatio[CurrentGear]*Input.GetAxis("Vertical");
        BackRightWheel.motorTorque=EngineTorgue/GearRatio[CurrentGear]*Input.GetAxis("Vertical");
        
        //轉動角度是任意數乘以用戶輸入值
        FrontLeftWheel.steerAngle=20*Input.GetAxis("Horizontal");
        FrontRightWheel.steerAngle=20*Input.GetAxis("Horizontal");
    }
    void ShiftGears()
    {
        int AppropriateGear=CurrentGear;
        if(EngineRPM>=MaxEngineRPM)
        {
            AppropriateGear=CurrentGear;
            for(int i=0;i<GearRatio.Length;i++)
            {
                if(FrontLeftWheel.rpm*GearRatio[i]<MaxEngineRPM)
                {
                    AppropriateGear=i;
                    break;
                }
            }
            CurrentGear=AppropriateGear;
        }
        
        if(EngineRPM<=MaxEngineRPM)
        {
            AppropriateGear=CurrentGear;
            for(int j=GearRatio.Length-1;j>=0;j--)
            {
                if(FrontLeftWheel.rpm*GearRatio[j]>MinEngineRPM)
                {
                    AppropriateGear=j;
                    break;
                }
            }
            CurrentGear=AppropriateGear;
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM