Hi all
I’m trying to simulate a gear shift input for my CarAIController. The idea is I have a CarController script that handles physics and inside there is ShiftGear(bool ShiftUpInput, bool ShiftDownInput)
public void shiftGear(bool shiftUpInput, bool shiftDownInput)
{
//if current gear less than 0 then it's reverse gear
//set gear ratio to reverse ratio
//0 is neutral
if (currentGear < 0)
{
currentGearRatio = -reverseRatio;
}
//else look up gear ratio in the array
else
{
currentGearRatio = gearRatio[currentGear];
}
switch (canShift)
{
case false:
shiftUpInput = false;
shiftDownInput = false;
break;
case true:
shiftUpInput = shiftUpInput;
shiftDownInput = shiftDownInput;
break;
}
//shift gear base on transmission type
switch (myTransmissionType)
{
//if semi auto with automatic clutch
//just press shift up and gear will shift after delay time
case TransmissionType.SemiAuto:
if (shiftUpInput && currentGear < gearRatio.Length - 1)
{
//only auto shift within delay time on gear 1 above
//as from 0 to gear 1 engine has to slowly drive the wheel and apply clutch
if (currentGear > 1)
{
currentGear++;
}
else currentGear++;
GetComponent<CarAudio>().PlayShiftSound();
StartCoroutine(emitBackFire());
}
if (shiftDownInput && currentGear >= 0)
{
StartCoroutine(ShiftDownAfterTime(shiftTime));
currentGear--;
GetComponent<CarAudio>().PlayShiftSound();
StartCoroutine(emitBackFire());
}
break;
//if manual with manual clutch
//has to press clutch in order to shift
//use clutch input > 0.90f to compensate for deadzone
case TransmissionType.Manual:
if ((shiftUpInput && clutchInput > 0.90f) && currentGear < gearRatio.Length - 1)
{
currentGear++;
//currentEngineRPM = Mathf.Clamp(currentEngineRPM, minRPM, maxRPM);
GetComponent<CarAudio>().PlayShiftSound();
StartCoroutine(emitBackFire());
}
if ((shiftDownInput&& clutchInput > 0.90f) && currentGear > 0)
{
currentGear--;
//currentEngineRPM = Mathf.Clamp(currentEngineRPM, minRPM, maxRPM);
GetComponent<CarAudio>().PlayShiftSound();
StartCoroutine(emitBackFire());
}
break;
}
}
So this function will receive input from another script CaruserController. This script will actually receive inputs from player and then feed that to the shifting function above in CarController.
bool shiftUp = Input.GetButtonDown("ShiftUp");
bool shiftDown = Input.GetButtonDown("ShiftDown");
myCarController.shiftGear(shiftUp, shiftDown);
Now I want to simulate the same input feeding method to carAIControl. But the problem is that when shifting in manual, the clutch has to be pressed, the RPM takes a while to move back. During that time, the check RPM for shifting method still run and the RPM still remain for a short time during the frame. So that the AI just shift furiously to the highest gear. It’s fine for semi auto since it is defined in CarController that the RPM will move back within a certain time, and the AI only need to wait for that certain time. But for manual there is no defined time, so there is no way to check
These are the code I have so far for the AI:
public IEnumerator ShiftUp()
{
switch (m_CarController.myTransmissionType)
{
case TransmissionType.Manual:
//release throttle, press clutch
throttle = 0f;
clutch = 1f;
//m_CarController.Move(steer, 0f, 1f, 0f);
//"press" shift up
m_CarController.shiftGear(true, false);
yield return null;
m_CarController.shiftGear(false, false);
//yield return new WaitForSeconds(shiftTimeDifficulty);
clutch = 0f;
yield return new WaitForSeconds(1f);
break;
case TransmissionType.SemiAuto:
m_CarController.shiftGear(true, false);
//yield return new WaitForEndOfFrame();
//yield return 0;
m_CarController.shiftGear(false, false);
//yield return new WaitForEndOfFrame();
yield return new WaitForSeconds(1f);
break;
}
}
//coroutin for shifting down
public IEnumerator ShiftDown()
{
//2 cases, manual clutch and semi auto
switch (m_CarController.myTransmissionType)
{
//if manual, press clutch then shift
//process takes time depends on difficulty level
case TransmissionType.Manual:
//release throttle, press clutch
throttle = 0f;
clutch = 1f;
//"press" shift down by setting input to true for 1 frame then false
m_CarController.shiftGear(false, true);
yield return null;
m_CarController.shiftGear(false, false);
//wait for difficulty time then restore throttle and release clutch
//yield return new WaitForSeconds(shiftTimeDifficulty);
clutch = 0f;
yield return new WaitForSeconds(1f);
break;
//if semi auto, just press shift gear
//since clutch and throttle are handled automatically by carcontroller
case TransmissionType.SemiAuto:
m_CarController.shiftGear(false, true);
//yield return new WaitForEndOfFrame();
// yield return 0;
m_CarController.shiftGear(false, false);
//yield return new WaitForEndOfFrame();
yield return new WaitForSeconds(1f);
break;
}
//yield return new WaitForSeconds(1f);
}
//handle gear changing
public void GearChange()
{
int currentGear = m_CarController.currentGear;
float currentRPM = m_CarController.currentEngineRPM;
//shift up when reach upper limit of power band
float shiftUpRPM;
float shiftDownRPM;
//if launch from neutral gear then shift up when RMP is at max torque RPM
if (currentGear == 0 )
{
//throttle = Mathf.Clamp((m_CarController.maxTorqueRPM - currentRPM) * AccelSensitivity, 0, 1);
shiftUpRPM = m_CarController.maxTorqueRPM;
//shiftDownRPM = m_CarController.maxTorqueRPM;
}
else
{
shiftUpRPM = m_CarController.powerBand[1];
shiftDownRPM = m_CarController.powerBand[1] / m_CarController.gearRatio[currentGear] / m_CarController.gearRatio[currentGear - 1];
}
//shift down when reach lower limit of power band
shiftDownRPM = m_CarController.powerBand[0];
//shiftDownRPM = m_CarController.powerBand[1] / m_CarController.gearRatio[currentGear] / m_CarController.gearRatio[currentGear - 1]; ;
//if (currentGear > 0)
//{
// shiftDownRPM = m_CarController.powerBand[1] / (m_CarController.gearRatio[currentGear] / m_CarController.gearRatio[currentGear - 1]);
//}
//else
//{
// shiftDownRPM = m_CarController.maxTorqueRPM;
//}
//only shift when car control is allowed shifting and AI is driving
if (m_CarController.canShift && Driving)
{
if (currentGear < m_CarController.gearRatio.Length - 1 && currentRPM >= shiftUpRPM)
{
StartCoroutine(ShiftUp());
}
if (currentGear > 1 && currentRPM <= shiftDownRPM)
{
StartCoroutine(ShiftDown());
}
}
}
Please help. Thank you very much