DragImage拖拽赋值组件
发布日期:2022-03-03 10:43:58 浏览次数:3 分类:技术文章

本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Rb-tree中删除元素后树形调整函数_Rb_tree_rebalance_for_erase
下一篇:RectAToB组件

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月15日 14时33分15秒