Skip to content

Instantly share code, notes, and snippets.

@foxor
Created November 17, 2018 22:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foxor/b10311c8cd034ff69fd824400d51d272 to your computer and use it in GitHub Desktop.
Save foxor/b10311c8cd034ff69fd824400d51d272 to your computer and use it in GitHub Desktop.
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;
}
}
}
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