您好,登錄后才能下訂單哦!
這篇文章主要介紹Unity3D如何實(shí)現(xiàn)甜品消消樂游戲,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
解釋:
之前用的ScreenToGif錄屏,因?yàn)樯蟼鞯?gif最大不超過5MB,所以做了不少刪幀和色彩弱化等處理,這才導(dǎo)致色彩看上去不是很舒服,不要盯著它看太久,不然會(huì)有點(diǎn)難受...
由于使用的素材是現(xiàn)成的,沒有花時(shí)間精力去扒,所以細(xì)節(jié)方面可能不是做的很好。
說明:
這次的甜品消消樂雖然看上去好像挺簡單普通的,但是相對于之前的坦克大戰(zhàn),某種程度上已然提升難度了,歸類到了算法類層的游戲。
拉到最后看代碼你就能理解我的意思了,坦克大戰(zhàn)的所有代碼加起來還不如消消樂兩個(gè)類的代碼多,其他各種細(xì)節(jié),坦克也只能望其項(xiàng)背...
如果坦克大戰(zhàn)是低階的,那么甜品消消樂就是中階的,有著不少的動(dòng)畫效果和交互(碰撞檢測和甜品的控制等),游戲運(yùn)行的所有機(jī)制和功能需要在模型層上進(jìn)行操控。
這次的消消樂需要一定的邏輯思維、算法基礎(chǔ)、Unity綜合能力和編程基礎(chǔ)。
方正粗圓的字體和布靈布靈的閃光特效會(huì)賦予游戲可愛風(fēng)的氛圍感。
我們把物體分為模型層和渲染層,這樣它們各司其職,降低工作的耦合性。
由于12.29日放假前還剩 兩門課設(shè)答辯和一門考試,不足之處以后再補(bǔ)充...
游戲資源(音頻、圖片、特效等)
場景和包(動(dòng)畫。渲染精靈和控制器等)
游戲腳本(UI、Runtime等)
......太多了,只選擇了部分作為展示
在Gizmos目錄下,可以找到對應(yīng)按鈕隱藏?cái)z像機(jī),這樣處理場景的時(shí)候會(huì)舒服很多
Clone都放上會(huì)有些雜亂,都刪掉,只放了一個(gè)背景圖
開始按鈕(玩家通過點(diǎn)擊開始按鈕,進(jìn)入新的一局游戲)
重玩按鈕(玩家可以及時(shí)返回開始界面進(jìn)行相應(yīng)操作)
時(shí)鐘(顯示游戲剩余時(shí)間,一局游戲初始化時(shí)間是60s)
計(jì)分板(顯示當(dāng)前游戲得分)
普通甜品(甜甜圈、糖果、起司...至少同時(shí)有3個(gè)在同一排或同一列時(shí),可以消除)
特殊甜品(一定條件下會(huì)觸發(fā)2種特殊甜品道具,一種是帶有左右晃動(dòng)特效的甜品,可以消除一整排的甜品;另一種是帶有上下晃動(dòng)特效的甜品,可以消除一整列的甜品)
積分面板(游戲時(shí)間結(jié)束后,會(huì)用類似飛躍的動(dòng)畫效果產(chǎn)生得分界面窗口,逐漸變大顯示,最終定格。點(diǎn)擊重玩立即開始下一局游戲,叉掉返回開始界面)
點(diǎn)擊開始進(jìn)入游戲,每一局新開的游戲設(shè)時(shí)60s(可以根據(jù)需要調(diào)整),用最快的速度消除出現(xiàn)在同一行或者同一列的相同的甜點(diǎn)會(huì)獲得相應(yīng)積分。
盡量用最優(yōu)的策略使得一定時(shí)間內(nèi)的積分最大化(不過這一點(diǎn),游戲玩熟了可能才能漸漸領(lǐng)悟,屬于大師級(jí)別的操作了??梢杂肁CM相關(guān)算法寫個(gè)外掛,應(yīng)該是用動(dòng)態(tài)規(guī)劃算法處理)。
當(dāng)符合特定消除條件的甜品被消除后,會(huì)隨機(jī)產(chǎn)生兩類特殊甜品的一種,這個(gè)甜品會(huì)瞬間清除一整行或者一整列的甜品,使得積分暴增。
相同時(shí)間內(nèi)積分高者或者相同積分用時(shí)少者優(yōu)勝。
小蝦選用的是Unity個(gè)人版,采用的是Unity一個(gè)較新的版本-2021.1.16,這里建議小伙伴們下載和教程相同版本的,不然真的會(huì)有可能遇到卡點(diǎn)消耗心情哈。
可以和我一樣在Unity Hub里面安裝,Hub感覺挺好用的。
但是每次重啟后都要手動(dòng)激活許可證,這是真的挺煩的。
小蝦在這里主要介紹部分核心代碼實(shí)現(xiàn),想知道其他部分實(shí)現(xiàn)的小伙伴在下方留言,我再添加~
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如何實(shí)現(xiàn)甜品消消樂游戲”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。