123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- using UnityEngine;
- using System.Collections.Generic;
- using UnityEngine.Serialization;
- namespace Pathfinding.RVO {
- using Pathfinding.Util;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [AddComponentMenu("Pathfinding/Local Avoidance/RVO Controller")]
- [HelpURL("http://arongranberg.com/astar/documentation/stable/class_pathfinding_1_1_r_v_o_1_1_r_v_o_controller.php")]
- public class RVOController : VersionedMonoBehaviour {
- [SerializeField][FormerlySerializedAs("radius")]
- internal float radiusBackingField = 0.5f;
- [SerializeField][FormerlySerializedAs("height")]
- float heightBackingField = 2;
- [SerializeField][FormerlySerializedAs("center")]
- float centerBackingField = 1;
-
-
-
-
- public float radius {
- get {
- if (ai != null) return ai.radius;
- return radiusBackingField;
- }
- set {
- if (ai != null) ai.radius = value;
- radiusBackingField = value;
- }
- }
-
-
-
-
- public float height {
- get {
- if (ai != null) return ai.height;
- return heightBackingField;
- }
- set {
- if (ai != null) ai.height = value;
- heightBackingField = value;
- }
- }
-
- [Tooltip("A locked unit cannot move. Other units will still avoid it. But avoidance quality is not the best")]
- public bool locked;
-
-
-
-
-
-
-
- [Tooltip("Automatically set #locked to true when desired velocity is approximately zero")]
- public bool lockWhenNotMoving = false;
-
- [Tooltip("How far into the future to look for collisions with other agents (in seconds)")]
- public float agentTimeHorizon = 2;
-
- [Tooltip("How far into the future to look for collisions with obstacles (in seconds)")]
- public float obstacleTimeHorizon = 2;
-
-
-
-
- [Tooltip("Max number of other agents to take into account.\n" +
- "A smaller value can reduce CPU load, a higher value can lead to better local avoidance quality.")]
- public int maxNeighbours = 10;
-
-
-
-
- public RVOLayer layer = RVOLayer.DefaultAgent;
-
-
-
-
-
-
-
-
-
-
-
-
-
- [Pathfinding.EnumFlag]
- public RVOLayer collidesWith = (RVOLayer)(-1);
-
-
-
-
-
-
- [HideInInspector]
- [System.Obsolete]
- public float wallAvoidForce = 1;
-
-
-
-
-
-
-
-
-
- [HideInInspector]
- [System.Obsolete]
- public float wallAvoidFalloff = 1;
-
- [Tooltip("How strongly other agents will avoid this agent")]
- [UnityEngine.Range(0, 1)]
- public float priority = 0.5f;
-
-
-
-
- public float center {
- get {
-
- if (ai != null) return ai.height/2;
- return centerBackingField;
- }
- set {
- centerBackingField = value;
- }
- }
-
- [System.Obsolete("This field is obsolete in version 4.0 and will not affect anything. Use the LegacyRVOController if you need the old behaviour")]
- public LayerMask mask { get { return 0; } set {} }
-
- [System.Obsolete("This field is obsolete in version 4.0 and will not affect anything. Use the LegacyRVOController if you need the old behaviour")]
- public bool enableRotation { get { return false; } set {} }
-
- [System.Obsolete("This field is obsolete in version 4.0 and will not affect anything. Use the LegacyRVOController if you need the old behaviour")]
- public float rotationSpeed { get { return 0; } set {} }
-
- [System.Obsolete("This field is obsolete in version 4.0 and will not affect anything. Use the LegacyRVOController if you need the old behaviour")]
- public float maxSpeed { get { return 0; } set {} }
-
- public MovementPlane movementPlane {
- get {
- if (simulator != null) return simulator.movementPlane;
- else if (RVOSimulator.active) return RVOSimulator.active.movementPlane;
- else return MovementPlane.XZ;
- }
- }
-
- public IAgent rvoAgent { get; private set; }
-
- public Simulator simulator { get; private set; }
-
- protected Transform tr;
- [SerializeField]
- [FormerlySerializedAs("ai")]
- IAstarAI aiBackingField;
-
- protected IAstarAI ai {
- get {
- #if UNITY_EDITOR
- if (aiBackingField == null && !Application.isPlaying) aiBackingField = GetComponent<IAstarAI>();
- #endif
-
-
- if ((aiBackingField as MonoBehaviour) == null) aiBackingField = null;
- return aiBackingField;
- }
- set {
- aiBackingField = value;
- }
- }
-
- public bool debug;
-
-
-
-
- public Vector3 position {
- get {
- return To3D(rvoAgent.Position, rvoAgent.ElevationCoordinate);
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public Vector3 velocity {
- get {
-
-
-
- var dt = Time.deltaTime > 0.0001f ? Time.deltaTime : 0.02f;
- return CalculateMovementDelta(dt) / dt;
- }
- set {
- rvoAgent.ForceSetVelocity(To2D(value));
- }
- }
-
-
-
-
-
-
-
- public Vector3 CalculateMovementDelta (float deltaTime) {
- if (rvoAgent == null) return Vector3.zero;
- return To3D(Vector2.ClampMagnitude(rvoAgent.CalculatedTargetPoint - To2D(ai != null ? ai.position : tr.position), rvoAgent.CalculatedSpeed * deltaTime), 0);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public Vector3 CalculateMovementDelta (Vector3 position, float deltaTime) {
- return To3D(Vector2.ClampMagnitude(rvoAgent.CalculatedTargetPoint - To2D(position), rvoAgent.CalculatedSpeed * deltaTime), 0);
- }
-
- public void SetCollisionNormal (Vector3 normal) {
- rvoAgent.SetCollisionNormal(To2D(normal));
- }
-
-
-
-
- [System.Obsolete("Set the 'velocity' property instead")]
- public void ForceSetVelocity (Vector3 velocity) {
- this.velocity = velocity;
- }
-
-
-
-
-
- public Vector2 To2D (Vector3 p) {
- float dummy;
- return To2D(p, out dummy);
- }
-
-
-
-
-
-
-
- public Vector2 To2D (Vector3 p, out float elevation) {
- if (movementPlane == MovementPlane.XY) {
- elevation = -p.z;
- return new Vector2(p.x, p.y);
- } else {
- elevation = p.y;
- return new Vector2(p.x, p.z);
- }
- }
-
-
-
-
-
- public Vector3 To3D (Vector2 p, float elevationCoordinate) {
- if (movementPlane == MovementPlane.XY) {
- return new Vector3(p.x, p.y, -elevationCoordinate);
- } else {
- return new Vector3(p.x, elevationCoordinate, p.y);
- }
- }
- void OnDisable () {
- if (simulator == null) return;
-
-
-
- simulator.RemoveAgent(rvoAgent);
- }
- void OnEnable () {
- tr = transform;
- ai = GetComponent<IAstarAI>();
- var aiBase = ai as AIBase;
-
-
- if (aiBase != null) aiBase.FindComponents();
- if (RVOSimulator.active == null) {
- Debug.LogError("No RVOSimulator component found in the scene. Please add one.");
- enabled = false;
- } else {
- simulator = RVOSimulator.active.GetSimulator();
-
-
- if (rvoAgent != null) {
- simulator.AddAgent(rvoAgent);
- } else {
- rvoAgent = simulator.AddAgent(Vector2.zero, 0);
- rvoAgent.PreCalculationCallback = UpdateAgentProperties;
- }
- }
- }
- protected void UpdateAgentProperties () {
- var scale = tr.localScale;
- rvoAgent.Radius = Mathf.Max(0.001f, radius * scale.x);
- rvoAgent.AgentTimeHorizon = agentTimeHorizon;
- rvoAgent.ObstacleTimeHorizon = obstacleTimeHorizon;
- rvoAgent.Locked = locked;
- rvoAgent.MaxNeighbours = maxNeighbours;
- rvoAgent.DebugDraw = debug;
- rvoAgent.Layer = layer;
- rvoAgent.CollidesWith = collidesWith;
- rvoAgent.Priority = priority;
- float elevation;
-
-
-
- rvoAgent.Position = To2D(ai != null ? ai.position : tr.position, out elevation);
- if (movementPlane == MovementPlane.XZ) {
- rvoAgent.Height = height * scale.y;
- rvoAgent.ElevationCoordinate = elevation + (center - 0.5f * height) * scale.y;
- } else {
- rvoAgent.Height = 1;
- rvoAgent.ElevationCoordinate = 0;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void SetTarget (Vector3 pos, float speed, float maxSpeed) {
- if (simulator == null) return;
- rvoAgent.SetTarget(To2D(pos), speed, maxSpeed);
- if (lockWhenNotMoving) {
- locked = speed < 0.001f;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void Move (Vector3 vel) {
- if (simulator == null) return;
- var velocity2D = To2D(vel);
- var speed = velocity2D.magnitude;
- rvoAgent.SetTarget(To2D(ai != null ? ai.position : tr.position) + velocity2D, speed, speed);
- if (lockWhenNotMoving) {
- locked = speed < 0.001f;
- }
- }
-
-
-
-
- [System.Obsolete("Use transform.position instead, the RVOController can now handle that without any issues.")]
- public void Teleport (Vector3 pos) {
- tr.position = pos;
- }
- void OnDrawGizmos () {
- tr = transform;
-
- if (ai == null) {
- var color = AIBase.ShapeGizmoColor * (locked ? 0.5f : 1.0f);
- var pos = transform.position;
- var scale = tr.localScale;
- if (movementPlane == MovementPlane.XY) {
- Draw.Gizmos.Cylinder(pos, Vector3.forward, 0, radius * scale.x, color);
- } else {
- Draw.Gizmos.Cylinder(pos + To3D(Vector2.zero, center - height * 0.5f) * scale.y, To3D(Vector2.zero, 1), height * scale.y, radius * scale.x, color);
- }
- }
- }
- protected override int OnUpgradeSerializedData (int version, bool unityThread) {
- if (version <= 1) {
- if (!unityThread) return -1;
- if (transform.localScale.y != 0) centerBackingField /= Mathf.Abs(transform.localScale.y);
- if (transform.localScale.y != 0) heightBackingField /= Mathf.Abs(transform.localScale.y);
- if (transform.localScale.x != 0) radiusBackingField /= Mathf.Abs(transform.localScale.x);
- }
- return 2;
- }
- }
- }
|