Unity 基于eventTriggers的3D场景交互系统「建议收藏」

2022-09-05 13:06:31 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

Unity 基于eventTriggers的3D场景交互系统

Unity里的3D项目有时候需要大量的交互,而且是无UI的交互。 这时候可以像UI系统里,使用eventTrigger去制作交互系统。但是这个缺少自定义功能,所以我写了个自定义交互系统。这个交互系统可以做到什么呢?直接上图(仅为演示DEMO)。

  1. 点击触发事件
  1. 移动并且事件
  1. 复杂的交互

该系统采用的工厂设计模式,将你需要的功能写入EventTriggersDemo,将你的功能码和相关设置写入(需继承TriggerHelper抽象类)你的类。 使用时将根据设置触发事件。以下代码仅为框架,无具体实现代码。

代码语言:javascript复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Game
{ 
   
    [Flags]
    public enum THcode:int   //添加TH时可以使用&一次添加多个
    { 
   
        _null=0,
        one=1,
        two=2,
        three=4,
        _virtual=8
    }
}
代码语言:javascript复制
using System.Collections.Generic;
using UnityEngine;

namespace Game
{ 
   
    public abstract class TriggerHelper
    { 
   
        public THcode Code;
        public GameObject cardObject;
        public abstract void DefaultHelp();
        public abstract void CloseHelp();
    }
} 
代码语言:javascript复制
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;

namespace Game
{ 
   
    public class VirtualTH : TriggerHelper
    { 
   
        public VirtualTH()
        { 
   
            Code = THcode._virtual;
        }
        public VirtualTH(GameObject gameObject):this()
        { 
   
            cardObject = gameObject;
        }
        public override void CloseHelp()
        { 
   
            CardEventTriggers.RemoveEventTriggersListener(cardObject, EventTriggerType.PointerDown,
                cardObject.GetComponent<CardEventTriggers>().Click);
        }

        public override void DefaultHelp()
        { 
   
            CardEventTriggers.AddEventTriggersListener(cardObject, EventTriggerType.PointerDown,
                cardObject.GetComponent<CardEventTriggers>().Click);
        }
    }
}
代码语言:javascript复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using System;

namespace Game
{ 
   
    public class EventTriggersDemo : MonoBehaviour
    { 
   
        public  Dictionary<int, TriggerHelper> THdic = new Dictionary<int, TriggerHelper>();
        private THcode Oncode;
        private THcode Offcode;
        [HideInInspector]
        public THcode showCode;
        
       
        protected void Start()
        { 
   
            showCode = THcode._null;
            
            InitDic();

        }

        #region Check
        public bool Check(THcode hcode)
        { 
   
            if ((showCode & hcode) == hcode)
                return true;
            else return false;
        }
        [ContextMenu("ShowCode")]
        private void ShowCode()
        { 
   
            Debug.Log(showCode);
        }

        #endregion
        #region Set or Delete
        public void SetOncode(THcode hcode)
        { 
   
            Oncode = hcode;
            UpdateHelp();
        }
        public void DelTrigger(THcode hcode)
        { 
   
            Offcode = hcode;
            RemoveHelp();
        }

        #endregion
        
        /// <summary>
        /// 必须调用,注意更新
        /// </summary>
        private void InitDic()
        { 
   
            VirtualTH virtualTH = new VirtualTH(this.gameObject);

            THdic.Add((int)THcode._virtual, virtualTH);
        }
        
        /// <summary>
        /// 更新卡牌挂载 (算法可优化,请自行优化)
        /// </summary>
        public void UpdateHelp()
        { 
   
            foreach (KeyValuePair<int, TriggerHelper> kvp in THdic)
            { 
   
                DefaultMultiHelp(kvp, Oncode);
            }
        }
        public void RemoveHelp()
        { 
   
            foreach (KeyValuePair<int, TriggerHelper> kvp in THdic)
            { 
   
                CloseMultiHelp(kvp, Offcode);
            }
        }
        private void DefaultHelp(KeyValuePair<int, TriggerHelper> kvp , THcode oncode,THcode target)
        { 
   
            if(((THcode)kvp.Key & oncode)== target)
            { 
   
                showCode = showCode | target;
                kvp.Value.DefaultHelp();
            }
        }
        private void DefaultMultiHelp(KeyValuePair<int, TriggerHelper> kvp, THcode oncode)
        { 
   
            Array enum_array = Enum.GetValues(typeof(THcode));
            foreach (THcode _enum in enum_array)
            { 
   
                if (_enum != THcode._null)
                    DefaultHelp(kvp, oncode, _enum);
            }
        }
        private void CloseHelp(KeyValuePair<int, TriggerHelper> kvp, THcode offcode, THcode target)
        { 
   
            if(((THcode)kvp.Key & offcode)== target)
            { 
   
                showCode = showCode & (~target);
                kvp.Value.CloseHelp();
            }
        }
        private void CloseMultiHelp(KeyValuePair<int, TriggerHelper> kvp, THcode offcode)
        { 
   
            Array enum_array= Enum.GetValues(typeof(THcode));
            foreach(THcode _enum in enum_array)
            { 
   
                if(_enum != THcode._null)
                   CloseHelp(kvp,offcode,_enum);
            }
        }


        #region EventData :书写我需要的EventTrigger功能
        //以下为虚方法形式的功能自定义,也可直接自定义(不开源,请自行研究)
        //除了鼠标交互系统,按键交互也可以制作。
        #region Virtual 
        public void Click(BaseEventData baseEventData)
        { 
   
            Click();
        }
        public virtual void Click()
        { 
   
            Debug.LogWarning("Don't Override!Or it wasn't invoked!");
        }
        #endregion
        
        #endregion


        /// <summary>
        /// 添加事件(不能识别是否重复添加事件,重复添加,触发时将多次运行自定义功能。这是我要的功能,不想要重复添加,需要修改)
        /// </summary>
        /// <param name="object"></param>
        /// <param name="type">事件类型</param>
        /// <param name="action">事件方法</param>
        public static void AddEventTriggersListener(GameObject @object, EventTriggerType type, UnityAction<BaseEventData> action)
        { 
   
            EventTrigger.Entry entry=null;
            EventTrigger eventTrigger = @object.GetComponent<EventTrigger>();
            if (eventTrigger == null)
            { 
   
                @object.AddComponent<EventTrigger>();
                eventTrigger = @object.GetComponent<EventTrigger>();
            }
            foreach (EventTrigger.Entry existingEntry in eventTrigger.triggers)
            { 
   
                if (existingEntry.eventID == type)
                { 
   
                    entry = existingEntry;
                }
            }
            if (NeedNew(entry))
            { 
   
                entry = new EventTrigger.Entry();
                entry.eventID = type;
                entry.callback.AddListener(action);
                eventTrigger.triggers.Add(entry);
                return;
            }
                Debug.Log(@object.transform.name   String.Format(" Add {0} ETListener!",type.ToString()));
                entry.callback.AddListener(action);
        }
        /// <summary>
        /// 删除事件(不是删除一个,而是相同的全删)
        /// </summary>
        /// <param name="object"></param>
        /// <param name="type">事件类型</param>
        /// <param name="action">事件方法</param>
        public static void RemoveEventTriggersListener(GameObject @object, EventTriggerType type,UnityAction<BaseEventData> action)
        { 
   
            if (@object.GetComponent<EventTrigger>())
            { 
   
                EventTrigger eventTrigger = @object.GetComponent<EventTrigger>();
                foreach (EventTrigger.Entry _entry in eventTrigger.triggers)
                { 
   
                   // Debug.Log(_entry.eventID.ToString());
                    if (_entry.eventID == type)
                    { 
   
                            Debug.Log(@object.transform.name   String.Format(" Remove {0} ETListener!", type.ToString()));
                            _entry.callback.RemoveListener(action);
                    }
                }
            }
        }
        private static bool NeedNew(EventTrigger.Entry entry)
        { 
   
            if (entry == null)
                return true;
            else return false;
        }

    }
}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/137569.html原文链接:https://javaforall.cn

0 人点赞