2021年7月10日如何构建一个简单的trigger系统
发布日期:2022-03-03 10:44:00 浏览次数:8 分类:技术文章

本文共 9202 字,大约阅读时间需要 30 分钟。

我在工作中经常看到别人写trigger,我自己一直很想写,由于工作的原因写了一个最简单的,这个trigger还不包括triggercondition 我这里没有条件分支,只有节点逻辑,这个东西也是以后需要扩展的。

triggerview.cs脚本(可以挂在gameObject上先选择一个触发类型,然后点+然后填写相关的参数 然后在你的脚本中通常和triggerview在同一个节点上或者同一个节点数上去触发trigger,至于什么时候触发那是逻辑的事情)  triggersystem.cs脚本 (在triggerview中构建 )  TriggerCollider处理具体的实务逻辑 这里就是开关碰撞盒子 简化了一些无用的逻辑代码(当然你也可以构建一个定时检测的任务,开一个定时器检测比如飞剑特效飞行的距离,距离到了执行xx触发器之类的) 具体exe怎么执行可以自行改造  

using UnityEngine;

using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif

#if UNITY_EDITOR

[CustomEditor(typeof(TriggerView))]
public class TriggerViewDataEditor: Editor // 编辑器和实现写在一个类中了建议分开
{
    TriggerView self;

    public List<TriggerHandle> _handles = new List<TriggerHandle>();

    public void OnEnable()
    {
        self = target as TriggerView;
    }
    public override void OnInspectorGUI()
    {
        self = target as TriggerView;
        if (self == null) return;

        EditorGUI.BeginChangeCheck();

        self.m_eventDefine = (TriggerDefine.TriggerEventDefine)EditorGUILayout.Popup((int)self.m_eventDefine,
                    TriggerDefine.TriggerEnumString);
        GUILayout.BeginHorizontal();
        if(GUILayout.Button("+"))
        {
            if(self.m_eventDefine == TriggerDefine.TriggerEventDefine.hideOrShow_caster)
            {
                var obj = new TriggerHideOrShowRole();
                obj.triggerType = (int)TriggerDefine.TriggerEventDefine.hideOrShow_caster;
                obj.jsonData = obj.ToStringEx();
                _handles.Add(obj);
            }
            
        }
        if(GUILayout.Button("-"))
        {
            if(_handles.Count == 0 )
            {
                return; 
            }
            var removeIndex = (_handles.Count - 1);
            _handles.RemoveAt(removeIndex);
            self.stringObjects.RemoveAt(removeIndex);
            
            EditorUtility.SetDirty(self.gameObject);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();

        }

        GUILayout.EndHorizontal();
        GUILayout.BeginVertical();
        for (int i = 0; i < self.stringObjects.Count; i++)
        {
            if(i >= _handles.Count || _handles[i] == null)
            {
                var obj = TriggerHandle.CreateByString(self.stringObjects[i]);
                if(i >= _handles.Count)
                {
                    _handles.Add(obj);
                }
                else
                {
                    _handles[i] = obj;
                }
                obj.DrawInspector(this, i);
            }
            else
            {
                _handles[i].DrawInspector(this, i);
            }
        }
        GUILayout.EndVertical();

        if (EditorGUI.EndChangeCheck())

        {
            if (_handles.Count > 0)
            {
                self.stringObjects.Clear();
            }
            for (int i = 0; i < _handles.Count; i++)
            {
                self.stringObjects.Add(TriggerHandle.ToStringEx(_handles[i], this, i));
            }
            EditorUtility.SetDirty(self.gameObject);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
        
    }

}

#endif

public class TriggerView : MonoBehaviour

{
   
    public List<string> stringObjects = new List<string>();
    [HideInInspector]
    public List<TriggerHandle> handles = new List<TriggerHandle>();
    public Dictionary<int, TriggerHandle> triggerMap = new Dictionary<int, TriggerHandle>();
    public TriggerDefine.TriggerEventDefine m_eventDefine = TriggerDefine.TriggerEventDefine.Add_Effect_LifeTime;
    private TriggerSystem m_triggerSystem;
 

    private void Awake()

    {
       
        handles.Clear();
        for (int i = 0; i < stringObjects.Count; i++)
        {
            handles.Add(TriggerHandle.CreateByString(stringObjects[i]));
            if(triggerMap.ContainsKey(handles[i].triggerId))
            {
                Debug.LogError("存在相同的triggerId");
            }
            triggerMap.Add(handles[i].triggerId, handles[i]);
        }
        Debug.Log("打印triggerMap");
        foreach(var item in triggerMap)
        {
            Debug.Log(item.Key);
        }
        m_triggerSystem =  new TriggerSystem().Attach(this.gameObject);
        RegisterAllTrigger();  // 注册所有的trigger
    }
   

    private void RegisterAllTrigger()

    {
        for (int i = 0; i < handles.Count; i++)
        {
            m_triggerSystem.RegisterTrigger( handles[i].triggerId);
        }
    }

    public void TriggerId(int id) // 触发trigger的接口

    {
        m_triggerSystem.Trigger(id);
    }
}

triggerSystem.cs脚本

using System.Collections;

using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System.Reflection;

public partial class TriggerSystem  {
    private GameObject m_go;
    private TriggerView m_view;
    private FieldInfo[] eventFiledInfos;
    private Dictionary<int, TriggerHandle> triggerHandlers = new Dictionary<int, TriggerHandle>();
    public TriggerSystem Attach(GameObject go)
    {
        m_go = go;
        return this;
    }

    public void RegisterTrigger(int triggerId)

    {
        var view = GetTriggerView();
        TriggerHandle handle = view.triggerMap[triggerId];
        triggerHandlers.Add(triggerId, handle);
    }    
    public void Trigger(int triggerId)
    {
        if (!triggerHandlers.ContainsKey(triggerId))
        {
            return;
        }
        triggerHandlers[triggerId].Exe(m_go,m_view,this);
    }

    public void RemoveRrigger(int triggerId)

    {
        if (!triggerHandlers.ContainsKey(triggerId)) return;
        triggerHandlers.Remove(triggerId);
    }

    public TriggerView GetTriggerView()

    {
        if (m_view == null)
            m_view = m_go.GetComponent<TriggerView>();
        return m_view;
    }

}

triggerDefine.cs

using System;

public static class TriggerDefine

{
    public enum TriggerEventDefine
    {
        Add_Effect_LifeTime = 0,
        Create_effect,
        open_close_collider,
        create_sub_emiter,
        Timer_Check, 
        end_track, 
        hideOrShow_caster, 
    }

    public static Type[] typeArr =

    {
        typeof(TriggerCollider),
    };
    public static string[] TriggerEnumString =
    {
        "开启关闭碰撞",
    };
}

TriggerHandle.cs 

using UnityEngine;

using System.Collections.Generic;
using rkt;
using System.Text;
using LitJson;

#if UNITY_EDITOR

using UnityEditor;
#endif

public interface ITriggerHandle
{
#if UNITY_EDITOR
    public void DrawInspector(TriggerViewDataEditor self, int index);
    
    public  string ToStringEx();
#endif
    public TriggerHandle CreateByStringMap(Dictionary<string, string> dataMap);
}

[System.Serializable]

public class TriggerHandle : ITriggerHandle
{
    [SerializeField]
    public int triggerType = 0;
    [SerializeField]
    public int triggerId;
    [SerializeField]
    public bool bAfterTriggerDestroy; // 触发后销毁 
 

    public virtual void Exe(GameObject go,TriggerView view,TriggerSystem triggerSys)

    {

    }

    

    public virtual TriggerHandle CreateByStringMap(Dictionary<string, string> dataMap)

    {
        this.triggerId = int.Parse(dataMap["triggerId"]);
        this.triggerType = int.Parse(dataMap["triggerType"]);
        if(dataMap.ContainsKey("bAfterTriggerDestroy"))
        {
            this.bAfterTriggerDestroy = bool.Parse(dataMap["bAfterTriggerDestroy"]);
        }
        return this;
    }

    public static TriggerHandle CreateByString(string jsondata)

    {
        Dictionary<string, string> dataMap = new Dictionary<string, string>();
        var arr1 = jsondata.Split('#');
        for (int i = 0; i < arr1.Length; i++)
        {
            if (!string.IsNullOrEmpty(arr1[i]))
            {
                var arr2 = arr1[i].Split('-');
                dataMap.Add(arr2[0], arr2[1]);
            }
        }

        var ty = TriggerDefine.typeArr[int.Parse(dataMap["triggerType"])];

        var tmp = System.Activator.CreateInstance(ty) as TriggerHandle;
        tmp.CreateByStringMap(dataMap);
        return tmp;
    }

#if UNITY_EDITOR

    public string jsonData;

    public virtual void DrawInspector(TriggerViewDataEditor self, int index)

    {
        triggerId = EditorGUILayout.IntField("triggerId", triggerId);
        EditorGUILayout.TextField("触发器类型",TriggerDefine.TriggerEnumString[triggerType]);
        this.bAfterTriggerDestroy = EditorGUILayout.Toggle("触发后是否删除", bAfterTriggerDestroy);
    }
   
   
    public virtual string ToStringEx()
    {
        return "";
    }
    public static string ToStringEx(TriggerHandle handle, TriggerViewDataEditor view,int index)
    {
        string str = handle.ToStringEx();
        //var methodInfo = TriggerDefine.typeArr[handle.triggerType].GetMethod("ToStringEx");
        //string str = (string) methodInfo.Invoke(handle, new object[] { });
        if(string.IsNullOrEmpty(str))
        {
            return handle.jsonData;
        }
        return str;
        //if (handle is TriggerAddEffectLifeTime)
        //{
        //    return (handle as TriggerAddEffectLifeTime).ToStringEx();
        //}
        //if (handle is TriggerCreateEffect)
        //{
        //    return (handle as TriggerCreateEffect).ToStringEx();
        //}
    }
    
#endif
}

TriggerCollider.cs

using UnityEngine;

using System.Collections.Generic;
using rkt;
using System.Text;
using LitJson;
#if UNITY_EDITOR
using UnityEditor;
#endif
[System.Serializable]
public class TriggerCollider : TriggerHandle
{
    [SerializeField]
    public int openOrClose = 1; // 1开启 非1关闭

//trigger触发的方法 在TriggerSystem中注册该方法   

  public override void Exe(GameObject go, TriggerView view, TriggerSystem triggerSys)

    {
        var triggerView = view;
        if (triggerView == null) return;
        TriggerCollider triggerCollider = triggerView.triggerMap[triggerId] as TriggerCollider;

        Debug.Log("触发了trigger" + triggerCollider.triggerId);

        var colider = go.GetComponent<Collider2D>();
        if (colider != null)
        {
            colider.enabled = triggerCollider.openOrClose == 1;
        }
        if (triggerCollider.bAfterTriggerDestroy)
        {
            triggerSys.RemoveRrigger(triggerId);
        }
    }
    public override TriggerHandle CreateByStringMap(Dictionary<string, string> dataMap)
    {
        base.CreateByStringMap(dataMap);
        this.openOrClose = int.Parse(dataMap["openOrClose"]);
        return this;
    }

#if UNITY_EDITOR

    private bool isFoldOut = true;
    public override void DrawInspector(TriggerViewDataEditor self, int index)
    {

        EditorGUI.BeginChangeCheck();

        isFoldOut = EditorGUILayout.Foldout(isFoldOut, index.ToString());
        if (isFoldOut)
        {
            base.DrawInspector(self, index);
            this.openOrClose = EditorGUILayout.IntField("1表示开启0表示关闭碰撞", this.openOrClose);
        }
        if (EditorGUI.EndChangeCheck())
        {
            jsonData = ToStringEx();
            EditorUtility.SetDirty((self.target as TriggerView).gameObject);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

    }

    public override string ToStringEx()
    {
        var fieldArr = typeof(TriggerCollider).GetFields();
        StringBuilder sb = new StringBuilder();
        foreach (var field in fieldArr)
        {
            object[] attrs = field.GetCustomAttributes(true);
            for (int i = 0; i < attrs.Length; i++)
            {
                if (attrs[i].GetType() == typeof(UnityEngine.SerializeField))
                {
                    sb.Append(field.Name + "-" + field.GetValue(this) + "#");
                    break;
                }
            }
        }
        jsonData = sb.ToString();
        return jsonData;

    }

#endif

}
 

转载地址:https://blog.csdn.net/yangjie6898862/article/details/118639597 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:3种递归写法 获取结点树目录
下一篇:不使用递归算法找结点||组件

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年03月28日 18时50分49秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章