using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; using HighlightPlus; public class SelectionManager : Singleton { //物体列表 public List Sets = new List(); //启用选择 public bool CanMakeSelections = true; //多选 public KeyCode keyMultiselect = KeyCode.LeftControl; //减选 public KeyCode keyDeselect = KeyCode.LeftAlt; //框选 public KeyCode DracRectKey = KeyCode.LeftShift; private static List selectedGameObjects = new List(); private bool isSelecting = false; private Vector3 mousePosition; public GameObject SingleObject; //可选择物体 private struct SelectableObject { public GameObject gameObject; public SelectableUnit selectable; public bool isActive; } private void Start() { //检测相机 if (!Camera.main) Debug.Log("The SelectionManager requires a camera with the tag 'MainCamera'"); ClearSelection(); } private void Update() { if (!Camera.main) return; if (Sets.Count > 0) { //删除不存在的选定对象 selectedGameObjects = selectedGameObjects.Where(i => i.gameObject != null).ToList(); if (CanMakeSelections) { // 如果按下鼠标左键, 保存鼠标位置并开始选择 if (Input.GetMouseButtonDown(0)) { isSelecting = true; mousePosition = Input.mousePosition; } if (Input.GetMouseButtonUp(0)) { if (!EventSystem.current.IsPointerOverGameObject()) { if (isSelecting) { //如果按住Shift键,则不删除已选内容 if (!(Input.GetKey(keyMultiselect)) && !(Input.GetKey(keyDeselect))) ClearSelection(); List newSelectedObjects = new List(); bool isFiltered = false; if (!isFiltered && newSelectedObjects.Count == 0) { newSelectedObjects.AddRange(Utils.FindGameObjectsInList(Sets)); } if (Input.GetKey(DracRectKey)) { foreach (GameObject selectedObject in newSelectedObjects) { if (IsWithinSelectionBounds(selectedObject)) { ParseGameObjectForSelection(selectedObject); } } } } isSelecting = false; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out RaycastHit selectionHit)) { ParseGameObjectForSelection(selectionHit.transform.gameObject); } } } } } } #region Private Methods /// /// 减选物体 /// /// void DetachSelection(SelectableObject selectedObject) { if (selectedObject.gameObject != null) { selectedObject.gameObject.GetComponent().highlighted = false; SingleObject = null; if (selectedObject.selectable) { selectedObject.selectable.OnEndSelection(); } } } /// /// 选择物体 /// /// private void ParseGameObjectForSelection(GameObject sender) { var validObject = sender.GetComponent(); if (validObject) { bool containsObject = false; List objectsToRemove = new List(); for (int x = 0; x < selectedGameObjects.Count; x++) { SelectableObject selectedObject = selectedGameObjects[x]; if (selectedObject.gameObject == sender) { containsObject = true; selectedObject.isActive = true; } selectedGameObjects[x] = selectedObject; if (Input.GetKey(keyDeselect) && selectedObject.gameObject == sender) { DetachSelection(selectedObject); objectsToRemove.Add(selectedObject); } } selectedGameObjects = selectedGameObjects.Except(objectsToRemove).ToList(); if (!containsObject && !Input.GetKey(keyDeselect)) { var selectable = sender.GetComponent(); if (selectable && selectable != selectable.playerOwned) return; switch (sender.GetComponent().selectMode) { case SelectMode.Single: var selected1 = new SelectableObject { gameObject = sender, isActive = true }; if (selectable) { selected1.selectable = selectable; selected1.selectable.OnBeginSelection(); } selectedGameObjects.Add(selected1); SingleObject = sender; break; case SelectMode.Multiple: foreach (Transform t in sender.transform.parent) { var selected2 = new SelectableObject { gameObject = t.gameObject, isActive = true }; if (selectable) { selected2.selectable = selectable; selected2.selectable.OnBeginSelection(); } selectedGameObjects.Add(selected2); SingleObject = sender; } break; } //高亮显示 for (int i = 0; i < selectedGameObjects.Count; i++) { selectedGameObjects[i].gameObject.GetComponent().highlighted = true; } } } } void OnGUI() { if (MainMenu.Instance.MenuMode != MainMenuMode.体验漫游) { if (isSelecting && Input.GetKey(DracRectKey)) { // Create a rect from both mouse positions var rect = Utils.GetScreenRect(mousePosition, Input.mousePosition); Utils.DrawScreenRect(rect, new Color(0.2f, 0.8f, 0.2f, 0.25f)); Utils.DrawScreenRectBorder(rect, 1, new Color(0.2f, 0.8f, 0.2f)); } } } /// /// 选择范围 /// /// /// private bool IsWithinSelectionBounds(GameObject gameObject) { if (!isSelecting) return false; var camera = Camera.main; var viewportBounds = Utils.GetViewportBounds(camera, mousePosition, Input.mousePosition); return viewportBounds.Contains(camera.WorldToViewportPoint(gameObject.transform.position)); } #endregion #region Public Methods /// /// 返回选择对象的列表 /// /// public static List GetSelectedObjects() { return selectedGameObjects.Select(i => i.gameObject).ToList(); } /// /// 将物体添加到选择列表 /// /// public void AddGameObjectToSelection(GameObject newObject) { ParseGameObjectForSelection(newObject); } /// /// 从选择列表中移除物体 /// /// public void RemoveGameObjectFromSelection(GameObject removedObject) { foreach (SelectableObject selectedObject in selectedGameObjects) { if (selectedObject.gameObject == removedObject) { DetachSelection(selectedObject); selectedGameObjects.Remove(selectedObject); } } } /// /// 清空选择 /// public void ClearSelection() { foreach (SelectableObject selectedObject in selectedGameObjects) { DetachSelection(selectedObject); } selectedGameObjects.Clear(); } /// /// 检查物体是否被选择 /// /// /// public static bool IsContains(GameObject go) { var obj = GetSelectedObjects().Find(o => o == go); return obj ? true : false; } #endregion }