您好,登錄后才能下訂單哦!
這篇文章主要介紹Unity3D如何實現甜品消消樂游戲,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
解釋:
之前用的ScreenToGif錄屏,因為上傳的.gif最大不超過5MB,所以做了不少刪幀和色彩弱化等處理,這才導致色彩看上去不是很舒服,不要盯著它看太久,不然會有點難受...
由于使用的素材是現成的,沒有花時間精力去扒,所以細節方面可能不是做的很好。
說明:
這次的甜品消消樂雖然看上去好像挺簡單普通的,但是相對于之前的坦克大戰,某種程度上已然提升難度了,歸類到了算法類層的游戲。
拉到最后看代碼你就能理解我的意思了,坦克大戰的所有代碼加起來還不如消消樂兩個類的代碼多,其他各種細節,坦克也只能望其項背...
如果坦克大戰是低階的,那么甜品消消樂就是中階的,有著不少的動畫效果和交互(碰撞檢測和甜品的控制等),游戲運行的所有機制和功能需要在模型層上進行操控。
這次的消消樂需要一定的邏輯思維、算法基礎、Unity綜合能力和編程基礎。
方正粗圓的字體和布靈布靈的閃光特效會賦予游戲可愛風的氛圍感。
我們把物體分為模型層和渲染層,這樣它們各司其職,降低工作的耦合性。
由于12.29日放假前還剩 兩門課設答辯和一門考試,不足之處以后再補充...
游戲資源(音頻、圖片、特效等)
場景和包(動畫。渲染精靈和控制器等)
游戲腳本(UI、Runtime等)
......太多了,只選擇了部分作為展示
在Gizmos目錄下,可以找到對應按鈕隱藏攝像機,這樣處理場景的時候會舒服很多
Clone都放上會有些雜亂,都刪掉,只放了一個背景圖
開始按鈕(玩家通過點擊開始按鈕,進入新的一局游戲)
重玩按鈕(玩家可以及時返回開始界面進行相應操作)
時鐘(顯示游戲剩余時間,一局游戲初始化時間是60s)
計分板(顯示當前游戲得分)
普通甜品(甜甜圈、糖果、起司...至少同時有3個在同一排或同一列時,可以消除)
特殊甜品(一定條件下會觸發2種特殊甜品道具,一種是帶有左右晃動特效的甜品,可以消除一整排的甜品;另一種是帶有上下晃動特效的甜品,可以消除一整列的甜品)
積分面板(游戲時間結束后,會用類似飛躍的動畫效果產生得分界面窗口,逐漸變大顯示,最終定格。點擊重玩立即開始下一局游戲,叉掉返回開始界面)
點擊開始進入游戲,每一局新開的游戲設時60s(可以根據需要調整),用最快的速度消除出現在同一行或者同一列的相同的甜點會獲得相應積分。
盡量用最優的策略使得一定時間內的積分最大化(不過這一點,游戲玩熟了可能才能漸漸領悟,屬于大師級別的操作了。可以用ACM相關算法寫個外掛,應該是用動態規劃算法處理)。
當符合特定消除條件的甜品被消除后,會隨機產生兩類特殊甜品的一種,這個甜品會瞬間清除一整行或者一整列的甜品,使得積分暴增。
相同時間內積分高者或者相同積分用時少者優勝。
小蝦選用的是Unity個人版,采用的是Unity一個較新的版本-2021.1.16,這里建議小伙伴們下載和教程相同版本的,不然真的會有可能遇到卡點消耗心情哈。
可以和我一樣在Unity Hub里面安裝,Hub感覺挺好用的。
但是每次重啟后都要手動激活許可證,這是真的挺煩的。
小蝦在這里主要介紹部分核心代碼實現,想知道其他部分實現的小伙伴在下方留言,我再添加~
UI-PropertyDrawers-MenuOptions.cs
using System; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using UnityEngine.SceneManagement; using UnityEditor.Experimental.SceneManagement; namespace UnityEditor.UI { /// <summary> /// This script adds the UI menu options to the Unity Editor. /// </summary> static internal class MenuOptions { private const string kUILayerName = "UI"; private const string kStandardSpritePath = "UI/Skin/UISprite.psd"; private const string kBackgroundSpritePath = "UI/Skin/Background.psd"; private const string kInputFieldBackgroundPath = "UI/Skin/InputFieldBackground.psd"; private const string kKnobPath = "UI/Skin/Knob.psd"; private const string kCheckmarkPath = "UI/Skin/Checkmark.psd"; private const string kDropdownArrowPath = "UI/Skin/DropdownArrow.psd"; private const string kMaskPath = "UI/Skin/UIMask.psd"; static private DefaultControls.Resources s_StandardResources; static private DefaultControls.Resources GetStandardResources() { if (s_StandardResources.standard == null) { s_StandardResources.standard = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePath); s_StandardResources.background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePath); s_StandardResources.inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>(kInputFieldBackgroundPath); s_StandardResources.knob = AssetDatabase.GetBuiltinExtraResource<Sprite>(kKnobPath); s_StandardResources.checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>(kCheckmarkPath); s_StandardResources.dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>(kDropdownArrowPath); s_StandardResources.mask = AssetDatabase.GetBuiltinExtraResource<Sprite>(kMaskPath); } return s_StandardResources; } private class DefaultEditorFactory : DefaultControls.IFactoryControls { public static DefaultEditorFactory Default = new DefaultEditorFactory(); public GameObject CreateGameObject(string name, params Type[] components) { return ObjectFactory.CreateGameObject(name, components); } } private class FactorySwapToEditor : IDisposable { DefaultControls.IFactoryControls factory; public FactorySwapToEditor() { factory = DefaultControls.factory; DefaultControls.factory = DefaultEditorFactory.Default; } public void Dispose() { DefaultControls.factory = factory; } } private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform) { SceneView sceneView = SceneView.lastActiveSceneView; // Couldn't find a SceneView. Don't set position. if (sceneView == null || sceneView.camera == null) return; // Create world space Plane from canvas position. Vector2 localPlanePosition; Camera camera = sceneView.camera; Vector3 position = Vector3.zero; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out localPlanePosition)) { // Adjust for canvas pivot localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x; localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y; localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x); localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y); // Adjust for anchoring position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x; position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y; Vector3 minLocalPosition; minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x; minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y; Vector3 maxLocalPosition; maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x; maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y; position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x); position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y); } itemTransform.anchoredPosition = position; itemTransform.localRotation = Quaternion.identity; itemTransform.localScale = Vector3.one; } private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand) { GameObject parent = menuCommand.context as GameObject; bool explicitParentChoice = true; if (parent == null) { parent = GetOrCreateCanvasGameObject(); explicitParentChoice = false; // If in Prefab Mode, Canvas has to be part of Prefab contents, // otherwise use Prefab root instead. PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null && !prefabStage.IsPartOfPrefabContents(parent)) parent = prefabStage.prefabContentsRoot; } if (parent.GetComponentsInParent<Canvas>(true).Length == 0) { // Create canvas under context GameObject, // and make that be the parent which UI element is added under. GameObject canvas = MenuOptions.CreateNewUI(); Undo.SetTransformParent(canvas.transform, parent.transform, ""); parent = canvas; } GameObjectUtility.EnsureUniqueNameForSibling(element); SetParentAndAlign(element, parent); if (!explicitParentChoice) // not a context click, so center in sceneview SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>()); // This call ensure any change made to created Objects after they where registered will be part of the Undo. Undo.RegisterFullObjectHierarchyUndo(parent == null ? element : parent, ""); // We have to fix up the undo name since the name of the object was only known after reparenting it. Undo.SetCurrentGroupName("Create " + element.name); Selection.activeGameObject = element; } private static void SetParentAndAlign(GameObject child, GameObject parent) { if (parent == null) return; Undo.SetTransformParent(child.transform, parent.transform, ""); RectTransform rectTransform = child.transform as RectTransform; if (rectTransform) { rectTransform.anchoredPosition = Vector2.zero; Vector3 localPosition = rectTransform.localPosition; localPosition.z = 0; rectTransform.localPosition = localPosition; } else { child.transform.localPosition = Vector3.zero; } child.transform.localRotation = Quaternion.identity; child.transform.localScale = Vector3.one; SetLayerRecursively(child, parent.layer); } private static void SetLayerRecursively(GameObject go, int layer) { go.layer = layer; Transform t = go.transform; for (int i = 0; i < t.childCount; i++) SetLayerRecursively(t.GetChild(i).gameObject, layer); } // Graphic elements [MenuItem("GameObject/UI/Text", false, 2000)] static public void AddText(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateText(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } [MenuItem("GameObject/UI/Image", false, 2001)] static public void AddImage(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateImage(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } [MenuItem("GameObject/UI/Raw Image", false, 2002)] static public void AddRawImage(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateRawImage(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } // Controls // Button and toggle are controls you just click on. [MenuItem("GameObject/UI/Button", false, 2030)] static public void AddButton(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateButton(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } [MenuItem("GameObject/UI/Toggle", false, 2031)] static public void AddToggle(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateToggle(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } // Slider and Scrollbar modify a number [MenuItem("GameObject/UI/Slider", false, 2033)] static public void AddSlider(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateSlider(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } [MenuItem("GameObject/UI/Scrollbar", false, 2034)] static public void AddScrollbar(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateScrollbar(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } // More advanced controls below [MenuItem("GameObject/UI/Dropdown", false, 2035)] static public void AddDropdown(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateDropdown(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } [MenuItem("GameObject/UI/Input Field", false, 2036)] public static void AddInputField(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateInputField(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } // Containers [MenuItem("GameObject/UI/Canvas", false, 2060)] static public void AddCanvas(MenuCommand menuCommand) { var go = CreateNewUI(); SetParentAndAlign(go, menuCommand.context as GameObject); if (go.transform.parent as RectTransform) { RectTransform rect = go.transform as RectTransform; rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.anchoredPosition = Vector2.zero; rect.sizeDelta = Vector2.zero; } Selection.activeGameObject = go; } [MenuItem("GameObject/UI/Panel", false, 2061)] static public void AddPanel(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreatePanel(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); // Panel is special, we need to ensure there's no padding after repositioning. RectTransform rect = go.GetComponent<RectTransform>(); rect.anchoredPosition = Vector2.zero; rect.sizeDelta = Vector2.zero; } [MenuItem("GameObject/UI/Scroll View", false, 2062)] static public void AddScrollView(MenuCommand menuCommand) { GameObject go; using (new FactorySwapToEditor()) go = DefaultControls.CreateScrollView(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); } // Helper methods static public GameObject CreateNewUI() { // Root for the UI var root = ObjectFactory.CreateGameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster)); root.layer = LayerMask.NameToLayer(kUILayerName); Canvas canvas = root.GetComponent<Canvas>(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; // Works for all stages. StageUtility.PlaceGameObjectInCurrentStage(root); bool customScene = false; PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { Undo.SetTransformParent(root.transform, prefabStage.prefabContentsRoot.transform, ""); customScene = true; } Undo.SetCurrentGroupName("Create " + root.name); // If there is no event system add one... // No need to place event system in custom scene as these are temporary anyway. // It can be argued for or against placing it in the user scenes, // but let's not modify scene user is not currently looking at. if (!customScene) CreateEventSystem(false); return root; } [MenuItem("GameObject/UI/Event System", false, 2100)] public static void CreateEventSystem(MenuCommand menuCommand) { GameObject parent = menuCommand.context as GameObject; CreateEventSystem(true, parent); } private static void CreateEventSystem(bool select) { CreateEventSystem(select, null); } private static void CreateEventSystem(bool select, GameObject parent) { StageHandle stage = parent == null ? StageUtility.GetCurrentStageHandle() : StageUtility.GetStageHandle(parent); var esys = stage.FindComponentOfType<EventSystem>(); if (esys == null) { var eventSystem = ObjectFactory.CreateGameObject("EventSystem"); if (parent == null) StageUtility.PlaceGameObjectInCurrentStage(eventSystem); else SetParentAndAlign(eventSystem, parent); esys = ObjectFactory.AddComponent<EventSystem>(eventSystem); ObjectFactory.AddComponent<StandaloneInputModule>(eventSystem); Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name); } if (select && esys != null) { Selection.activeGameObject = esys.gameObject; } } // Helper function that returns a Canvas GameObject; preferably a parent of the selection, or other existing Canvas. static public GameObject GetOrCreateCanvasGameObject() { GameObject selectedGo = Selection.activeGameObject; // Try to find a gameobject that is the selected GO or one if its parents. Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null; if (IsValidCanvas(canvas)) return canvas.gameObject; // No canvas in selection or its parents? Then use any valid canvas. // We have to find all loaded Canvases, not just the ones in main scenes. Canvas[] canvasArray = StageUtility.GetCurrentStageHandle().FindComponentsOfType<Canvas>(); for (int i = 0; i < canvasArray.Length; i++) if (IsValidCanvas(canvasArray[i])) return canvasArray[i].gameObject; // No canvas in the scene at all? Then create a new one. return MenuOptions.CreateNewUI(); } static bool IsValidCanvas(Canvas canvas) { if (canvas == null || !canvas.gameObject.activeInHierarchy) return false; // It's important that the non-editable canvas from a prefab scene won't be rejected, // but canvases not visible in the Hierarchy at all do. Don't check for HideAndDontSave. if (EditorUtility.IsPersistent(canvas) || (canvas.hideFlags & HideFlags.HideInHierarchy) != 0) return false; return StageUtility.GetStageHandle(canvas.gameObject) == StageUtility.GetCurrentStageHandle(); } } }
Editor-EventSystem-EventTriggerEditors.cs
using System; using UnityEngine; using UnityEngine.EventSystems; namespace UnityEditor.EventSystems { [CustomEditor(typeof(EventTrigger), true)] public class EventTriggerEditor : Editor { SerializedProperty m_DelegatesProperty; GUIContent m_IconToolbarMinus; GUIContent m_EventIDName; GUIContent[] m_EventTypes; GUIContent m_AddButonContent; protected virtual void OnEnable() { m_DelegatesProperty = serializedObject.FindProperty("m_Delegates"); m_AddButonContent = EditorGUIUtility.TrTextContent("Add New Event Type"); m_EventIDName = new GUIContent(""); // Have to create a copy since otherwise the tooltip will be overwritten. m_IconToolbarMinus = new GUIContent(EditorGUIUtility.IconContent("Toolbar Minus")); m_IconToolbarMinus.tooltip = "Remove all events in this list."; string[] eventNames = Enum.GetNames(typeof(EventTriggerType)); m_EventTypes = new GUIContent[eventNames.Length]; for (int i = 0; i < eventNames.Length; ++i) { m_EventTypes[i] = new GUIContent(eventNames[i]); } } public override void OnInspectorGUI() { serializedObject.Update(); int toBeRemovedEntry = -1; EditorGUILayout.Space(); Vector2 removeButtonSize = GUIStyle.none.CalcSize(m_IconToolbarMinus); for (int i = 0; i < m_DelegatesProperty.arraySize; ++i) { SerializedProperty delegateProperty = m_DelegatesProperty.GetArrayElementAtIndex(i); SerializedProperty eventProperty = delegateProperty.FindPropertyRelative("eventID"); SerializedProperty callbacksProperty = delegateProperty.FindPropertyRelative("callback"); m_EventIDName.text = eventProperty.enumDisplayNames[eventProperty.enumValueIndex]; EditorGUILayout.PropertyField(callbacksProperty, m_EventIDName); Rect callbackRect = GUILayoutUtility.GetLastRect(); Rect removeButtonPos = new Rect(callbackRect.xMax - removeButtonSize.x - 8, callbackRect.y + 1, removeButtonSize.x, removeButtonSize.y); if (GUI.Button(removeButtonPos, m_IconToolbarMinus, GUIStyle.none)) { toBeRemovedEntry = i; } EditorGUILayout.Space(); } if (toBeRemovedEntry > -1) { RemoveEntry(toBeRemovedEntry); } Rect btPosition = GUILayoutUtility.GetRect(m_AddButonContent, GUI.skin.button); const float addButonWidth = 200f; btPosition.x = btPosition.x + (btPosition.width - addButonWidth) / 2; btPosition.width = addButonWidth; if (GUI.Button(btPosition, m_AddButonContent)) { ShowAddTriggermenu(); } serializedObject.ApplyModifiedProperties(); } private void RemoveEntry(int toBeRemovedEntry) { m_DelegatesProperty.DeleteArrayElementAtIndex(toBeRemovedEntry); } void ShowAddTriggermenu() { // Now create the menu, add items and show it GenericMenu menu = new GenericMenu(); for (int i = 0; i < m_EventTypes.Length; ++i) { bool active = true; // Check if we already have a Entry for the current eventType, if so, disable it for (int p = 0; p < m_DelegatesProperty.arraySize; ++p) { SerializedProperty delegateEntry = m_DelegatesProperty.GetArrayElementAtIndex(p); SerializedProperty eventProperty = delegateEntry.FindPropertyRelative("eventID"); if (eventProperty.enumValueIndex == i) { active = false; } } if (active) menu.AddItem(m_EventTypes[i], false, OnAddNewSelected, i); else menu.AddDisabledItem(m_EventTypes[i]); } menu.ShowAsContext(); Event.current.Use(); } private void OnAddNewSelected(object index) { int selected = (int)index; m_DelegatesProperty.arraySize += 1; SerializedProperty delegateEntry = m_DelegatesProperty.GetArrayElementAtIndex(m_DelegatesProperty.arraySize - 1); SerializedProperty eventProperty = delegateEntry.FindPropertyRelative("eventID"); eventProperty.enumValueIndex = selected; serializedObject.ApplyModifiedProperties(); } } }
Runtime-UIElements-ExecuteEvents.cs
using System; using System.Collections.Generic; using UnityEngine.Pool; namespace UnityEngine.EventSystems { public static class ExecuteEvents { public delegate void EventFunction<T1>(T1 handler, BaseEventData eventData); public static T ValidateEventData<T>(BaseEventData data) where T : class { if ((data as T) == null) throw new ArgumentException(String.Format("Invalid type: {0} passed to event expecting {1}", data.GetType(), typeof(T))); return data as T; } private static readonly EventFunction<IPointerMoveHandler> s_PointerMoveHandler = Execute; private static void Execute(IPointerMoveHandler handler, BaseEventData eventData) { handler.OnPointerMove(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IPointerEnterHandler> s_PointerEnterHandler = Execute; private static void Execute(IPointerEnterHandler handler, BaseEventData eventData) { handler.OnPointerEnter(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IPointerExitHandler> s_PointerExitHandler = Execute; private static void Execute(IPointerExitHandler handler, BaseEventData eventData) { handler.OnPointerExit(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IPointerDownHandler> s_PointerDownHandler = Execute; private static void Execute(IPointerDownHandler handler, BaseEventData eventData) { handler.OnPointerDown(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IPointerUpHandler> s_PointerUpHandler = Execute; private static void Execute(IPointerUpHandler handler, BaseEventData eventData) { handler.OnPointerUp(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IPointerClickHandler> s_PointerClickHandler = Execute; private static void Execute(IPointerClickHandler handler, BaseEventData eventData) { handler.OnPointerClick(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IInitializePotentialDragHandler> s_InitializePotentialDragHandler = Execute; private static void Execute(IInitializePotentialDragHandler handler, BaseEventData eventData) { handler.OnInitializePotentialDrag(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IBeginDragHandler> s_BeginDragHandler = Execute; private static void Execute(IBeginDragHandler handler, BaseEventData eventData) { handler.OnBeginDrag(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IDragHandler> s_DragHandler = Execute; private static void Execute(IDragHandler handler, BaseEventData eventData) { handler.OnDrag(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IEndDragHandler> s_EndDragHandler = Execute; private static void Execute(IEndDragHandler handler, BaseEventData eventData) { handler.OnEndDrag(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IDropHandler> s_DropHandler = Execute; private static void Execute(IDropHandler handler, BaseEventData eventData) { handler.OnDrop(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IScrollHandler> s_ScrollHandler = Execute; private static void Execute(IScrollHandler handler, BaseEventData eventData) { handler.OnScroll(ValidateEventData<PointerEventData>(eventData)); } private static readonly EventFunction<IUpdateSelectedHandler> s_UpdateSelectedHandler = Execute; private static void Execute(IUpdateSelectedHandler handler, BaseEventData eventData) { handler.OnUpdateSelected(eventData); } private static readonly EventFunction<ISelectHandler> s_SelectHandler = Execute; private static void Execute(ISelectHandler handler, BaseEventData eventData) { handler.OnSelect(eventData); } private static readonly EventFunction<IDeselectHandler> s_DeselectHandler = Execute; private static void Execute(IDeselectHandler handler, BaseEventData eventData) { handler.OnDeselect(eventData); } private static readonly EventFunction<IMoveHandler> s_MoveHandler = Execute; private static void Execute(IMoveHandler handler, BaseEventData eventData) { handler.OnMove(ValidateEventData<AxisEventData>(eventData)); } private static readonly EventFunction<ISubmitHandler> s_SubmitHandler = Execute; private static void Execute(ISubmitHandler handler, BaseEventData eventData) { handler.OnSubmit(eventData); } private static readonly EventFunction<ICancelHandler> s_CancelHandler = Execute; private static void Execute(ICancelHandler handler, BaseEventData eventData) { handler.OnCancel(eventData); } public static EventFunction<IPointerMoveHandler> pointerMoveHandler { get { return s_PointerMoveHandler; } } public static EventFunction<IPointerEnterHandler> pointerEnterHandler { get { return s_PointerEnterHandler; } } public static EventFunction<IPointerExitHandler> pointerExitHandler { get { return s_PointerExitHandler; } } public static EventFunction<IPointerDownHandler> pointerDownHandler { get { return s_PointerDownHandler; } } public static EventFunction<IPointerUpHandler> pointerUpHandler { get { return s_PointerUpHandler; } } public static EventFunction<IPointerClickHandler> pointerClickHandler { get { return s_PointerClickHandler; } } public static EventFunction<IInitializePotentialDragHandler> initializePotentialDrag { get { return s_InitializePotentialDragHandler; } } public static EventFunction<IBeginDragHandler> beginDragHandler { get { return s_BeginDragHandler; } } public static EventFunction<IDragHandler> dragHandler { get { return s_DragHandler; } } public static EventFunction<IEndDragHandler> endDragHandler { get { return s_EndDragHandler; } } public static EventFunction<IDropHandler> dropHandler { get { return s_DropHandler; } } public static EventFunction<IScrollHandler> scrollHandler { get { return s_ScrollHandler; } } public static EventFunction<IUpdateSelectedHandler> updateSelectedHandler { get { return s_UpdateSelectedHandler; } } public static EventFunction<ISelectHandler> selectHandler { get { return s_SelectHandler; } } public static EventFunction<IDeselectHandler> deselectHandler { get { return s_DeselectHandler; } } public static EventFunction<IMoveHandler> moveHandler { get { return s_MoveHandler; } } public static EventFunction<ISubmitHandler> submitHandler { get { return s_SubmitHandler; } } public static EventFunction<ICancelHandler> cancelHandler { get { return s_CancelHandler; } } private static void GetEventChain(GameObject root, IList<Transform> eventChain) { eventChain.Clear(); if (root == null) return; var t = root.transform; while (t != null) { eventChain.Add(t); t = t.parent; } } public static bool Execute<T>(GameObject target, BaseEventData eventData, EventFunction<T> functor) where T : IEventSystemHandler { var internalHandlers = ListPool<IEventSystemHandler>.Get(); GetEventList<T>(target, internalHandlers); // if (s_InternalHandlers.Count > 0) // Debug.Log("Executinng " + typeof (T) + " on " + target); var internalHandlersCount = internalHandlers.Count; for (var i = 0; i < internalHandlersCount; i++) { T arg; try { arg = (T)internalHandlers[i]; } catch (Exception e) { var temp = internalHandlers[i]; Debug.LogException(new Exception(string.Format("Type {0} expected {1} received.", typeof(T).Name, temp.GetType().Name), e)); continue; } try { functor(arg, eventData); } catch (Exception e) { Debug.LogException(e); } } var handlerCount = internalHandlers.Count; ListPool<IEventSystemHandler>.Release(internalHandlers); return handlerCount > 0; } /// <summary> /// Execute the specified event on the first game object underneath the current touch. /// </summary> private static readonly List<Transform> s_InternalTransformList = new List<Transform>(30); public static GameObject ExecuteHierarchy<T>(GameObject root, BaseEventData eventData, EventFunction<T> callbackFunction) where T : IEventSystemHandler { GetEventChain(root, s_InternalTransformList); var internalTransformListCount = s_InternalTransformList.Count; for (var i = 0; i < internalTransformListCount; i++) { var transform = s_InternalTransformList[i]; if (Execute(transform.gameObject, eventData, callbackFunction)) return transform.gameObject; } return null; } private static bool ShouldSendToComponent<T>(Component component) where T : IEventSystemHandler { var valid = component is T; if (!valid) return false; var behaviour = component as Behaviour; if (behaviour != null) return behaviour.isActiveAndEnabled; return true; } /// <summary> /// Get the specified object's event event. /// </summary> private static void GetEventList<T>(GameObject go, IList<IEventSystemHandler> results) where T : IEventSystemHandler { // Debug.LogWarning("GetEventList<" + typeof(T).Name + ">"); if (results == null) throw new ArgumentException("Results array is null", "results"); if (go == null || !go.activeInHierarchy) return; var components = ListPool<Component>.Get(); go.GetComponents(components); var componentsCount = components.Count; for (var i = 0; i < componentsCount; i++) { if (!ShouldSendToComponent<T>(components[i])) continue; // Debug.Log(string.Format("{2} found! On {0}.{1}", go, s_GetComponentsScratch[i].GetType(), typeof(T))); results.Add(components[i] as IEventSystemHandler); } ListPool<Component>.Release(components); // Debug.LogWarning("end GetEventList<" + typeof(T).Name + ">"); } /// <summary> /// Whether the specified game object will be able to handle the specified event. /// </summary> public static bool CanHandleEvent<T>(GameObject go) where T : IEventSystemHandler { var internalHandlers = ListPool<IEventSystemHandler>.Get(); GetEventList<T>(go, internalHandlers); var handlerCount = internalHandlers.Count; ListPool<IEventSystemHandler>.Release(internalHandlers); return handlerCount != 0; } /// <summary> /// Bubble the specified event on the game object, figuring out which object will actually receive the event. /// </summary> public static GameObject GetEventHandler<T>(GameObject root) where T : IEventSystemHandler { if (root == null) return null; Transform t = root.transform; while (t != null) { if (CanHandleEvent<T>(t.gameObject)) return t.gameObject; t = t.parent; } return null; } } }
以上是“Unity3D如何實現甜品消消樂游戲”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。