121 lines
4.3 KiB
C#
121 lines
4.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Reset.Core.Tools;
|
|
using Reset.Units;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public class UnitCombat : UnitComponent {
|
|
// public List<Collider> draggedUnits = new List<Collider>();
|
|
public Dictionary<Collider, float> draggedColliders = new Dictionary<Collider, float>();
|
|
|
|
private UnitMovementHandler movement;
|
|
|
|
private Vector3 lastPosition;
|
|
private Vector3 positionDelta;
|
|
|
|
private float lastSpeed;
|
|
private float speedDelta;
|
|
private float sinAmplitude;
|
|
private float sinOffset;
|
|
|
|
private List<Collider> activelyDraggedColliders;
|
|
private List<Collider> expiredColliders;
|
|
|
|
void Awake(){
|
|
movement = GetComponent<UnitMovementHandler>();
|
|
|
|
activelyDraggedColliders = new List<Collider>();
|
|
expiredColliders = new List<Collider>();
|
|
}
|
|
|
|
void Start(){
|
|
lastPosition = transform.position;
|
|
sinOffset = Random.value;
|
|
sinAmplitude = 1 + Random.value / 4f;
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update(){
|
|
// Calculate movement for dragged units
|
|
DragAttackedUnits();
|
|
|
|
// Check timers to make sure an object doesn't stay dragged
|
|
CheckUnitTimers();
|
|
}
|
|
|
|
// dragTime is set as a maximum. If no time is provided then it defaults to two seconds.
|
|
public void AddDragCollider(Collider newCollider, float dragTime = 2f){
|
|
if (draggedColliders.ContainsKey(newCollider)) {
|
|
draggedColliders[newCollider] = dragTime;
|
|
} else {
|
|
draggedColliders.Add(newCollider, dragTime);
|
|
activelyDraggedColliders.Add(newCollider);
|
|
}
|
|
}
|
|
|
|
public void RemoveDragCollider(Collider colliderToRemove){
|
|
draggedColliders.Remove(colliderToRemove);
|
|
activelyDraggedColliders.Remove(colliderToRemove);
|
|
}
|
|
|
|
void CheckUnitTimers(){
|
|
// Decrease the timer of the dragged colliders
|
|
foreach (Collider thisCollider in activelyDraggedColliders) {
|
|
draggedColliders[thisCollider] -= 1f * Time.deltaTime;
|
|
|
|
// Pend them for removal when ready
|
|
if (draggedColliders[thisCollider] < 0f) {
|
|
expiredColliders.Add(thisCollider);
|
|
}
|
|
}
|
|
|
|
// Remove expired colliders
|
|
for (int i = 0; i < expiredColliders.Count; i++) {
|
|
RemoveDragCollider(expiredColliders[i]);
|
|
}
|
|
|
|
// Clear list if not empty
|
|
if (expiredColliders.Count > 0f) {
|
|
expiredColliders.Clear();
|
|
}
|
|
}
|
|
|
|
void DragAttackedUnits(){
|
|
// Get the original difference in position for speed and direction
|
|
positionDelta = Vector3.Lerp(positionDelta, lastPosition.DirectionTo(transform.position), 5f * Time.deltaTime);
|
|
speedDelta = Vector3.Distance(lastPosition, transform.position) / Time.deltaTime;
|
|
|
|
// Add some randomness to the movements based on small offsets
|
|
float sinVal = Mathf.Sin(2f + sinOffset) * sinAmplitude;
|
|
speedDelta += sinVal;
|
|
|
|
// Set a floor to prevent them from not moving enough
|
|
speedDelta = Mathf.Max(3f, speedDelta);
|
|
|
|
// Multiply the speed to be lower when further, and faster when close
|
|
float speedDiff = Mathf.Lerp(.2f, 1.4f, speedDelta);
|
|
speedDelta *= speedDiff;
|
|
|
|
// Debug
|
|
DebugOverlayDrawer.ChangeValue($"Combat - {name}", "Position Delta", positionDelta);
|
|
DebugOverlayDrawer.ChangeValue($"Combat - {name}", "Speed Delta", speedDelta);
|
|
|
|
// Update last known position
|
|
lastPosition = transform.position;
|
|
|
|
// Apply the speed, direction, and rotation to each unit
|
|
foreach (Collider draggedUnit in activelyDraggedColliders) {
|
|
UnitMovementHandler draggedUnitMovement = draggedUnit.GetComponent<UnitMovementHandler>();
|
|
if (!draggedUnitMovement) {
|
|
Debug.LogError($"No available UnitMovement on {draggedUnit.name}. Aborting drag on this unit.");
|
|
continue;
|
|
}
|
|
|
|
draggedUnitMovement.SetNewRotation(-transform.position.DirectionTo(draggedUnit.transform.position), 1f, true);
|
|
draggedUnitMovement.SetNewDirection(positionDelta.ToVector2(), 1f, true);
|
|
draggedUnitMovement.SetNewSpeed(speedDelta, 1f, true);
|
|
}
|
|
}
|
|
} |