130 lines
3.8 KiB
C#

using UnityEngine;
using System.Collections.Generic;
using Pathfinding.RVO;
using Pathfinding.Util;
namespace Pathfinding.Examples {
/// <summary>
/// RVO Example Scene Unit Controller.
/// Controls AIs and camera in the RVO example scene.
/// </summary>
[HelpURL("https://arongranberg.com/astar/documentation/stable/groupcontroller.html")]
public class GroupController : MonoBehaviour {
public GUIStyle selectionBox;
public bool adjustCamera = true;
Vector2 start, end;
bool wasDown = false;
List<RVOExampleAgent> selection = new List<RVOExampleAgent>();
SimulatorBurst sim;
Camera cam;
public void Start () {
cam = Camera.main;
var simu = RVOSimulator.active;
if (simu == null) {
this.enabled = false;
throw new System.Exception("No RVOSimulator in the scene. Please add one");
}
sim = simu.GetSimulator();
}
public void Update () {
if (adjustCamera) {
// Adjust camera
var bounds = sim.AgentBounds;
float max = Mathf.Max(Mathf.Max(bounds.xMax, -bounds.xMin), Mathf.Max(bounds.yMax, -bounds.yMin));
float hh = max / Mathf.Tan((cam.fieldOfView*Mathf.Deg2Rad/2.0f));
float hv = max / Mathf.Tan(Mathf.Atan(Mathf.Tan(cam.fieldOfView*Mathf.Deg2Rad/2.0f)*cam.aspect));
var yCoord = Mathf.Max(hh, hv)*1.1f;
yCoord = Mathf.Max(yCoord, 20);
yCoord = Mathf.Min(yCoord, cam.farClipPlane - 1f);
cam.transform.position = Vector3.Lerp(cam.transform.position, new Vector3(0, yCoord, 0), Time.smoothDeltaTime*2);
}
if (Input.GetKey(KeyCode.A) && Input.GetKeyDown(KeyCode.Mouse0)) {
Order();
}
}
// Update is called once per frame
void OnGUI () {
if (Event.current.type == EventType.MouseUp && Event.current.button == 0 && !Input.GetKey(KeyCode.A)) {
Select(start, end);
wasDown = false;
}
if (Event.current.type == EventType.MouseDrag && Event.current.button == 0) {
end = Event.current.mousePosition;
if (!wasDown) { start = end; wasDown = true; }
}
if (Input.GetKey(KeyCode.A)) wasDown = false;
if (wasDown) {
Rect r = Rect.MinMaxRect(Mathf.Min(start.x, end.x), Mathf.Min(start.y, end.y), Mathf.Max(start.x, end.x), Mathf.Max(start.y, end.y));
if (r.width > 4 && r.height > 4)
GUI.Box(r, "", selectionBox);
}
}
public void Order () {
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
float radsum = 0;
for (int i = 0; i < selection.Count; i++) radsum += selection[i].GetComponent<RVOController>().radius;
float radius = radsum / (Mathf.PI);
radius *= 2f;
for (int i = 0; i < selection.Count; i++) {
float deg = 2*Mathf.PI*i/selection.Count;
Vector3 p = hit.point + new Vector3(Mathf.Cos(deg), 0, Mathf.Sin(deg))*radius;
//Debug.DrawRay (p,Vector3.up*4,Color.cyan);
//Debug.Break();
selection[i].SetTarget(p);
selection[i].SetColor(GetColor(deg));
selection[i].RecalculatePath();
}
}
}
public void Select (Vector2 _start, Vector2 _end) {
_start.y = Screen.height - _start.y;
_end.y = Screen.height - _end.y;
Vector2 start = Vector2.Min(_start, _end);
Vector2 end = Vector2.Max(_start, _end);
if ((end-start).sqrMagnitude < 4*4) return;
selection.Clear();
RVOExampleAgent[] rvo = UnityCompatibility.FindObjectsByTypeSorted<RVOExampleAgent>();
for (int i = 0; i < rvo.Length; i++) {
Vector2 sp = cam.WorldToScreenPoint(rvo[i].transform.position);
if (sp.x > start.x && sp.y > start.y && sp.x < end.x && sp.y < end.y) {
selection.Add(rvo[i]);
}
}
}
/// <summary>Radians to degrees constant</summary>
const float rad2Deg = 360.0f/ ((float)System.Math.PI*2);
/// <summary>Color from an angle</summary>
public Color GetColor (float angle) {
return AstarMath.HSVToRGB(angle * rad2Deg, 0.8f, 0.6f);
}
}
}