mirror of
https://github.com/Xevion/Rebirth.git
synced 2025-12-06 21:16:06 -06:00
Fixed smart unit movement with planetary surface movement & cohesion rules
This commit is contained in:
@@ -4,6 +4,7 @@ using UnityEngine;
|
|||||||
using DataStructures.ViliWonka.KDTree;
|
using DataStructures.ViliWonka.KDTree;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEditor.Search;
|
||||||
|
|
||||||
public class Planet : MonoBehaviour
|
public class Planet : MonoBehaviour
|
||||||
{
|
{
|
||||||
@@ -11,6 +12,7 @@ public class Planet : MonoBehaviour
|
|||||||
private LineRenderer _lineRenderer;
|
private LineRenderer _lineRenderer;
|
||||||
private CircleCollider2D _circleCollider;
|
private CircleCollider2D _circleCollider;
|
||||||
private Network _network;
|
private Network _network;
|
||||||
|
public KDQuery Query => _query;
|
||||||
private KDQuery _query;
|
private KDQuery _query;
|
||||||
public KDTree Tree => _tree;
|
public KDTree Tree => _tree;
|
||||||
private KDTree _tree;
|
private KDTree _tree;
|
||||||
@@ -35,10 +37,8 @@ public class Planet : MonoBehaviour
|
|||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
while (_units.Count < 10)
|
while (_units.Count < 16)
|
||||||
SpawnUnit();
|
SpawnUnit();
|
||||||
|
|
||||||
InvokeRepeating("ChangeUnits", 0.0f, 1f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnMouseDown()
|
void OnMouseDown()
|
||||||
@@ -53,9 +53,9 @@ public class Planet : MonoBehaviour
|
|||||||
return (Vector2)transform.position + new Vector2(Mathf.Cos(theta), Mathf.Sin(theta)) * radius;
|
return (Vector2)transform.position + new Vector2(Mathf.Cos(theta), Mathf.Sin(theta)) * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetUnitAngle(Unit unit)
|
public float GetAngle(Vector2 position)
|
||||||
{
|
{
|
||||||
var angle = Mathf.Atan2(unit.transform.position.y, unit.transform.position.x) * Mathf.Rad2Deg;
|
var angle = Mathf.Atan2(position.y - transform.position.y, position.x - transform.position.x) * Mathf.Rad2Deg;
|
||||||
return angle < 0 ? angle + 360 : angle;
|
return angle < 0 ? angle + 360 : angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
143
Assets/Unit.cs
143
Assets/Unit.cs
@@ -1,74 +1,145 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Quaternion = UnityEngine.Quaternion;
|
||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
|
using Vector2 = UnityEngine.Vector2;
|
||||||
|
using Vector3 = UnityEngine.Vector3;
|
||||||
|
|
||||||
public class Unit : MonoBehaviour
|
public class Unit : MonoBehaviour
|
||||||
{
|
{
|
||||||
private Planet planet;
|
private Planet planet;
|
||||||
private Vector2 planetaryVelocity; // X: rotational, Y: altitude
|
|
||||||
public float edgeWidth;
|
public float edgeWidth;
|
||||||
public Color fillColor = Color.white;
|
public Color fillColor = Color.white;
|
||||||
public Color edgeColor = Color.white;
|
public Color edgeColor = Color.white;
|
||||||
public float Size;
|
public float Size;
|
||||||
public int TreeIndex;
|
public int TreeIndex;
|
||||||
private float RotationSpeed;
|
private Vector2 _velocity = Vector3.up;
|
||||||
private float BobbingOffset;
|
private float timeOffset;
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
Render();
|
Render();
|
||||||
|
|
||||||
|
_velocity = Random.insideUnitCircle.normalized;
|
||||||
planet = GetComponentInParent<Planet>();
|
planet = GetComponentInParent<Planet>();
|
||||||
planetaryVelocity = new Vector2(0, 0)
|
timeOffset = Random.Range(0, (float)(2 * Math.PI));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 SteerTowards(Vector2 vector)
|
||||||
{
|
{
|
||||||
x = (Random.value > 0.5f ? 1 : -1) * 32 * Random.Range(0.8f, 1.2f),
|
Vector2 v = vector.normalized * 1 - _velocity;
|
||||||
};
|
var clamped = Vector2.ClampMagnitude(v, 1);
|
||||||
RotationSpeed = Random.value > 0.5f ? 1 : -1 * Random.Range(0.8f, 1.2f) * 4f;
|
Debug.Log($"SteerTowards {planet.name}/{name} Vector: {vector}, Modified Vector: {v}, Cur Velocity: {_velocity}, Clamped Vector: {clamped}");
|
||||||
BobbingOffset = Random.Range(0, (float)(2 * Math.PI));
|
return clamped;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
// Rotate itself slightly
|
var acceleration = Vector2.zero;
|
||||||
transform.Rotate(new Vector3(0, 0, Time.deltaTime * RotationSpeed));
|
|
||||||
|
|
||||||
transform.Translate(Vector3.up * Time.deltaTime);
|
// var upcomingAngle = planet.GetAngle(transform.position + (Vector3)_velocity);
|
||||||
|
// var angleTarget = planet.GetSurfacePosition(upcomingAngle, 0.4f);
|
||||||
|
// acceleration -= angleTarget;
|
||||||
|
|
||||||
// Get distance from planet
|
var targetDistance = (Mathf.Sin(Time.time * 0.5f + timeOffset) + 1) / 2f;
|
||||||
|
var surfaceTarget = planet.GetSurfacePosition(planet.GetAngle((Vector2)transform.position + _velocity), targetDistance);
|
||||||
|
var surfaceTargetVector = ((Vector2)transform.position - surfaceTarget).normalized;
|
||||||
var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f;
|
var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f;
|
||||||
var maxDistance = 1f;
|
// var vectorMultiplier = Mathf.LerpUnclamped(1f, 1.5f, 2f * Math.Abs(targetDistance - distance) / targetDistance);
|
||||||
var minDistance = 0.2f;
|
// var vectorMultiplier = Mathf.LerpUnclamped(0.5f, 1f, distance < targetDistance ? 0.3f / distance : distance / 0.2f);
|
||||||
|
surfaceTargetVector *= 1.5f;
|
||||||
|
acceleration -= surfaceTargetVector;
|
||||||
|
|
||||||
bool isTooFar = distance > maxDistance;
|
if (TreeIndex == 0)
|
||||||
bool isTooClose = distance < minDistance;
|
|
||||||
|
|
||||||
// If incorrect distance, rotate
|
|
||||||
if (isTooFar || isTooClose)
|
|
||||||
{
|
{
|
||||||
var directionToPlanet = (planet.transform.position - transform.position).normalized;
|
Debug.Log($"{planet.name} Acceleration: {acceleration}, Velocity: {_velocity}");
|
||||||
var projectionOnRight = Vector3.Dot(directionToPlanet, transform.right);
|
|
||||||
var planetOnRight = projectionOnRight < 0;
|
|
||||||
|
|
||||||
var direction = planetOnRight == isTooFar ? 1 : -1;
|
|
||||||
var turningSpeed = 200f;
|
|
||||||
if (isTooClose) turningSpeed *= 3;
|
|
||||||
else if (isTooFar) turningSpeed *= (distance - maxDistance);
|
|
||||||
transform.Rotate(new Vector3(0, 0, direction * turningSpeed * Time.deltaTime));
|
|
||||||
|
|
||||||
// var angle = Mathf.Atan2(transform.position.y, transform.position.x) * Mathf.Rad2Deg;
|
|
||||||
// angle += Random.Range(-10, 10);
|
|
||||||
// transform.rotation = Quaternion.Euler(0, 0, angle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 newVelocity = _velocity + acceleration * Time.deltaTime;
|
||||||
|
float speed = newVelocity.magnitude;
|
||||||
|
Vector2 dir = newVelocity / speed;
|
||||||
|
speed = Mathf.Clamp(speed, 0.5f, 1.5f);
|
||||||
|
_velocity = dir * speed;
|
||||||
|
|
||||||
|
var results = new List<int>();
|
||||||
|
planet.Query.Radius(planet.Tree, transform.position, 0.1f, results);
|
||||||
|
Vector2 away = Vector2.zero;
|
||||||
|
foreach (var unitIndex in results)
|
||||||
|
{
|
||||||
|
if (unitIndex == TreeIndex) continue;
|
||||||
|
var diff = (Vector2)(planet.Tree.Points[unitIndex] - transform.position);
|
||||||
|
away -= diff.normalized;
|
||||||
|
}
|
||||||
|
acceleration += away * 0.5f;
|
||||||
|
|
||||||
|
transform.eulerAngles = new Vector3(0, 0, Mathf.Rad2Deg * -Mathf.Atan2(_velocity.x, _velocity.y));
|
||||||
|
transform.position += (Vector3)_velocity * Time.deltaTime;
|
||||||
planet.Tree.Points[TreeIndex] = transform.position;
|
planet.Tree.Points[TreeIndex] = transform.position;
|
||||||
|
|
||||||
|
// var angle = planet.GetAngle(transform.position);
|
||||||
|
// var forwardAngle = planet.GetAngle(transform.forward);
|
||||||
|
|
||||||
|
// Get distance from planet
|
||||||
|
// var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f;
|
||||||
|
// var maxDistance = 1f;
|
||||||
|
// var minDistance = 0.2f;
|
||||||
|
|
||||||
|
// bool isTooFar = distance > maxDistance;
|
||||||
|
// bool isTooClose = distance < minDistance;
|
||||||
|
|
||||||
|
// var steerTarget = Vector3.zero;
|
||||||
|
|
||||||
|
// If incorrect distance, rotate
|
||||||
|
// if (isTooFar || isTooClose)
|
||||||
|
// {
|
||||||
|
// var directionToPlanet = (planet.transform.position - transform.position).normalized;
|
||||||
|
// var projectionOnRight = Vector3.Dot(directionToPlanet, transform.right);
|
||||||
|
// var planetOnRight = projectionOnRight < 0;
|
||||||
|
|
||||||
|
// steerTarget = planetOnRight ? transform.right : -transform.right;
|
||||||
|
|
||||||
|
// var direction = planetOnRight == isTooFar ? 1 : -1;
|
||||||
|
// var turningSpeed = 200f;
|
||||||
|
// if (isTooClose) turningSpeed *= 3;
|
||||||
|
// else if (isTooFar) turningSpeed *= (distance - maxDistance);
|
||||||
|
// transform.Rotate(new Vector3(0, 0, direction * turningSpeed * Time.deltaTime));
|
||||||
|
|
||||||
|
// if (steerTarget == Vector3.zero)
|
||||||
|
// steerTarget = transform.up;
|
||||||
|
|
||||||
|
|
||||||
|
// var angle = new Vector3(0, 0, Mathf.Rad2Deg * -Mathf.Atan2(steerTarget.x, steerTarget.y));
|
||||||
|
// transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, angle, Time.deltaTime * 2f);
|
||||||
|
|
||||||
|
// transform.position += transform.up * Time.deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDrawGizmos()
|
public void OnDrawGizmos()
|
||||||
{
|
{
|
||||||
// Draw a line forward
|
var surfaceTarget = planet.GetSurfacePosition(planet.GetAngle((Vector2)transform.position + _velocity), 0.4f);
|
||||||
Gizmos.color = Color.red;
|
Gizmos.color = Color.blue;
|
||||||
Gizmos.DrawLine(transform.position, transform.position + transform.up);
|
Gizmos.DrawLine(transform.position, surfaceTarget);
|
||||||
|
|
||||||
|
var velocityPosition = transform.position + (Vector3)_velocity;
|
||||||
|
Gizmos.color = Color.green;
|
||||||
|
Gizmos.DrawLine(transform.position, velocityPosition);
|
||||||
|
|
||||||
|
// Draw the angle from the planet center to the unit
|
||||||
|
// var angle = planet.GetAngle(transform.position);
|
||||||
|
// // Draw the angle from the unit's immediate forward to the planet center
|
||||||
|
// var forwardAngle = planet.GetAngle(transform.position - transform.up);
|
||||||
|
// var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f;
|
||||||
|
|
||||||
|
// Gizmos.color = Color.red;
|
||||||
|
// Gizmos.DrawLine(planet.transform.position, planet.GetSurfacePosition(angle, distance));
|
||||||
|
// Gizmos.color = Color.green;
|
||||||
|
// Gizmos.DrawLine(planet.transform.position, planet.GetSurfacePosition(forwardAngle, distance));
|
||||||
|
|
||||||
|
// // Draw a line forward
|
||||||
|
// Gizmos.color = Color.red;
|
||||||
|
// Gizmos.DrawLine(transform.position, transform.position + transform.up);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
@@ -131,4 +202,6 @@ public class Unit : MonoBehaviour
|
|||||||
lineRenderer.positionCount = mesh.vertices.Length;
|
lineRenderer.positionCount = mesh.vertices.Length;
|
||||||
lineRenderer.SetPositions(mesh.vertices);
|
lineRenderer.SetPositions(mesh.vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
15
README.md
15
README.md
@@ -13,3 +13,18 @@ A simple puzzle game about growth.
|
|||||||
- Scroll to lower/raise the total percentage of units.
|
- Scroll to lower/raise the total percentage of units.
|
||||||
- Drag to another planet, release to send units.
|
- Drag to another planet, release to send units.
|
||||||
- Until units arrive, they won't be selectable or part of the usable population on a planet.
|
- Until units arrive, they won't be selectable or part of the usable population on a planet.
|
||||||
|
|
||||||
|
## Planet Selection
|
||||||
|
|
||||||
|
1. Click on a Planet
|
||||||
|
2. Planet emits signal to Network
|
||||||
|
3. Network pulls Selection GameObject into view, overhead planet
|
||||||
|
4. Network takes all scroll key inputs, re-renders Selection gameobject to fit percentage
|
||||||
|
5. Click on another planet (to send units), or same one (to cancel)
|
||||||
|
6. Network sends signal to Planet to send units
|
||||||
|
7. Or if cancelled, Selection gameObject is hidden
|
||||||
|
8. If sent, Planet tells units to start moving to another planet
|
||||||
|
|
||||||
|
## Unit Combat
|
||||||
|
|
||||||
|
All units are placed inside datastructure
|
||||||
|
|||||||
Reference in New Issue
Block a user