/// <summary> /// 指定したNestElementをNestSystemに登録し、付近のNestElementのノードと自動的に接続する。 /// 自動接続は現在の建築システムの仕様に基づき、一か所だけで行われます。(変更される可能性あり) /// </summary> /// <param name="target"></param> /// <param name="needToBeConnected">スナップによってほかのNestElementに接続できない場合、設置不能として判定する。</param> /// <returns>配置が成功したかどうか。</returns> public bool PlaceElementWithAutoConnect(NestElement target, bool needToBeConnected = true, float autoConnectThresholdDistance = 0.01f) { GetSnappableNode(target, out NestPathNode originNode, out NestPathNode targetNode, out float distance); if (distance <= autoConnectThresholdDistance) { //自動接続を行う if (!IsPlaceable(target, targetNode.Host)) { return(false); } Host.ConnectElements(originNode, targetNode); } else { if (needToBeConnected) { return(false); } if (!IsPlaceable(target)) { return(false); } } Host.RegisterNestElementToGameContext(target); return(true); }
/// <summary> /// 自動スナップを行った際に吸引されるノードを取得する。 /// </summary> /// <param name="target"></param> /// <param name="originNode"></param> /// <param name="targetNode"></param> /// <param name="distance"></param> public void GetSnappableNode(NestElement target, out NestPathNode originNode, out NestPathNode targetNode, out float distance) { var nodes = Host.NestElements.Where(e => e != target).SelectMany(e => e.GetNodes()).Where(n => n.IsExposed); NestPathNode argMinDistanceOrigin = null; NestPathNode argMinDistance = null; float minSqrDistance = float.MaxValue; foreach (var n in target.GetNodes().Where(n => n.IsExposed)) { var connectables = nodes.Where(other => other.IsExposed && other.IsConnectable(n) && n.IsConnectable(other)); foreach (var other in connectables) { float sqrDistance = (other.WorldPosition - n.WorldPosition).sqrMagnitude; if (sqrDistance < minSqrDistance) { argMinDistanceOrigin = n; minSqrDistance = sqrDistance; argMinDistance = other; } } } originNode = argMinDistanceOrigin; targetNode = argMinDistance; distance = Mathf.Sqrt(minSqrDistance); }
/// <summary> /// NestElementが現在の位置に設置できるかどうかを取得する。 /// </summary> /// <param name="target"></param> /// <returns></returns> public bool CanPlaceable(NestElement target) { var cf = new ContactFilter2D() { layerMask = LayerMask.GetMask("NestElement"), }; return(Physics2D.OverlapCollider(target.GetBlockingShape(), cf, overlapResult) == 0); }
public NestPathNode(NestElement host, Vector2 localPosition, string name = "") { Host = host; LocalPosition = localPosition; if (!string.IsNullOrEmpty(name)) { Name = name; IsExposed = true; } }
/// <summary> /// NestElementが現在の位置に設置できるかどうかを取得する。 /// 【注意】NestElementの位置を更新した直後、同一フレーム内で呼び出すと、移動前の位置で重複判定が行われるようです。結果正しい結果が得られないことがあります。 /// </summary> /// <param name="target"></param> /// <returns></returns> public bool IsPlaceable(NestElement target) { var cf = new ContactFilter2D() { useLayerMask = true, layerMask = LayerMask.GetMask("NestElement"), }; int res = target.GetBlockingShape().OverlapCollider(cf, overlapResult); //Debug.Log(res, overlapResult[0]); return(res == 0); }
public NestPathElementEdge(IEnumerable <NestElement> elements, NestPathElementEdgeData data) { Data = data; NestElement elementA = null; NestElement elementB = null; foreach (var e in elements) { if (e.Data.Guid == data.ElementGuidA) { elementA = e; } else if (e.Data.Guid == data.ElementGuidB) { elementB = e; } } if (elementA == default || elementB == default) { throw new ArgumentException("指定されたNestElementが見つかりませんでした。"); } var nodeA = elementA.GetNodes().Where(n => n.IsExposed).FirstOrDefault(n => n.Name == data.NodeNameA); if (nodeA == default) { throw new ArgumentException("指定されたNestPathNodeが見つかりませんでした。"); } var nodeB = elementB.GetNodes().Where(n => n.IsExposed).FirstOrDefault(n => n.Name == data.NodeNameB); if (nodeB == default) { throw new ArgumentException("指定されたNestPathNodeが見つかりませんでした。"); } if (!nodeA.IsConnectable(nodeB)) { throw new ArgumentException("指定されたNestPathNodeどうしは接続を禁止しています。"); } if (!nodeB.IsConnectable(nodeA)) { throw new ArgumentException("指定されたNestPathNodeどうしは接続を禁止しています。"); } A = nodeA; B = nodeB; RegisterToNode(); }
/// <summary> /// 指定したNestElementに関して、付近のノードにスナップした後の座標を取得する /// </summary> /// <param name="target">スナップさせるNestElement</param> /// <param name="thresholdDistance">スナップの基準となる</param> /// <returns></returns> public Vector2 GetSnappedPosition(NestElement target, float thresholdDistance = 0.2f) { GetSnappableNode(target, out NestPathNode originNode, out NestPathNode targetNode, out float distance); if (targetNode == null) { return(target.transform.position); } if (distance > thresholdDistance) { return(target.transform.position); } return((Vector2)target.transform.position + (targetNode.WorldPosition - originNode.WorldPosition)); }
/// <summary> /// NestElementが現在の位置に設置できるかどうかを取得する。 /// 【注意】NestElementの位置を更新した直後、同一フレーム内で呼び出すと、移動前の位置で重複判定が行われるようです。結果正しい結果が得られないことがあります。 /// </summary> /// <param name="target">設置するNestElement</param> /// <param name="ignore">スナップ対象のNestElement。重複していても無視される。</param> /// <returns></returns> public bool IsPlaceable(NestElement target, NestElement ignore = null) { var cf = new ContactFilter2D() { useLayerMask = true, layerMask = LayerMask.GetMask("NestElement"), }; int res = target.GetBlockingShape().OverlapCollider(cf, overlapResult); //スナップ対象のNestElementとの重複を無視します。グリッド上でしか接続を行わない現状ならこういう施策が可能ですが、そうでない場合は不正な形状の巣を形成する可能性があります if (ignore != null && res == 1 && overlapResult[0] == ignore.GetBlockingShape()) { return(true); } return(res == 0); }
/// <summary> /// 指定したNestElementをNestSystemに登録し、付近のNestElementのノードと自動的に接続する。 /// 自動接続は現在の建築システムの仕様に基づき、一か所だけで行われます。(変更される可能性あり) /// </summary> /// <param name="target"></param> /// <returns>配置が成功したかどうか。</returns> public bool PlaceElementWithAutoConnect(NestElement target, float autoConnectThresholdDistance = 0.01f) { if (!CanPlaceable(target)) { return(false); } Host.AddNestElement(target); GetSnappableNode(target, out NestPathNode originNode, out NestPathNode targetNode, out float distance); if (distance <= autoConnectThresholdDistance) { //自動接続を行う Host.ConnectElements(originNode, targetNode); } return(true); }
/// <summary> /// 外部で生成したNestElementをNestSystemに登録する。 /// あらかじめNestElement.Initializeで適切なNestElementDataが注入されている必要がある。 /// </summary> /// <param name="element"></param> public void RegisterNestElementToGameContext(NestElement element) { if (element.Data == null) { throw new ArgumentException("NestElementDataが設定されていません。あらかじめ適切なNestElementDataを注入してください。"); } if (Data.Structure.NestElements.Contains(element.Data)) { throw new ArgumentException("指定されたNestElementのDataはすでに登録されています。"); } if (!nestElements.Contains(element)) { nestElements.Add(element); } Data.Structure.NestElements.Add(element.Data); }
/// <summary> /// InstantiateNestElement()で追加したNestElementを削除します。 /// セーブデータからNestElementを削除し、関連するElement間接続を破棄します。 /// GameObjectの破棄までは担当しないので、呼び出し側でDestroyしてください /// </summary> /// <param name="element"></param> public void RemoveNestElement(NestElement element) { if (Data.Structure.NestElements.Contains(element.Data)) { Data.Structure.NestElements.Remove(element.Data); nestElements.Remove(element); //Element間接続がある場合はその接続も破棄 var l = elementEdges.Where(e => e.A.Host == element || e.B.Host == element).ToList(); foreach (var e in l) { if (Data.Structure.ElementEdges.Contains(e.Data)) { Data.Structure.ElementEdges.Remove(e.Data); } e.Clear(); elementEdges.Remove(e); } } }
public void PushDown() { position = Input.mousePosition; position.z = 10f; screenToWorldPointPosition = Camera.main.ScreenToWorldPoint(position); //Listでシーン内にあるNestElementをすべて取得 var list = NestSystem.Instance.NestElements; //貯蓄庫と女王の部屋の数を数えます for (int i = 0; i < list.Count; i++) { if (list[i].GetType().Name == "StoreRoom") { Chochikukonum++; } else if (list[i].GetType().Name == "QueenRoom")//仮の名前 { QweenRoomNum++; } } //出現させるNestElementのデータを保存 NestElementData data; if (NestName == "IShapeVertical") { data = new IShapeRoadData(EnumRoadHVDirection.Vertical) { IsUnderConstruction = true }; } else if (NestName == "IShapeHorizontal") { data = new IShapeRoadData(EnumRoadHVDirection.Horizontal) { IsUnderConstruction = true }; } else if (NestName == "LShapeBottom") { data = new LShapeRoadData(EnumRoadDirection.Bottom) { IsUnderConstruction = true }; } else if (NestName == "LShapeRight") { data = new LShapeRoadData(EnumRoadDirection.Right) { IsUnderConstruction = true }; } else if (NestName == "LShapeTop") { data = new LShapeRoadData(EnumRoadDirection.Top) { IsUnderConstruction = true }; } else if (NestName == "LShapeLeft") { data = new LShapeRoadData(EnumRoadDirection.Left) { IsUnderConstruction = true }; } else if (NestName == "TShapeBottom") { data = new TShapeRoadData(EnumRoadDirection.Bottom) { IsUnderConstruction = true }; } else if (NestName == "TShapeRight") { data = new TShapeRoadData(EnumRoadDirection.Right) { IsUnderConstruction = true }; } else if (NestName == "TShapeTop") { data = new TShapeRoadData(EnumRoadDirection.Top) { IsUnderConstruction = true }; } else if (NestName == "TShapeLeft") { data = new TShapeRoadData(EnumRoadDirection.Left) { IsUnderConstruction = true }; } else if (NestName == "Chochikubeya" && Chochikukonum == 0) { //data = new ChochikubeyaData(); data = new StoreRoomData() { IsUnderConstruction = true }; } else if (NestName == "QueenRoom" && QweenRoomNum == 0) { //data = new QweenAntRoomData(); data = new QueenRoomData() { IsUnderConstruction = true }; } else if (NestName == "Cross") { data = new CrossShapeRoadData() { IsUnderConstruction = true }; } else { data = new CrossShapeRoadData(); } //貯蓄庫と女王の部屋が指定されたときシーン内に巣でにそれらの部屋があるなら出せない if ((NestName == "Chochikubeya" && Chochikukonum != 0) || (NestName == "QueenRoom" && QweenRoomNum != 0)) { GetComponent <EventTrigger>().triggers.Clear(); } else { nestelement = NestSystem.Instance.InstantiateNestElement(data, false, false); nestelement.transform.position = screenToWorldPointPosition; (nestelement as NestBuildableElement).SetImage(EnumNestImage.Spector); } }
public void PushDown() { position = Input.mousePosition; position.z = 10f; screenToWorldPointPosition = Camera.main.ScreenToWorldPoint(position); //Listでシーン内にあるNestElementをすべて取得 var list = NestSystem.Instance.NestElements; //貯蓄庫と女王の部屋の数を数えます for (int i = 0; i < list.Count; i++) { if (list[i].gameObject.name == "Chochikubeya(Clone)") { Chochikukonum++; } else if (list[i].gameObject.name == "QweenAntRoom(Clone)")//仮の名前 { QweenRoomNum++; } } //出現させるNestElementのデータを保存 NestElementData data; if (NestName == "IShapeVertical") { data = new IShapeRoadData(EnumRoadHVDirection.Vertical); } else if (NestName == "IShapeHorizontal") { data = new IShapeRoadData(EnumRoadHVDirection.Horizontal); } else if (NestName == "LShapeBottom") { data = new LShapeRoadData(EnumRoadDirection.Bottom); } else if (NestName == "LShapeRight") { data = new LShapeRoadData(EnumRoadDirection.Right); } else if (NestName == "LShapeTop") { data = new LShapeRoadData(EnumRoadDirection.Top); } else if (NestName == "LShapeLeft") { data = new LShapeRoadData(EnumRoadDirection.Left); } else if (NestName == "TShapeBottom") { data = new TShapeRoadData(EnumRoadDirection.Bottom); } else if (NestName == "TShapeRight") { data = new TShapeRoadData(EnumRoadDirection.Right); } else if (NestName == "TShapeTop") { data = new TShapeRoadData(EnumRoadDirection.Top); } else if (NestName == "TShapeLeft") { data = new TShapeRoadData(EnumRoadDirection.Left); } else if (NestName == "Chochikubeya") { //data = new ChochikubeyaData(); data = new CrossShapeRoadData(); } else if (NestName == "QweenAntRoom") { //data = new QweenAntRoomData(); data = new CrossShapeRoadData(); } else if (NestName == "Cross") { data = new CrossShapeRoadData(); } else { data = new CrossShapeRoadData(); } //貯蓄庫と女王の部屋が指定されたときシーン内に巣でにそれらの部屋があるなら出せない if ((NestName == "Chochikubeya" && Chochikukonum != 0) || (NestName == "QweenAntRoom" && QweenRoomNum != 0)) { } else { nestelement = NestSystem.Instance.InstantiateNestElement(data); nestelement.transform.position = screenToWorldPointPosition; } }
public NestPathRoomNode(NestElement host, Vector2 localPosition, string name = "") : base(host, localPosition, name) { }