Created
November 17, 2018 22:45
-
-
Save foxor/b10311c8cd034ff69fd824400d51d272 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class BusController : MonoBehaviour | |
{ | |
protected static readonly float ATTACK_MODIFIER = 7f; | |
protected static readonly float FLIGHT_MODIFIER = 250f; | |
protected static readonly float BRAKE_MODIFIER = -0.7f; | |
protected static readonly float PITCH_CORRECT_TARGET_TIME = 0.2f; | |
protected static readonly float MOUSE_PIXELS_TO_RADIANS = Mathf.Deg2Rad; | |
protected static readonly float GROUND_CONTACT_GRACE_PERIOD = 0.25f; | |
public Camera attachedCamera; | |
protected Vector3 mousePosition = new Vector3(Mathf.PI / -2f, 50f * Mathf.Deg2Rad, 0f); | |
protected float cameraDistance; | |
protected Rigidbody body; | |
protected bool tryUnlockMouse; | |
protected float lastGroundContactTime; | |
protected bool currentlyOnGround; | |
protected bool jumped; | |
protected bool OnGround | |
{ | |
get | |
{ | |
return currentlyOnGround || lastGroundContactTime + GROUND_CONTACT_GRACE_PERIOD > Time.time; | |
} | |
} | |
protected quaternionPID PID; | |
public void Awake() | |
{ | |
cameraDistance = (attachedCamera.transform.position - transform.position).magnitude; | |
body = GetComponent<Rigidbody>(); | |
PID = new quaternionPID(body.rotation, body.rotation * Quaternion.Euler(0f, 0f, 90f), 0.1f, 0.005f, 8f); | |
} | |
protected void TryPush(Vector3 jetpackForce) | |
{ | |
body.AddForce(jetpackForce); | |
} | |
public void Update() | |
{ | |
if (tryUnlockMouse |= Input.GetKeyDown(KeyCode.Escape)) | |
{ | |
Cursor.lockState = CursorLockMode.None; | |
Cursor.visible = true; | |
} | |
else | |
{ | |
Cursor.lockState = CursorLockMode.Locked; | |
} | |
mousePosition = new Vector3( | |
mousePosition.x - Input.GetAxisRaw("Mouse X") * MOUSE_PIXELS_TO_RADIANS, | |
Mathf.Clamp(mousePosition.y - Input.GetAxisRaw("Mouse Y") * MOUSE_PIXELS_TO_RADIANS, Mathf.PI * 10 / 30f, Mathf.PI * 14f / 30f) | |
); | |
Vector3 cameraUnitSpherePosition = new Vector3( | |
Mathf.Cos(mousePosition.x) * Mathf.Sin(mousePosition.y), | |
Mathf.Cos(mousePosition.y), | |
Mathf.Sin(mousePosition.x) * Mathf.Sin(mousePosition.y) | |
).normalized; | |
attachedCamera.transform.position = transform.position + cameraUnitSpherePosition * cameraDistance; | |
attachedCamera.transform.rotation = Quaternion.LookRotation(-cameraUnitSpherePosition); | |
Vector3 targetRotationEuler = (attachedCamera.transform.rotation * Quaternion.Euler(-20f, 0f, 0f)).eulerAngles; | |
if (OnGround || true) | |
{ | |
targetRotationEuler.x = 0f; | |
} | |
PID.UpdateTarget(Quaternion.Euler(targetRotationEuler)); | |
} | |
protected float wrap(float input) | |
{ | |
return (input + 180f) % 360f - 180f; | |
} | |
public void FixedUpdate() | |
{ | |
TryPush(transform.rotation * Vector3.forward * Input.GetAxisRaw("Forward") * ATTACK_MODIFIER); | |
if (!jumped && OnGround && Input.GetAxisRaw("Vertical") != 0f) | |
{ | |
jumped = true; | |
TryPush(transform.rotation * Vector3.up * Input.GetAxisRaw("Vertical") * FLIGHT_MODIFIER); | |
} | |
if (Input.GetKey(KeyCode.E)) | |
{ | |
body.AddForce(body.velocity * BRAKE_MODIFIER); | |
} | |
body.AddRelativeTorque(PID.Update(body.rotation)); | |
} | |
public void OnCollisionEnter(Collision hit) | |
{ | |
if (hit.gameObject.tag == "Ground") | |
{ | |
//TODO: Set PID target so that bus normal = ground normal | |
jumped = false; | |
currentlyOnGround = true; | |
} | |
} | |
public void OnCollisionExit(Collision hit) | |
{ | |
if (hit.gameObject.tag == "Ground") | |
{ | |
currentlyOnGround = false; | |
lastGroundContactTime = Time.time; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Linq; | |
using System; | |
public class floatPID : PID<float, float> | |
{ | |
public floatPID(float currentValue, float target, float pGain = 0f, float iGain = 0f, float dGain = 0f) : | |
base(currentValue, target, pGain, iGain, dGain) | |
{ } | |
protected override float amplify(float value, float gain) | |
{ | |
return value * gain; | |
} | |
protected override float combine(float lhs, float rhs) | |
{ | |
return lhs + rhs; | |
} | |
protected override float difference(float lhs, float rhs) | |
{ | |
return lhs - rhs; | |
} | |
} | |
public class quaternionPID : PID<Quaternion, Vector3> | |
{ | |
public quaternionPID(Quaternion currentValue, Quaternion target, float pGain = 0f, float iGain = 0f, float dGain = 0f) : | |
base(currentValue, target, pGain, iGain, dGain) | |
{ } | |
/*public override void UpdateTarget(Quaternion newTarget) | |
{ | |
if (Quaternion.Dot(newTarget, target) >= 0) | |
{ | |
base.UpdateTarget(newTarget); | |
} | |
else | |
{ | |
base.UpdateTarget(Quaternion.Inverse(newTarget)); | |
} | |
}*/ | |
protected Vector3 wrap(Vector3 input) | |
{ | |
return new Vector3( | |
(input.x + 180f) % 360f - 180f, | |
(input.y + 180f) % 360f - 180f, | |
(input.z + 180f) % 360f - 180f | |
); | |
} | |
protected override Vector3 difference(Quaternion lhs, Quaternion rhs) | |
{ | |
return wrap((Quaternion.Inverse(lhs) * rhs).eulerAngles); | |
} | |
protected override Vector3 amplify(Vector3 value, float gain) | |
{ | |
return value * gain; | |
} | |
protected override Vector3 combine(Vector3 lhs, Vector3 rhs) | |
{ | |
return lhs + rhs; | |
} | |
} | |
public abstract class PID<S,O> | |
{ | |
protected static readonly int HISTORY_LENGTH = 30; | |
protected S[] history = new S[HISTORY_LENGTH]; | |
protected bool historyFull = false; | |
protected int currentHistoryIndex = 0; | |
protected S target; | |
protected float pGain; | |
protected float iGain; | |
protected float dGain; | |
public PID(S currentValue, S target, float pGain, float iGain, float dGain) | |
{ | |
history[0] = currentValue; | |
this.target = target; | |
this.pGain = pGain; | |
this.iGain = iGain; | |
this.dGain = dGain; | |
} | |
public virtual void UpdateTarget(S newTarget) | |
{ | |
this.target = newTarget; | |
} | |
public O Update(S sample) | |
{ | |
if (pGain == 0f && iGain == 0f && dGain == 0f) | |
{ | |
return default(O); | |
} | |
O derivative = difference(sample, history[currentHistoryIndex]); | |
currentHistoryIndex = (currentHistoryIndex + 1) % HISTORY_LENGTH; | |
history[currentHistoryIndex] = sample; | |
historyFull |= currentHistoryIndex == HISTORY_LENGTH - 1; | |
O integral = default(O); | |
for (int i = 0; i < HISTORY_LENGTH && (historyFull || i <= currentHistoryIndex); i++) | |
{ | |
integral = combine(integral, difference(history[i], target)); | |
} | |
O positional = difference(sample, target); | |
return combine(combine(amplify(positional, pGain), amplify(integral, iGain)), amplify(derivative, dGain)); | |
} | |
protected abstract O difference(S lhs, S rhs); | |
protected abstract O combine(O lhs, O rhs); | |
protected abstract O amplify(O value, float gain); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment