Hi, i wrote basic script to stabilize bike in my game, it’s just a begining. My moto is stabie if it stays in the 0,0,0 coords, when i want to move it somewhere else it’s doing front flip. Stabilization algorithm is basic PD controller. Here is my code:
using XInputDotNetPure;
public class MotoController: MonoBehaviour {
public WheelCollider rearCollider;
public WheelCollider frontCollider;
public Transform frontWheel;
public Transform rearWheel;
public Vector3 centerOfMass;
public Transform COMSphere;
bool playerIndexSet = false;
PlayerIndex playerIndex;
GamePadState state;
GamePadState prevState;
private float COMXLimit = 1.5f;
private float COMZLimit = 2f;
private float TurnLimit = 60.0f;
public float smooth = 1f;
private float smoothTurn;
private float newAngle;
private Vector3 newCOMPosition;
private Vector3 newlocalRotation;
//PID
private float popUchyb = 0;
public float stalaD = 0.01f;
public float stalaP = 0.1f;
private float p = 0;
private float d = 0;
private float uchyb = 0;
private float odpowiedz;
Vector3 temp;
//END of PID
float roznicaKata = 0;
// Use this for initialization
void Start () {
centerOfMass = new Vector3(0, 1f, 0);
this.rigidbody.centerOfMass = centerOfMass;
}
void Awake () {
newAngle = frontCollider.steerAngle;
newCOMPosition = this.centerOfMass;
newlocalRotation = this.transform.localEulerAngles;
}
// Update is called once per frame
void FixedUpdate() {
//PID
roznicaKata = transform.localEulerAngles.z;
if(roznicaKata > 180f) roznicaKata = roznicaKata - 360;
uchyb = -(0 - roznicaKata);
d = stalaD * ((uchyb - popUchyb / Time.deltaTime));
p = uchyb * stalaP;
odpowiedz = p+d;
//END OF PID
}
void Update () {
// Find a PlayerIndex, for a single player game
if (!playerIndexSet || !prevState.IsConnected)
{
for (int i = 0; i < 4; ++i)
{
PlayerIndex testPlayerIndex = (PlayerIndex)i;
GamePadState testState = GamePad.GetState(testPlayerIndex);
if (testState.IsConnected)
{
Debug.Log(string.Format("GamePad found {0}", testPlayerIndex));
playerIndex = testPlayerIndex;
playerIndexSet = true;
}
}
}
state = GamePad.GetState(playerIndex);
//Turning
newAngle = state.ThumbSticks.Right.X * TurnLimit;
smoothTurn = Mathf.Lerp(frontCollider.steerAngle, newAngle, Time.deltaTime * smooth);
frontCollider.steerAngle = smoothTurn;
rearCollider.motorTorque = state.Triggers.Right * 50;
rearCollider.brakeTorque = state.Triggers.Left * 100;
//Center Of Mass
Vector3 pos = new Vector3();
pos.x = Mathf.Lerp(-state.ThumbSticks.Left.X * COMXLimit, newCOMPosition.x, Time.deltaTime);
pos.z = Mathf.Lerp(-state.ThumbSticks.Left.Y * COMZLimit, newCOMPosition.z, Time.deltaTime * 15);
if(odpowiedz >=3.0f) odpowiedz = 3.0f;
if(odpowiedz <=-3.0f) odpowiedz = -3.0f;
Vector3 tp;
tp = transform.TransformPoint(centerOfMass);
tp += transform.TransformDirection(Vector3.right) * (pos.x - odpowiedz);
COMSphere.position = tp;
this.rigidbody.centerOfMass = tp;
popUchyb = uchyb;
prevState = state;
}
void OnGUI() {
GUI.Label(new Rect(20,20,200,100),
string.Format("Right ThumbStick.X: {0}
" +
"Right ThumbStick.Y: {1}
" +
"Left ThumbStick.X: {2}
" +
"Left ThumbStick.Y: {3}
"
, state.ThumbSticks.Right.X, state.ThumbSticks.Right.Y, state.ThumbSticks.Left.X, state.ThumbSticks.Left.Y));
GUI.Label(new Rect(20,220,200,100),
string.Format("Uchyb(stopnie: {0}
" +
“Odpowiedz: {1}”, roznicaKata,odpowiedz));
}
}