[unity]一种简单的触发器系统

如题,本系统实现了一种触发器(可视为简单的脚本)系统,代码如下:

TriggerGroup.cs:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Script.Systems.TriggerSyatem;
using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

namespace Script.Systems.TriggerSystem
{
    public class TriggerSet
    {
        public ITrigger triggers;
        public string name;
        public string description;

        public TriggerSet(ITrigger triggers, string name, string description)
        {
            this.triggers = triggers;
            this.name = name;
            this.description = description;
        }

        public void Active()
        {
            triggers.Active();
        }

        public void Inactive()
        {
            triggers.Inactive();
        }

        // 序列化
        public string Serialize()
        {
            return SerializationHelper.Serialize(this);
        }

        // 反序列化
        public static TriggerSet Deserialize(string json)
        {
            return SerializationHelper.Deserialize<TriggerSet>(json);
        }
    }
    public class TriggerGroup : MonoBehaviour, ITrigger
    {
        private List<ITrigger> triggers = new List<ITrigger>();

        public void RegisterTrigger(ITrigger trigger)
        {
            triggers.Add(trigger);
        }

        public void UnregisterTrigger(ITrigger trigger)
        {
            triggers.Remove(trigger);
        }

        public List<ITrigger> GetTriggers()
        {
            return new List<ITrigger>(triggers);
        }

        ITrigger ITrigger.Copy()
        {
            var copy = new TriggerGroup();
            foreach (var trigger in triggers)
            {
                copy.triggers.Add(trigger.Copy());
            }
            return copy;
        }

        public void Active()
        {
            foreach (var trigger in triggers)
            {
                trigger.Active();
            }
        }

        public void Inactive()
        {
            foreach (var trigger in triggers)
            {
                trigger.Inactive();
            }
        }

        // 序列化
        public string Serialize()
        {
            return SerializationHelper.Serialize(this);
        }

        // 反序列化
        public static TriggerGroup Deserialize(string json)
        {
            return SerializationHelper.Deserialize<TriggerGroup>(json);
        }
    }
    public class Trigger : ITrigger
    {
        public string triggerName;
        public List<Event> events = new List<Event>();
        public List<BaseCondition> conditions = new List<BaseCondition>();
        public List<BaseAction> actions = new List<BaseAction>();

        public void CheckTrigger(JObject arguments)
        {
            bool allConditionsMet = true;
            foreach (var condition in conditions)
            {
                var actualArguments = new JObject(arguments);
                actualArguments.AddRange(condition.addonArguments);
                if (!condition.CheckCondition(condition.parameters.MatchParameters(arguments)))
                {
                    allConditionsMet = false;
                    break;
                }
            }

            if (allConditionsMet)
            {
                foreach (var action in actions)
                {
                    action.Execute(action.Parameters.MatchParameters(arguments));
                }
            }
        }

        public ITrigger Copy()
        {
            var newTrigger = new Trigger
            {
                triggerName = this.triggerName
            };

            foreach (var @event in this.events)
            {
                newTrigger.events.Add(@event);
            }

            foreach (var condition in this.conditions)
            {
                newTrigger.conditions.Add(condition);
            }

            foreach (var action in this.actions)
            {
                newTrigger.actions.Add(action);
            }

            return newTrigger;
        }

        public void Active()
        {
            foreach (var @event in events)
            {
                if (Event.eventToTrigger.ContainsKey(@event))
                {
                    Event.eventToTrigger[@event].Add(this);
                }
                else
                {
                    Event.eventToTrigger.Add(@event, new HashSet<Trigger> { this });
                }
            }
        }

        public void Inactive()
        {
            foreach (var @event in events)
            {
                if (Event.eventToTrigger.ContainsKey(@event))
                {
                    Event.eventToTrigger[@event].Remove(this);
                }
            }
        }

        // 序列化
        public string Serialize()
        {
            return SerializationHelper.Serialize(this);
        }

        // 反序列化
        public static Trigger Deserialize(string json)
        {
            return SerializationHelper.Deserialize<Trigger>(json);
        }
    }

    [System.Serializable]
    public struct Parameter
    {
        public string name;
        public string type;
    }

    public static class ParameterListExtension
    {
        public static JObject MatchParameters(this List<Parameter> parameterList, JObject input)
        {
            if (parameterList == null || input == null)
            {
                throw new ArgumentNullException("参数列表或输入对象不能为空");
            }

            JObject matchedParameters = new JObject();

            foreach (var parameter in parameterList)
            {
                if (input.TryGetValue(parameter.name, out var value))
                {
                    if(value.GetType().ToString() != parameter.type)
                    {
                        Debug.LogError($"参数类型不匹配: {parameter.name},期望类型: {parameter.type},实际类型: {value.GetType()}");
                        continue;
                    }
                    matchedParameters[parameter.name] = value;
                }
            }

            return matchedParameters;
        }
    }

    public interface ITrigger
    {
        public ITrigger Copy();
        public void Active();
        public void Inactive();
    }
    public static class SerializationHelper
    {
        private static readonly JsonSerializerSettings settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Auto,
            Formatting = Formatting.Indented
        };

        public static string Serialize(object obj)
        {
            return JsonConvert.SerializeObject(obj, settings);
        }

        public static T Deserialize<T>(string json)
        {
            return JsonConvert.DeserializeObject<T>(json, settings);
        }
    }
}

/*
// 示例:自定义事件、条件和动作
namespace Script.Systems.TriggerSystem.Examples
{
    public class PlayerMovedEvent : Script.Systems.TriggerSystem.Event
    {
        public PlayerMovedEvent()
        {
            eventName = "PlayerMoved";
            parameters.Add(new Script.Systems.TriggerSystem.Parameter
            {
                name = "x",
                type = "float",
                value = 10.5f
            });
            parameters.Add(new Script.Systems.TriggerSystem.Parameter
            {
                name = "y",
                type = "float",
                value = 20.5f
            });
        }
    }

    public class HealthLowCondition : Script.Systems.TriggerSystem.Condition
    {
        public HealthLowCondition()
        {
            conditionName = "HealthLow";
            parameters.Add(new Script.Systems.TriggerSystem.Parameter
            {
                name = "threshold",
                type = "float",
                value = 30f
            });
        }

        public override bool CheckCondition()
        {
            Debug.Log($"{conditionName}: 检查血量是否低于 {parameters[0].value}");
            return true;
        }
    }

    public class ShowWarningAction : Script.Systems.TriggerSystem.Action
    {
        public ShowWarningAction()
        {
            actionName = "ShowWarning";
            parameters.Add(new Script.Systems.TriggerSystem.Parameter
            {
                name = "message",
                type = "string",
                value = "血量过低,请注意!"
            });
        }

        public override void Execute()
        {
            Debug.Log($"{actionName}: 显示警告消息: {parameters[0].value}");
        }
    }
}
*/

Event.cs:

using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using UnityEngine;

namespace Script.Systems.TriggerSystem
{
    [CreateAssetMenu(fileName = "NewEvent", menuName = "Game/Event", order = 10)]
    public class Event : ScriptableObject
    {
        public static Dictionary<Event, HashSet<Trigger>> eventToTrigger = new();

        public string eventName;
        public List<Parameter> parameters = new List<Parameter>();

        void OnEnable()
        {
            eventToTrigger.Add(this, new());
            GameDataManager.Instance.RegisterEvent(GetEventID());
            GameDataManager.Instance.AddListener(GetEventID(), (object arguments) =>
            {
                JObject argumentsJObject = arguments as JObject;

                foreach (var trigger in eventToTrigger[this])
                {
                    trigger.CheckTrigger(argumentsJObject);
                }
            });
        }

        public Event Copy()
        {
            var newEvent = Event.CreateInstance<Event>();
            newEvent.eventName = this.eventName;
            newEvent.parameters = new List<Parameter>(this.parameters);

            foreach (var param in this.parameters)
            {
                newEvent.parameters.Add(new Parameter
                {
                    name = param.name,
                    type = param.type,
                });
            }
            return newEvent;
        }

        public string GetEventID()
        {
            return $"trigger_{eventName}";
        }
    }
}

ActionManager.cs:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Script.Systems.TriggerSystem
{
    public static class ActionManager
    {
        public static Dictionary<string, Type> actionList = new Dictionary<string, Type>();

        public static BaseAction GetNewActionInstance(string typeName)
        {
            if (actionList.TryGetValue(typeName, out Type type))
            {
                return (BaseAction)Activator.CreateInstance(type);
            }
            else
            {
                Debug.LogError($"Action '{typeName}' not found.");
                return null;
            }
        }
    }

    public interface IAction
    {
        string ActionName { get; }
        List<Parameter> Parameters { get; }
        void Execute(JObject arguments);
    }

    public abstract class BaseAction : IAction
    {
        public JObject addonArguments;
        public abstract List<Parameter> Parameters { get; }
        public abstract string ActionName { get; }
        public abstract void Execute(JObject arguments);

        // 序列化 addonArguments
        public string SerializeAddonArguments()
        {
            return JsonConvert.SerializeObject(addonArguments, Formatting.Indented);
        }

        // 反序列化 addonArguments
        public void DeserializeAddonArguments(string json)
        {
            addonArguments = JsonConvert.DeserializeObject<JObject>(json);
        }
    }

    public class ShowWarningAction : BaseAction
    {
        public override string ActionName => "ShowWarning";

        static ShowWarningAction()
        {
            ActionManager.actionList.Add("ShowWarning", typeof(ShowWarningAction));
        }

        public override List<Parameter> Parameters
        {
            get
            {
                return new List<Parameter>
                {
                    new() { name = "message", type = typeof(string).ToString() }
                };
            }
        }

        public override void Execute(JObject arguments)
        {
            if (arguments.TryGetValue("message", out JToken message))
            {
                Debug.Log($"ShowWarning: {message}");
            }
            else
            {
                Debug.LogError("No message provided for ShowWarning action.");
            }
        }
    }

    public class PlaySoundAction : BaseAction
    {
        public override string ActionName => "PlaySound";

        static PlaySoundAction()
        {
            ActionManager.actionList.Add("PlaySound", typeof(PlaySoundAction));
        }

        public override List<Parameter> Parameters
        {
            get
            {
                return new List<Parameter>
                {
                    new() { name = "soundName", type = typeof(string).ToString() }
                };
            }
        }

        public override void Execute(JObject arguments)
        {
            if (arguments.TryGetValue("soundName", out JToken soundName))
            {
                Debug.Log($"Playing sound: {soundName}");
            }
            else
            {
                Debug.LogError("No soundName provided for PlaySound action.");
            }
        }
    }
}

ConditionManager.cs:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Script.Systems.TriggerSystem;
using System;
using System.Collections.Generic;
using UnityEngine;


namespace Script.Systems.TriggerSyatem
{
    public static class ConditionManager
    {
        public static Dictionary<string, Type> conditionList = new Dictionary<string, Type>();

        public static BaseCondition GetNewConditionInstance(string typeName)
        {
            if (conditionList.TryGetValue(typeName, out Type type))
            {
                return (BaseCondition)Activator.CreateInstance(type);
            }
            else
            {
                Debug.LogError($"Condition '{typeName}' not found.");
                return null;
            }
        }
    }

    public interface ICondition
    {
        string ConditionName { get; }
        bool CheckCondition(JObject arguments);
    }

    public abstract class BaseCondition : ICondition
    {
        public JObject addonArguments;
        public abstract List<Parameter> parameters { get; }
        public abstract string ConditionName { get; }
        public abstract bool CheckCondition(JObject arguments);

        // 序列化 addonArguments
        public string SerializeAddonArguments()
        {
            return JsonConvert.SerializeObject(addonArguments, Formatting.Indented);
        }

        // 反序列化 addonArguments
        public void DeserializeAddonArguments(string json)
        {
            addonArguments = JsonConvert.DeserializeObject<JObject>(json);
        }
    }

    public class CompareCondition : BaseCondition
    {
        public override string ConditionName => "CompareCondition";

        static CompareCondition()
        {
            ConditionManager.conditionList.Add("CompareCondition", typeof(CompareCondition));
        }

        public override List<Parameter> parameters
        {
            get
            {
                return new List<Parameter> {
                new() { name = "value1", type = typeof(float).ToString() },
                new() { name = "value2", type = typeof(float).ToString() }
            }
                ;
            }
        }

        public override bool CheckCondition(JObject arguments)
        {
            // 实现比较逻辑
            if (arguments.TryGetValue("value1", out JToken value1) &&
                arguments.TryGetValue("value2", out JToken value2))
            {
                return value1.ToString() == value2.ToString();
            }
            return false;
        }
    }

    public class HealthLowCondition : BaseCondition
    {
        public override string ConditionName => "HealthLow";

        static HealthLowCondition()
        {
            ConditionManager.conditionList.Add("HealthLow", typeof(HealthLowCondition));
        }

        public override List<Parameter> parameters
        {
            get
            {
                return new List<Parameter> {
                new() { name = "health", type = typeof(float).ToString() },
                new() { name = "threshold", type = typeof(float).ToString() }
            }
                ;
            }
        }

        public override bool CheckCondition(JObject arguments)
        {
            // 实现健康值检查逻辑
            if (arguments.TryGetValue("health", out JToken health) &&
                arguments.TryGetValue("threshold", out JToken threshold))
            {
                return (float)health < (float)threshold;
            }
            return false;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值