本文共 8141 字,大约阅读时间需要 27 分钟。
DragImage拖拽赋值组件
游戏中的拖拽组件、拖拽类。 游戏开发中经常需要拖拽一个图标来完成赋值操作,比如我们游戏就需要拖拽技能图标到一个孔位上实现技能的装配
重要的3个方法 DragIn(拖自己) DragOut(被别人拖) DragSus (拖拽成功后做的表现,不做逻辑) 主要就是想把几个阶段分出来,同时做到逻辑和显示分离,方便写代码,解决bug
using UnityEngine;
using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; /* 首先需要设置SetData(data) data是一个table的数据类型 可以放任何数据 方便拖拽传输数据结构 什么是DragIn 就是拖拽A A会执行的一个方法,参数是A的data 什么是DragOut 就是把A拖到B上 ,B执行的操作 参数是A的data和B的data DragSus 其实可以和DragOut合在一起 这里分开主要是一个做逻辑一个做显示 显示是比较灵活的 不方便在c#处理 这个放到lua的回调函数中想怎么显示怎么显示 规则自己定 反之 如果是B拖A那么执行A的DragOut B的DragIn */ namespace rkt { //这3个代理函数 应该放入CustomSetting。cs中的自定义代理列表中 public delegate bool DragOut(object dataA, object dataB); public delegate bool DragIn( object dataA); public delegate void DragSus(GameObject a, GameObject b); //拖拽类 一定需要有组件Image 不然没法copy一个image显示 [RequireComponent(typeof(Image))] public class DragImage : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler, IDropHandler { public object data; // 待传输的数据结构 private GameObject drag_icon; private RectTransform cashe_drag_com; private RectTransform cavas_rect; private bool canDrag = true; private GameObject uiRoot { get; set; } // 拖拽生成的副本的父结点 private Camera UGUIcamera { get; set; } public DragOut dragOutfunc; public DragIn dragInfunc; public DragSus dragSusfunc; public int dragImageSortOrder =10000; public Image targetImage;
public void SetData(object data) // Lua那边传数据过来
{ this.data = data; }
public void OnBeginDrag(PointerEventData eventData) //鼠标拖拽拾取对象
{canDrag = true;
if (dragInfunc != null && !dragInfunc(data)) { canDrag = false; return; }//代替品实例化
if (uiRoot == null) { uiRoot = GameObject.Find("UGuiSystem/MainCanvas"); cavas_rect = uiRoot.GetComponent<RectTransform>(); var tmp = GameObject.Find("UGuiSystem"); // uguicamera所在的节点 if (tmp) { UGUIcamera = tmp.GetComponent<Camera>(); }}
if (uiRoot == null || UGUIcamera == null) { return; } if(drag_icon != null) { GameObject.Destroy(drag_icon); drag_icon = null; }drag_icon = new GameObject("icon");
drag_icon.layer = LayerMask.NameToLayer("UI"); drag_icon.transform.SetParent(uiRoot.transform, false); drag_icon.AddComponent<RectTransform>(); cashe_drag_com = drag_icon.GetComponent<RectTransform>(); var img = drag_icon.AddComponent<Image>(); if (targetImage) { img.sprite = targetImage.sprite; } else { img.sprite = this.GetComponent<Image>().sprite; } var canvas = drag_icon.AddComponent<Canvas>(); canvas.overrideSorting = true; canvas.sortingOrder = dragImageSortOrder; // 层级尽量高//防止拖拽结束时,代替品挡住了准备覆盖的对象而使得 OnDrop() 无效
CanvasGroup group = drag_icon.AddComponent<CanvasGroup>(); group.blocksRaycasts = false; } public void OnEndDrag(PointerEventData eventData) { if (drag_icon) { Destroy(drag_icon); drag_icon = null; } }public void OnDrag(PointerEventData eventData)
{ if (!canDrag) { return; } Vector3 pos; if(cashe_drag_com == null) { return; } if (RectTransformUtility.ScreenPointToWorldPointInRectangle(cavas_rect, eventData.position, UGUIcamera, out pos)) { cashe_drag_com.position = pos; // 报过一次异常 可能需要处理一下异常 } }public void OnDrop(PointerEventData eventData) // 鼠标松开后获得拾取的对象
{ var com = eventData.pointerDrag.GetComponent<DragImage>(); if (com == null) { return; } if (!com.canDrag) { return; } if (dragOutfunc != null && !dragOutfunc(eventData.pointerDrag.GetComponent<DragImage>().data,data)) { return; } //A拖拽到B 现将B的位置和A的位置互换,已达到拖拽变换AB图标的效果 //Vector3 pos = eventData.pointerDrag.transform.position; //eventData.pointerDrag.transform.position = this.transform.position; //this.transform.position = pos; if(dragSusfunc != null ) { dragSusfunc(eventData.pointerDrag, gameObject); } }}
}lua端使用:
--拖拽数据赋值self.sub[i].dragCom.data = datatmp -- dragCom 是image组件 data 成员可以被赋值 一般就是应用数据 方便处理逻辑 传递逻辑 self.sub[i].dragCom.dragInfunc = function(a)--这个地方可以做一些逻辑判断 比如是否该图标能够被拖拽 不能拖拽就返回false 可以则返回true local heroLevel = GameHelp:GetHeroLevel(); if a.idx == 1 or a.skillId == nil or a.skillId <= 0 or heroLevel < gUIMainSkillOpenLevel[i] then -- 后续界面类型考虑枚举定义 return false; -- 普通技能无法拖拽 固定的 end --检查其后置技能是否可以被插入技能 self:SendLostAndGetSingle(a.skillId) return true -- 可以拖拽的end
self.sub[i].dragCom.dragOutfunc = (function(a,b) -- 被别人拖拽赋值 同样能否拖拽赋值成功也是通过返回false和true来判断的 local heroLevel = GameHelp:GetHeroLevel(); if b.idx == 1 or heroLevel < gUIMainSkillOpenLevel[i] then -- 被拖到普攻上 或者被上锁了 return false; end if i > 5 then -- 1 == 普攻 2345 前置技能 大于5后置技能 local frontSkillInfo = self:GetSkillInfo(i-4); if frontSkillInfo.skillId == nil or frontSkillInfo.skillId <= 0 then IGame.ChatClient:addSystemTips(TipType_Operate, InfoPos_ActorUnder, "请先装配前置技能") -- 系统提示功能 tip return false; end --前置技能== 拖拽技能 且 后置没有技能 拖拽技能到后置技能 需要提示无法拖拽 if a.skillId == frontSkillInfo.skillId and (b.skillId == nil or b.skillId == 0) then IGame.ChatClient:addSystemTips(TipType_Operate, InfoPos_ActorUnder, "请先装配前置技能") -- 系统提示功能 tip return false; end end self.sub[i].dataB = b; self.sub[i].dataB_ui_type = b.uitype; self.sub[i].dataA = a; self.sub[i].dataA_ui_type = a.uitype; if b.uitype == a.uitype then -- 自己托给自己的情况 B拖给B self:OnDragBToB(i); else -- 被转技能界面拖的情况 A拖给B 左侧技能拖给右侧技能 local rst = false; local hasConfilt,pos = self:HasConflict(i) if hasConfilt then --需要对dataA的数据进行加工 self.sub[i].dataA_ui_type = self.sub[i].dataB_ui_type self.sub[i].dataA.idx = pos; rst = self:OnDragBToB(i); --这种情况下自己处理显示相关 else rst = self:OnDragAToB(i); end return rst; end return true;end);self.sub[i].dragCom.dragSusfunc = (function(a,b) -- b和a都是gameObject 拖拽成功后的显示操作 --BtoB的情况 if self.sub[i].dataA_ui_type == self.sub[i].dataB_ui_type then --交换一下image local idxA = self.sub[i].dataA.idx; local idxB = self.sub[i].dataB.idx; local comb = self.sub[idxB].skillIcon local coma = self.sub[idxA].skillIcon local tempSprite = comb.sprite; comb.sprite = coma.sprite; coma.sprite = tempSprite; for ii = MIN_SKILL_INDEX,9 do Util.Log("销毁特效"..ii,"destroy"); self:DestroyAllEffect(ii) end if self:GetSkillInfo(self.sub[i].dataA.idx).skillId and self:GetSkillInfo(self.sub[i].dataA.idx).skillId > 0 then local rectA = coma.gameObject:GetComponent(typeof(RectTransform)) rectA.sizeDelta = Vector2.New(SKILL_ICON_SIZE,SKILL_ICON_SIZE); coma.enabled = true; self:PlayEffect(idxA,EFFECT_SUCESS,1000) else coma.enabled = false self:DestroyAllEffect(idxA) end if self:GetSkillInfo(self.sub[i].dataB.idx).skillId and self:GetSkillInfo(self.sub[i].dataB.idx).skillId > 0 then local rectB = comb.gameObject:GetComponent(typeof(RectTransform)) rectB.sizeDelta = Vector2.New(SKILL_ICON_SIZE,SKILL_ICON_SIZE); comb.enabled = true; --要发失去选中xx 选中xx 发选中b的事件 self:SendLostAndGetSingle(self:GetSkillInfo(self.sub[i].dataB.idx).skillId) self:PlayEffect(idxB,EFFECT_SUCESS,1000) self:DestroyEffect(idxB,EFFECT_SEL) else comb.enabled = false self:DestroyAllEffect(idxB) end else --AtoB的情况 这种需要知道A的结构 背景还未处理 local comb = self.sub[i].skillIcon; local coma = a:GetComponent(typeof(Image)) comb.sprite = coma.sprite; local rect = comb.gameObject:GetComponent(typeof(RectTransform)) rect.sizeDelta = Vector2.New(SKILL_ICON_SIZE,SKILL_ICON_SIZE); comb.enabled = true; --发选中b的事件 local curSelId = self:GetSkillInfo(self.sub[i].dataB.idx).skillId self:SendLostAndGetSingle(curSelId) --一次成功的拖拽应该给B都播放成功特效 以及需要给b选中状态 self:PlayEffect(i,EFFECT_SUCESS,1000) self:DestroyEffect(i,EFFECT_CAN_INSERT) end local lastSelId = self:GetSkillInfo(self.sub[i].dataB.idx).skillId local skillPart = GetSkillPart() for ii = MIN_SKILL_INDEX,9 do if ii ~= i and self:IsCanEquip(ii,lastSelId) then self:PlayEffect(ii,EFFECT_CAN_INSERT) end endend)
转载地址:https://blog.csdn.net/yangjie6898862/article/details/109692956 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!