Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class ScooterMoveController : MonoBehaviour{
- [Tooltip("The actual physics object to move")]
- public Rigidbody scooterRB;
- [Tooltip("The component that controls throttle input")]
- public ThrottleController throttle;
- [Tooltip("The global forward direction of this object is the direction we'll move in.")]
- public Transform steeringDir;
- [Tooltip("If true, vertical rotation of the cycle is allowed, the rigidbody x constraint must also be disabled.")]
- public bool doRotateVertical = false;
- [Tooltip("The acceleration applied if the throttle is maxxed forward.")]
- public float maxAcceleration = 5f;
- [Tooltip("The acceleration applied if the throttle is maxxed in reverse.")]
- public float reverseAcceleration = 5f;
- [Tooltip("When true, acceleration is applied as force, when false it's added as velocity.")]
- private bool accelerationIsForce = true;
- [Tooltip("The speed at which the scooter tries to turn.")]
- public float turnSpeed = 30f;
- //[Tooltip("The speed at which the scooter tries to turn when close to a standstill.")]
- //public float standstillTurnSpeed = 30f;
- //[Tooltip("The speed at which the scooter tries to turn when close to full speed.")]
- //public float topSpeedTurnSpeed = 15f;
- [Tooltip("The rate at which the scooter's turning slows as it reaches top turning speed.")]
- public float turnDrag = 10f;
- [Tooltip("The factor by which velocity is moved from side-to-side motion to forward motion when turning (the rest of this velocity is lost).")]
- public float velocityForwardConversionFactor = 0.3f;
- [Tooltip("Non-vertical velocity is capped at this value.")]
- public float maxSpeed = 30f;
- // [Tooltip("How much the cycle leans when you turn, in degrees.")]
- // public float leanFactor = 30f;
- void Update(){
- if (doRotateVertical)
- scooterRB.constraints |= RigidbodyConstraints.FreezeRotationX;
- }
- void FixedUpdate(){
- // Get the current forward direction of the scooter
- Vector3 trueForwardDir = scooterRB.transform.forward;
- // We don't care about vertical orientation
- trueForwardDir.y = 0f;
- // Calculate the magnitude of the velocity in the forward direction
- Vector3 trueForward = Vector3.Project(scooterRB.velocity, trueForwardDir);
- // ### FORCE ###
- // Add the force
- if (accelerationIsForce)
- {
- scooterRB.AddForce(scooterRB.transform.forward * (maxAcceleration * throttle.ThrottleValue - reverseAcceleration * throttle.ReverseThrottleValue), ForceMode.Acceleration);
- }
- else
- {
- scooterRB.velocity = scooterRB.velocity + (scooterRB.transform.forward * (maxAcceleration * throttle.ThrottleValue - reverseAcceleration * throttle.ReverseThrottleValue) * Time.fixedDeltaTime);
- }
- // Debug.Log(scooterRB.transform.forward * maxAcceleration * highestFixedUpdateThrottleValue * Time.fixedDeltaTime);
- // This should only be done when we're finished with the highestFixedUpdateThrottleValue for this FixedUpdate cycle
- throttle.ResetThrottle();
- // ### FORWARD FORCE CONVERSION ###
- // We don't want to include vertical velocity in velocity calculations
- Vector3 originalVel = scooterRB.velocity;
- Vector3 flatVel = originalVel;
- flatVel.y = 0;
- // Convert sideways velocity into forward velocity at a reduced rate, remove sideways velocity proportionally
- float sidewaysVelocity = flatVel.magnitude - trueForward.magnitude;
- Vector3 convertedFlatVel = trueForward.normalized * (trueForward.magnitude + sidewaysVelocity * velocityForwardConversionFactor * Time.fixedDeltaTime) + flatVel.normalized * (sidewaysVelocity * (1 - velocityForwardConversionFactor * Time.fixedDeltaTime));
- scooterRB.velocity = new Vector3(convertedFlatVel.x, originalVel.y, convertedFlatVel.z);
- // ### VELOCITY CAP ###
- // We don't want to include vertical velocity in velocity calculations
- originalVel = scooterRB.velocity;
- flatVel = originalVel;
- flatVel.y = 0;
- // Cap the max speed
- if(flatVel.magnitude > maxSpeed){
- flatVel = flatVel.normalized * maxSpeed;
- scooterRB.velocity = new Vector3(flatVel.x, originalVel.y, flatVel.z);
- }
- // ### DIRECTION ###
- Vector3 targetDir = steeringDir.forward;
- if (!doRotateVertical)
- {
- // Throw away vertical orientation if we don't care about vertical rotation
- targetDir.y = 0f;
- }
- // Get the target rotation
- Quaternion targetRot = Quaternion.LookRotation(targetDir);
- // We need to know whether we're going forward or backwards, so we check whether the vector is the same or not
- // Due to properties of dot product and projection, this should be 1 if the vectors are in the same direction and -1 otherwise
- float signMult = Vector3.Dot(trueForward.normalized, trueForwardDir.normalized);
- if (!Mathf.Approximately(signMult, 1) && !Mathf.Approximately(signMult, -1) && !Mathf.Approximately(signMult, 0))
- {
- throw new UnityException("We expect signMult to be either 0, 1, or -1, instead it was: " + signMult);
- }
- // The actual velocity is the magnitude times the signMult to determine the direction
- float currentForwardVel = trueForward.magnitude * signMult;
- float targetTurnSpeed = turnSpeed; // Mathf.Lerp(standstillTurnSpeed, topSpeedTurnSpeed, Mathf.InverseLerp(0, currentForwardVel, topSpeedTurnSpeed));
- // We want the turn to be more extreme the farther away from the center the handles are turned
- float turnIntensity = Vector3.SignedAngle(trueForwardDir, targetDir, Vector3.up) / 180f;
- float targetTurnAmount = targetTurnSpeed * Time.fixedDeltaTime * currentForwardVel * turnIntensity;
- // The scooter rotates towards the orientation of the handlebars at a rate of the maxTurnSpeed multiplied by the forward speed multiplied by how far from the current forward the handlebars are turned
- // The signMult from currentForwardVel means if we go backwards, the controls are inverted like expected
- //scooterRB.MoveRotation(scooterRB.rotation * Quaternion.AngleAxis(targetTurnAmount, Vector3.up));
- float turnRemaining = targetTurnAmount - scooterRB.angularVelocity.y;
- scooterRB.AddRelativeTorque(turnRemaining * Vector3.up, ForceMode.VelocityChange);
- // This is a workaround to a bug with rigidbody constraints Unity refuses to fix
- // This locks the x and z rotations
- if(scooterRB.transform.rotation.eulerAngles.x != 0 || scooterRB.transform.rotation.eulerAngles.z != 0)
- {
- scooterRB.transform.rotation = Quaternion.AngleAxis(scooterRB.transform.eulerAngles.y, Vector3.up);
- }
- // Rotate the cycle around the forward axis to emulate lean
- // scooterRB.transform.localRotation = Quaternion.AngleAxis(-leanFactor * currentForwardVel * turnIntensity, Vector3.forward);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement