297 lines
9.4 KiB
C#
297 lines
9.4 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.SceneManagement;
|
|
using static AffectingForcesManager;
|
|
|
|
public class PlayerController : MonoBehaviour
|
|
{
|
|
[SerializeField] public int playerId = 1;
|
|
[SerializeField] public string playerName = "gray";
|
|
// Private variables
|
|
[SerializeField] private CameraOperator cameraOperator;
|
|
[SerializeField] private float thrustAcceleration = 400;
|
|
[SerializeField] private float steerVelocity = 30;
|
|
[SerializeField] private float normalMaxVelocity = 10;
|
|
[SerializeField] private float absolutMaxVelocity = 20;
|
|
[SerializeField] private float antiDriftAmount = 20;
|
|
[SerializeField] private float minAntiDriftFactor = 0.2f;
|
|
[SerializeField] private float normalDrag = 0.1f;
|
|
[SerializeField] private float maximumDrag = 0.3f;
|
|
[SerializeField] private float torqueDrag = 0.2f;
|
|
// The time in Seconds the player is allowed to boost for
|
|
[SerializeField] private float maxBoostCapacity = 2f;
|
|
[SerializeField] private float minBoostCapacity = 0.3f * 2f;
|
|
[SerializeField] private float boostMagnitude = 1.5f;
|
|
[SerializeField] private float outsideBoostRate = 0.5f;
|
|
[SerializeField, Range(0, 1)] private float boostAntiGravityFactor = 0.2f;
|
|
[SerializeField] private float stunLooseControlFactor = 0.1f;
|
|
[SerializeField] private float tackleCriticalStunTime = 0.6f;
|
|
[SerializeField] private float tackleBodyStunTime = 0.3f;
|
|
[SerializeField, Range(0, 300)] private float criticalTacklePowerFactor = 10f;
|
|
[SerializeField, Range(0, 300)] private float normalTacklePowerFactor = 10f;
|
|
[SerializeField] private BoostCapacityUI boostUI;
|
|
private AffectingForcesManager forceManager;
|
|
public PlayerInput playerInput;
|
|
private Rigidbody body;
|
|
private Vector3 currentGravity = new Vector3();
|
|
// Saves the current input value for thrust
|
|
private float currentThrustInput = 0;
|
|
private float currentBoostInput = 0;
|
|
private float boostCapacity;
|
|
// Saves the current input for steering
|
|
private float currentSteerInput = 0;
|
|
private bool canBoost = true;
|
|
private TackleDetection[] tackleDetectors;
|
|
private bool isCriticalTackle = false;
|
|
private bool isTackled = false;
|
|
private float tackledTime = 0f;
|
|
// Current Zone the player occupies
|
|
private Zone zone = Zone.NimbleZone;
|
|
public int instanceID;
|
|
|
|
void Awake()
|
|
{
|
|
if (forceManager == null)
|
|
{
|
|
forceManager = GameObject.FindGameObjectWithTag("ForceManager").GetComponent<AffectingForcesManager>();
|
|
}
|
|
body = GetComponent<Rigidbody>();
|
|
playerInput = GetComponent<PlayerInput>();
|
|
}
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
instanceID = gameObject.GetInstanceID();
|
|
boostCapacity = maxBoostCapacity;
|
|
boostUI.SetMinBoostRatio(minBoostCapacity / maxBoostCapacity);
|
|
GameManager.GM.RegisterPlayer(this);
|
|
cameraOperator.AddPlayer(gameObject);
|
|
|
|
tackleDetectors = GetComponentsInChildren<TackleDetection>();
|
|
foreach (TackleDetection td in tackleDetectors)
|
|
{
|
|
td.TackleResponse.AddListener(StartTackleResponse);
|
|
}
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
foreach (TackleDetection td in tackleDetectors)
|
|
{
|
|
td.TackleResponse.RemoveAllListeners();
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void FixedUpdate()
|
|
{
|
|
if (GameManager.GM.currentState == GameState.Starting)
|
|
{
|
|
return;
|
|
}
|
|
zone = forceManager.GetZoneOfInstance(instanceID);
|
|
//BoostStateUpdate(Time.deltaTime);
|
|
// Rotate the vehicle with the current steer velocity
|
|
// Calculate the magnitude of the acceleration with the current thrust
|
|
UpdateMovement();
|
|
// TODO Always full thrust when boosting?
|
|
BoostStateUpdate(Time.deltaTime);
|
|
UpdateTackleResponse(isCriticalTackle);
|
|
}
|
|
|
|
void UpdateMovement()
|
|
{
|
|
|
|
//Debug.Log("inupdatemove " + currentThrustInput);
|
|
// Player rotation is always possible and same speed
|
|
transform.Rotate(0, 0, -steerVelocity * currentSteerInput * Time.deltaTime);
|
|
|
|
// Get and apply the current Gravity
|
|
currentGravity = forceManager.GetGravityForInstance(instanceID)(transform.position);
|
|
body.AddForce(currentGravity, ForceMode.Acceleration);
|
|
|
|
float tackleFactor = isCriticalTackle ? stunLooseControlFactor : 1f;
|
|
|
|
Vector3 acceleration = thrustAcceleration * currentThrustInput * Time.deltaTime
|
|
* Vector3.up * tackleFactor;
|
|
|
|
Vector3 currentVelocity = body.velocity;
|
|
|
|
Vector3 boostedAcceleration = BoostAcceleration(acceleration, currentGravity);
|
|
|
|
if (!isCriticalTackle)
|
|
{
|
|
// Add drag
|
|
Vector3 dragDecceleration = DragDecceleration(currentVelocity, zone);
|
|
body.AddForce(dragDecceleration, ForceMode.Acceleration);
|
|
|
|
if (!isTackled)
|
|
{
|
|
// Add anti drift acceleration
|
|
Vector3 driftDampeningAcceleration = DriftDampeningAcceleration(currentVelocity, zone);
|
|
body.AddForce(driftDampeningAcceleration, ForceMode.Acceleration);
|
|
}
|
|
|
|
if (currentVelocity.magnitude <= normalMaxVelocity || IsBoosting() || zone != Zone.NimbleZone)
|
|
{
|
|
body.AddRelativeForce(boostedAcceleration, ForceMode.Acceleration);
|
|
}
|
|
if (currentVelocity.magnitude >= absolutMaxVelocity)
|
|
{
|
|
body.velocity = body.velocity.normalized * absolutMaxVelocity;
|
|
}
|
|
}
|
|
|
|
// Default torque drag
|
|
body.AddTorque(body.angularVelocity * -torqueDrag, ForceMode.Acceleration);
|
|
|
|
Debug.DrawRay(transform.position, transform.up * currentVelocity.magnitude * 0.5f, Color.black);
|
|
}
|
|
|
|
Vector3 DriftDampeningAcceleration(Vector3 currentVelocity, Zone zone)
|
|
{
|
|
Vector3 antiDriftVelocity = new Vector3();
|
|
float antiDriftFactor = 1f;
|
|
// Cancel out inertia/drifting
|
|
if (zone == Zone.NimbleZone)
|
|
{
|
|
Vector3 rotation = transform.rotation.eulerAngles;
|
|
Vector3 driftVelocity = currentVelocity - Vector3.Project(currentVelocity, rotation);
|
|
antiDriftVelocity = Vector3.Reflect(-driftVelocity, transform.up) - driftVelocity;
|
|
antiDriftFactor = Mathf.InverseLerp(absolutMaxVelocity, normalMaxVelocity, currentVelocity.magnitude);
|
|
antiDriftFactor = Mathf.Max(antiDriftFactor, minAntiDriftFactor);
|
|
Debug.DrawRay(transform.position, driftVelocity.normalized * 5, Color.red);
|
|
}
|
|
Debug.DrawRay(transform.position, antiDriftVelocity.normalized * 5, Color.green);
|
|
return antiDriftVelocity * antiDriftAmount * antiDriftFactor;
|
|
}
|
|
|
|
Vector3 DragDecceleration(Vector3 currentVelocity, Zone zone)
|
|
{
|
|
Vector3 drag = new Vector3();
|
|
bool isBoosting = currentBoostInput > 0 && canBoost == true;
|
|
float minDragFactor = Mathf.InverseLerp(absolutMaxVelocity, normalMaxVelocity, currentVelocity.magnitude);
|
|
float normalDragFactor = Mathf.InverseLerp(normalMaxVelocity, 0, currentVelocity.magnitude);
|
|
if (!isBoosting && zone == Zone.NimbleZone)
|
|
{
|
|
drag -= currentVelocity.normalized * normalDrag;
|
|
}
|
|
if (currentVelocity.magnitude >= normalMaxVelocity && zone == Zone.NimbleZone)
|
|
{
|
|
drag -= currentVelocity.normalized * maximumDrag;
|
|
}
|
|
return drag;
|
|
}
|
|
|
|
bool IsBoosting()
|
|
{
|
|
return currentBoostInput > 0 && canBoost;
|
|
}
|
|
|
|
Vector3 BoostAcceleration(Vector3 acceleration, Vector3 currentGravity)
|
|
{
|
|
if (IsBoosting())
|
|
{
|
|
acceleration *= boostMagnitude;
|
|
acceleration -= currentGravity * boostAntiGravityFactor;
|
|
}
|
|
return acceleration;
|
|
}
|
|
|
|
void BoostStateUpdate(float deltaTime)
|
|
{
|
|
boostUI.UpdateFill(Math.Min(boostCapacity / maxBoostCapacity, 1));
|
|
if (IsBoosting() && currentThrustInput != 0)
|
|
{
|
|
// Debug.Log("Boost Kapazität wird verbraucht: " + boostCapacity);
|
|
boostCapacity -= deltaTime;
|
|
}
|
|
if (canBoost && zone == Zone.OutsideZone)
|
|
{
|
|
// Debug.Log("Boost Kapazität wird passiv verbraucht: " + boostCapacity);
|
|
boostCapacity -= deltaTime * outsideBoostRate;
|
|
}
|
|
if (boostCapacity <= 0)
|
|
{
|
|
canBoost = false;
|
|
// Debug.Log("Boost aufgebraucht");
|
|
}
|
|
// TODO this will be spam abused
|
|
if ((currentBoostInput <= 0 || currentThrustInput == 0 || !canBoost)
|
|
&& zone == Zone.NimbleZone
|
|
&& boostCapacity <= maxBoostCapacity)
|
|
{
|
|
// Debug.Log("Boost wird aufgeladen: " + boostCapacity);
|
|
boostCapacity += deltaTime;
|
|
}
|
|
if (canBoost == false && boostCapacity >= minBoostCapacity)
|
|
{
|
|
canBoost = true;
|
|
// Debug.Log("Boost verfügbar");
|
|
}
|
|
}
|
|
|
|
void UpdateTackleResponse(bool gotTackled = false)
|
|
{
|
|
if (gotTackled && !isTackled)
|
|
{
|
|
isTackled = true;
|
|
tackledTime = isCriticalTackle ? tackleCriticalStunTime : tackleBodyStunTime;
|
|
return;
|
|
}
|
|
tackledTime -= Time.deltaTime;
|
|
if (tackledTime <= 0)
|
|
{
|
|
isTackled = false;
|
|
isCriticalTackle = false;
|
|
tackledTime = 0;
|
|
}
|
|
}
|
|
|
|
public void OnThrust(InputAction.CallbackContext context)
|
|
{
|
|
currentThrustInput = context.ReadValue<float>();
|
|
}
|
|
|
|
public void OnSteer(InputAction.CallbackContext context)
|
|
{
|
|
currentSteerInput = context.ReadValue<float>();
|
|
}
|
|
|
|
public void OnBoost(InputAction.CallbackContext context)
|
|
{
|
|
currentBoostInput = context.ReadValue<float>();
|
|
}
|
|
|
|
public void OnResetScene(InputAction.CallbackContext context)
|
|
{
|
|
if (context.phase == InputActionPhase.Performed)
|
|
{
|
|
Debug.Log("reload triggered");
|
|
Destroy(GameManager.GM);
|
|
string currentSceneName = SceneManager.GetActiveScene().name;
|
|
SceneManager.LoadScene(currentSceneName);
|
|
}
|
|
}
|
|
void StartTackleResponse(TackleKind tackleKind, Collider collider)
|
|
{
|
|
float tacklePowerFactor = criticalTacklePowerFactor;
|
|
if (tackleKind == TackleKind.Critical)
|
|
{
|
|
isCriticalTackle = true;
|
|
}
|
|
else
|
|
{
|
|
isCriticalTackle = false;
|
|
tacklePowerFactor = normalTacklePowerFactor;
|
|
}
|
|
Vector3 colliderVelocity = collider.attachedRigidbody.velocity;
|
|
Vector3 tackleDirection = body.transform.position - collider.transform.position;
|
|
body.AddForce(colliderVelocity.magnitude * tackleDirection * tacklePowerFactor, ForceMode.Acceleration);
|
|
UpdateTackleResponse(true);
|
|
}
|
|
|
|
}
|