using Unity.Mathematics; using UnityEngine; using UnityEngine.InputSystem; [RequireComponent(typeof(Rigidbody2D))] public class CarLogic : MonoBehaviour { public InputAction steeringAction; public InputAction accelerationAction; public InputAction brakeAction; public float accelerationAmount = 10; [Tooltip("In degrees")] public float steeringAnglePerSecond = 10; public float maxAcceleration = 100; public float brakingAmount; private Rigidbody2D _rigidbody; private Transform _transform; private float _currentAcceleration; private float _wheelAccelerationAmount; private int _wheelOffroadCount = 0; public float CurrentAccelerationRatio() { return _currentAcceleration / maxAcceleration; } private void Awake() { _rigidbody = GetComponent(); _transform = transform; } private void Start() { steeringAction.Enable(); accelerationAction.Enable(); brakeAction.Enable(); var wheels = GetComponentsInChildren(); foreach (var wheel in wheels) { wheel.wheelOffRoad = WheelOffRoad; wheel.wheelOnRoad = WheelOnRoad; } _wheelAccelerationAmount = maxAcceleration / 5f; _wheelOffroadCount = 4; } private void WheelOffRoad() { _wheelOffroadCount++; } private void WheelOnRoad() { _wheelOffroadCount--; } private void Update() { var steeringValue = steeringAction.ReadValue(); var accelerationValue = accelerationAction.ReadValue(); var brakeValue = brakeAction.ReadValue(); // TODO: The way that I changed this too I like a lot better, however I do want to eventually figure out what was wrong with this verbose approach. // Vector2 velocityDir = _transform.up; // var currentAngleRad = Mathf.Acos(Vector3.Dot(velocityDir, Vector3.up)); // var deltaAngleRad = steeringValue * steeringAnglePerSecond * Time.deltaTime * Mathf.Deg2Rad; // var angleRad = deltaAngleRad + currentAngleRad; // // var angleCos = Mathf.Cos(angleRad); // var angleSin = Mathf.Sin(angleRad); // Vector2 nextVelocityDir; // nextVelocityDir.x = angleCos * velocityDir.x - // angleSin * velocityDir.y; // nextVelocityDir.y = angleSin * velocityDir.x + // angleCos * velocityDir.y; // // nextVelocityDir *= accelerationAmount * accelerationValue * Time.deltaTime; // TODO: probably not correct... ODE or some other formula. if (accelerationValue <= 0) { _currentAcceleration -= _rigidbody.drag * Time.deltaTime; } _currentAcceleration += accelerationValue * accelerationAmount * Time.deltaTime; _currentAcceleration -= brakeValue * brakingAmount * Time.deltaTime; if (_currentAcceleration > maxAcceleration / 3f) { _currentAcceleration -= _wheelOffroadCount * _wheelAccelerationAmount * Time.deltaTime; } // TODO: reverse logic. _currentAcceleration = Mathf.Clamp(_currentAcceleration, 0, maxAcceleration); if (_currentAcceleration > 0.01) { var newAngle = steeringValue * steeringAnglePerSecond * Time.deltaTime; _transform.Rotate(Vector3.forward, newAngle, Space.World); } _rigidbody.velocity = _transform.up * _currentAcceleration; } }