using UnityEngine; using System.Collections.Generic; namespace PathBerserker2d { /// /// Creates links to interconnect a collection. /// /// /// Consists of a list of points. /// At runtime a link is generated for each point to connect it with each other point. /// This is a convenience component. It drastically reduces the amount of work required to setup an elevator or ladder for example. /// /// Otherwise it functions and behaves the same as a NavLink. /// Reference the documentation for NavLink for further details. /// [AddComponentMenu("PathBerserker2d/Nav Link Cluster")] public sealed class NavLinkCluster : BaseNavLink { internal enum PointTraversalType { Exit, Entry, Both } internal LinkPoint[] LinkPoints => linkPoints; [SerializeField] internal LinkPoint[] linkPoints = new LinkPoint[] { new LinkPoint(Vector2.left * 2), new LinkPoint(Vector2.right * 2) }; private List linkInstances; #region UNITY private void OnEnable() { if (linkInstances == null) linkInstances = new List(); if (autoMap) UpdateMapping(); } private void OnDisable() { foreach (var li in linkInstances) li.RemoveFromWorld(); } #endregion /// /// Update the mapping for all link instances. Call after link positions have been changed. /// public void UpdateMapping() { NavSegmentPositionPointer navStart, navGoal; int instanceCounter = 0; foreach (var startPoint in linkPoints) { if (startPoint.traversalType == PointTraversalType.Exit) continue; Vector2 worldStart = transform.TransformPoint(startPoint.point); foreach (var goalPoint in linkPoints) { if (goalPoint.traversalType == PointTraversalType.Entry || goalPoint.point == startPoint.point) continue; Vector2 worldGoal = transform.TransformPoint(goalPoint.point); if (instanceCounter >= linkInstances.Count) { linkInstances.Add(new NavLinkInstance(this)); } var linkInstance = linkInstances[instanceCounter++]; if (PBWorld.TryMapPointWithStaged(worldStart, out navStart) && PBWorld.TryMapPointWithStaged(worldGoal, out navGoal)) { linkInstance.UpdateMapping(navStart, navGoal, worldStart, worldGoal); linkInstance.AddToWorld(); } else { linkInstance.RemoveFromWorld(); } } } } /// /// Set link instances to be traversable based on their start and end points. /// /// Determines whether to enable or disable the given link instance. Link instance is given as its start and goal position. public void SetLinksTraversable(System.Func traversableFunc) { foreach (var link in linkInstances) { if (link.IsAdded) link.IsTraversable = traversableFunc(link.Start.Position, link.Goal.Position); } } [System.Serializable] internal struct LinkPoint { [SerializeField] public Vector2 point; [SerializeField] public PointTraversalType traversalType; public LinkPoint(Vector2 point) { this.point = point; this.traversalType = PointTraversalType.Both; } } } }