Space-Smash-Out/Assets/Scripts/HitFeedbackTestObjectBehavior.cs

196 lines
5.7 KiB
C#

using System.Collections;
using System.Xml.Serialization;
using Managers;
using PrimeTween;
using UnityEngine;
using static AffectingForcesManager;
public class HitFeedbackTestObjectBehavior : MonoBehaviour
{
// Private variables
public AffectingForcesManager forceManager;
public TargetSpawner spawner;
public MeshRenderer meshRenderer1;
public MeshRenderer meshRenderer2;
private MaterialPropertyBlock materialProperties;
private ManageableAudio hitSound;
[SerializeField] private int scoreValue = 150;
[SerializeField] private float normalMaxVelocity = 10;
[SerializeField] private float absolutMaxVelocity = 20;
[SerializeField] private bool useAntiDrift = false;
[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;
[SerializeField] private float tackleStunTime = 0.6f;
// The time in Seconds the player is allowed to boost for
private Rigidbody body;
private Vector3 currentGravity = new Vector3();
// Current Zone the player occupies
private Zone zone = Zone.NimbleZone;
private int instanceID;
private bool isTackled;
private float tackledTime;
void Awake()
{
if (forceManager == null)
{
forceManager = GameObject.FindGameObjectWithTag("ForceManager").
GetComponent<AffectingForcesManager>();
}
materialProperties = new MaterialPropertyBlock();
UpdateBurnOut(0.3f);
}
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody>();
instanceID = gameObject.GetInstanceID();
hitSound = AudioManager.G.GetLocalSound("target_hit", 1, transform);
}
// Update is called once per frame
void FixedUpdate()
{
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();
UpdateTackleResponse();
}
void UpdateMovement()
{
// Get and apply the current Gravity
Transform gravitySource = forceManager.GetGravitySourceForInstance(instanceID);
currentGravity = forceManager.GetGravityForInstance(instanceID)(gravitySource, transform);
body.AddForce(currentGravity, ForceMode.Acceleration);
Vector3 currentVelocity = body.velocity;
if (useAntiDrift && !isTackled)
{
Vector3 driftDampeningAcceleration = DriftDampeningAcceleration(currentVelocity, zone);
// Add anti drift acceleration
body.AddForce(driftDampeningAcceleration, ForceMode.Acceleration);
}
if (currentVelocity.magnitude >= absolutMaxVelocity && !isTackled)
{
body.velocity = body.velocity.normalized * absolutMaxVelocity;
}
// Add drag
if (!isTackled)
{
Vector3 dragDecceleration = DragDecceleration(currentVelocity, zone);
body.AddForce(dragDecceleration, ForceMode.Acceleration);
}
// Default torque drag
body.AddTorque(body.angularVelocity * -torqueDrag, ForceMode.Acceleration);
Debug.DrawRay(transform.position, currentVelocity * 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();
float minDragFactor = Mathf.InverseLerp(absolutMaxVelocity, normalMaxVelocity,
currentVelocity.magnitude);
float normalDragFactor = Mathf.InverseLerp(normalMaxVelocity, 0, currentVelocity.magnitude);
if (zone == Zone.NimbleZone)
{
drag -= currentVelocity.normalized * normalDrag;
}
if (currentVelocity.magnitude >= normalMaxVelocity && zone == Zone.NimbleZone)
{
drag -= currentVelocity.normalized * maximumDrag;
}
return drag;
}
void UpdateTackleResponse(bool gotTackled = false)
{
if (gotTackled)
{
isTackled = true;
tackledTime = tackleStunTime;
return;
}
tackledTime -= Time.deltaTime;
if (tackledTime <= 0)
{
isTackled = false;
tackledTime = 0;
}
}
void OnTriggerEnter(Collider collider)
{
if (collider.tag == "Zone" || isTackled)
{
return;
}
Vector3 colliderVelocity = collider.attachedRigidbody.velocity;
Vector3 tackleDirection = body.transform.position - collider.transform.position;
float colliderMass = collider.attachedRigidbody.mass;
body.AddForce(colliderVelocity.magnitude * tackleDirection * (colliderMass / body.mass),
ForceMode.Acceleration);
UpdateTackleResponse(true);
hitSound.PlayAudio(false);
Destruction();
StatisticsManager.G.AddFreeFlightScore(150);
}
async void Destruction()
{
await Tween.Custom(0.33f, 0.5f, 1.2f, onValueChange: value =>
{
UpdateBurnOut(value);
}).
OnComplete(() => Destroy(gameObject));
}
private void UpdateBurnOut(float value)
{
materialProperties.SetFloat("_Burnout", value);
meshRenderer1.SetPropertyBlock(materialProperties);
meshRenderer2.SetPropertyBlock(materialProperties);
}
private void OnDestroy()
{
spawner.TargetDestroyed(gameObject);
}
}