开发者

C#和Unity中的解释器模式使用方式

目录
  • 概述
  • 一、解释器模式的核心概念
    • 1. 解释器模式的主要角色
    • 2. 解释器模式的 UML 类图
  • 二、解释器模式的实现方式
    • 1. 基础实现(布尔表达式解释器)
    • 2. 数学表达式解释器(四则运算)
  • 三、解释器模式的特点
    • 1. 优点
    • 2. 缺点
  • 四、解释器模式的使用场景
    • 1. 典型应用场景
    • 2. 具体案例
  • 五、解释器模式的进阶话题
    • 1. 语法树构建
    • 2. 使用访问者模式遍历语法树
    • 3. 解释器模式与编译器技术的区别
  • 六、解释器模式的最佳实践
    • 七、解释器模式与其他模式的关系
      • 八、现代替代方案
        • 九、在Uniry中的应用
          • 示例1:简单数学表达式解释器
          • 示例2:简单AI行为脚本解释器
          • 示例3:对话条件解释器
          • 在Unity中的实现建议
        • 总结

          概述

          解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法表示,并提供一个解释器来解释该语言中的句子。

          这种模式主要用于处理特定类型的问题,特别是那些可以被表示为语言句子的领域。

          一、解释器模式的核心概念

          1. 解释器模式的主要角色

          AbstractExpression(抽象表达式)

          • 声明一个抽象的解释操作接口

          TerminalExpression(终结符表达式)

          • 实现与文法中的终结符相关联的解释操作
          • 句子中的每个终结符都需要一个实例

          NonterminalExpression(非终结符表达式)

          • 文法中的每条规则都需要一个非终结符表达式类
          • 包含对其他表达式的引用(可能是终结符或非终结符)

          Context(上下文)

          • 包含解释器之外的全局信息

          Client(客户端)

          • 构建(或被给定)表示该语言中特定句子的抽象语法树
          • 调用解释操作

          2. 解释器模式的 UML 类图

          C#和Unity中的解释器模式使用方式

          二、解释器模式的实现方式

          1. 基础实现(布尔表达式解释器)

          // 上下文 - 存储变量值
          public class Context
          {
              private readonly Dictionary<string, bool> _variables = new();
            
              public bool GetVariable(string name) => _variables.TryGetValue(name, out var value) ? value : false;
              public void SetVariable(string name, bool value) => _variables[name] = value;
          }
          
          // 抽象表达式
          public interface IExpression
          {
              bool Interpret(Context context);
          }
          
          // 终结符表达式 - 变量
          public class VariableExpression : IExpression
          {
              private readonly string _name;
            
              public VariableExpression(string name) => _name = name;
            
              public bool Interpret(Context context) => context.GetVariable(_name);
          }
          
          // 非终结符表达式 - AND
          public class AndExpression : IExpression
          {
              private readonly IExpression _left;
              private readonly IExpression _right;
            
              public AndExpression(IExpression left, IExpression right)
              {
                  _left = left;
                  _right = right;
              }
            
              public bool Interpret(Context context) => _lefandroidt.Interpret(context) && _right.Interpret(context);
          }
          
          // 非终结符表达式 - OR
          public class OrExpression : IExpression
          {
              private readonly IExpression _left;
              private readonly IExpression _right;
            
              public OrExpression(IExpression left, IExpression right)
              {
                  _left = left;
                  _right = right;
              }
            
              public bool Interpret(Context context) => _left.Interpret(context) || _right.Interpret(context);
          }
          
          // 非终结符表达式 - NOT
          public class NotExpression : IExpression
          {
              private readonly IExpression _expression;
            
              public NotExpression(IExpression expression) => _expression = expression;
            
              public bool Interpret(Context context) => !_expression.Interpret(context);
          }
          
          // 客户端代码
          class Program
          {
              static void Main()
              {
                  // 创建上下文并设置变量
                  var context = new Context();
                  context.SetVariable("A", true);
                  context.SetVariable("B", false);
                  context.SetVariable("C", true);
            
                  // 构建表达式: (A AND B) OR (NOT C)
                  var expression = new OrExpression(
                      new AndExpression(
                          new VariableExpression("A"),
                          new VariableExpression("B")),
                      new NotExpression(
                          new VariableExpression("C")));
            
                  // 解释执行
                  bool result = expression.Interpret(context);
                  Console.WriteLine($"表达式结果为: {result}"); // 输出 False
              }
          }
          

          2. 数学表达式解释器(四则运算)

          // 上下文 - 存储变量值
          public class MathContext
          {
              private readonly Dictionary<string, int> _variables = new();
            
              public int GetVariable(string name) => _variables.TryGetValue(name, out var value) ? value : 0;
              public void SetVariable(string name, int value) => _variables[name] = value;
          }
          
          // 抽象表达式
          public interface IMathExpression
          {
              int Interpret(MathContext context);
          }
          
          // 终结符表达式 - 数字
          public class NumberExpression : IMathExpression
          {
              private readonly int _number;
            
              public NumberExpression(int number) => _number = number;
            
              public int Interpret(MathContext context) => _number;
          }
          
          // 终结符表达式 - 变量
          public class VariableMathExpression : IMathExpression
          {
              private readonly string _name;
            
              public VariableMathExpression(string name) => _name = name;
            
              public int Interpret(MathContext context) => context.GetVariable(_name);
          }
          
          // 非终结符表达式 - 加法
          public class AddExpression : IMathExpression
          {
              private readonly IMathExpression _left;
              private readonly IMathExpression _right;
            
              public AddExpression(IMathExpression left, IMathExpression right)
              {
                  _left = left;
                  _right = right;
              }
            
              public int Interpret(MathContext context) => _left.Interpret(context) + _right.Interpret(context);
          }
          
          // 非终结符表达式 - 减法
          public class SubtractExpression : IMathExpression
          {
              private readonly IMathExpression _left;
              private readonly IMathExpression _right;
            
              public SubtractExpression(IMathExpression left, IMathExpression right)
              {
                  _left = left;
                  _right = right;
              }
            
              public int Interpret(MathContext context) => _left.Interpret(context) - _right.Interpret(context);
          }
          
          // 使用示例
          var context = new MathContext();
          context.SetVariable("x", 10);
          context.SetVariable("y", 5);
          
          // 构建表达式: (x + 5) - (y - 2)
          var expression = new SubtractExpression(
              new AddExpression(
                  new VariableMathExpression("x"),
                  new NumberExpression(5)),
              new SubtractExpression(
                  new VariableMathExpression("y"),
                  new NumberExpression(2)));
          
          int result = expression.Interpret(context); // 结果为 12
          

          三、解释器模式的特点

          1. 优点

          • 易于扩展语法:新增表达式类即可扩展语言
          • 易于实现简单语言:对于简单文法实现直观
          • 分离语法分析:将语编程客栈法分析与表达式执行分离
          • 灵活性强:可以动态改变解释方式

          2. 缺点

          • 复杂度高:对于复杂文法,类数量会急剧增加
          • 效率较低:解释器模式通常比编译器效率低
          • 难以维护复杂文法:文法规则过多时代码难以维护
          • 应用场景有限:仅适用于特定领域问题

          四、解释器模式的使用场景

          1. 典型应用场景

          领域特定语言(DSL)

          • 正则表达式解释器
          • SQL条件解释器
          • 业务规则引擎

          数学表达式处理

          • 科学计算器
          • 公式编辑器
          • 财务计算系统

          配置文件解析

          • 自定义配置语法
          • 过滤条件解析

          编译器/解释器

          • 简单编程语言解释器
          • 模板引擎

          游戏开发

          • 游戏AI行为脚本
          • 技能效果描述语言

          2. 具体案例

          案例1:正则表达式解释器(简化版)
          // 抽象表达式
          public interface IRegexExpression
          {
              bool Interpret(string input);
          }
          
          // 终结符表达式 - 字符匹配
          public class CharExpression : IRegexExpression
          {
              private readonly char _char;
            
              public CharExpression(char c) => _char = c;
            
              public bool Interpret(string input) => input.Length > 0 && input[0] == _char;
          }
          
          // 非终结符表达式 - 序列
          public class SequenceExpression : IRegexExpression
          {
              private readonly List<IRegexExpression> _expressionsphp;
            
              public SequenceExpression(params IRegexExpression[] expressions) 
                  => _expressions = new List<IRegexExpression>(expressions);
            
              public bool Interpret(string input)
              {
                  string remaining = input;
                  foreach (var expr in _expressions)
                  {
                      if (!expr.Interpret(remaining)) return false;
                      remaining = remaining.Substring(1);
                  }
                  return true;
              }
          }
          
          // 非终结符表达式 - 或
          public class OrExpression : IRegexExpression
          {
              private readonly IRegexExpression _left;
              private readonly IRegexExpression _right;
            
              public OrExpression(IRegexExpression left, IRegexExpression right)
              {
                  _left = left;
                  _right = right;
              }
            
              public bool Interpret(string input) => _left.Interpret(input) || _right.Interpret(input);
          }
          
          // 使用
          var regex = new SequenceExpression(
              new CharExpression('a'),
              new OrExpression(
                  new CharExpression('b'),
                  new CharExpression('c')));
          
          bool match1 = regex.Interpret("ab"); // true
          bool match2 = regex.Interpret("ac"); // true
          bool match2 = regex.Interpret("ad"); // false
          
          案例2:业务规则引擎
          // 业务规则上下文
          public class BusinessContext
          {
           js   public Dictionary<string, object> Data { get; } = new();
          }
          
          // 条件表达式
          public class ConditionExpression
          {
              private readonly string _field;
              private readonly object _value;
              private readonly string _operator;
            
              public ConditionExpression(string field, string op, object value)
              {
                  _field = field;
                  _operator = op;
                  _value = value;
              }
            
              public bool Interpret(BusinessContext context)
              {
                  if (!context.Data.TryGetValue(_field, out var fieldValue)) return false;
            
                  return _operator switch
                  {
                      "==" => Equals(fieldValue, _value),
                      ">" => Comparer.Default.Compare(fieldValue, _value) > 0,
                      "<" => Comparer.Default.Compare(fieldValue, _value) < 0,
                      _ => false
                  };
              }
          }
          
          // 规则集
          public class RuleSet
          {
              private readonly List<ConditionExpression> _conditions = new();
            
              public void AddCondition(ConditionExpression condition) => _conditions.Add(condition);
            
              public bool EvaLuate(BusinessContext context)
              {
                  return _conditions.All(c => c.Interpret(context));
              }
          }
          
          // 使用
          var context = new BusinessContext();
          context.Data["Age"] = 25;
          context.Data["Salary"] = 50000;
          context.Data["IsEmployed"] = true;
          
          var rule = new RuleSet();
          rule.AddCondition(new ConditionExpression("Age", ">", 18));
          rule.AddCondition(new ConditionExpression("Salary", ">", 40000));
          rule.AddCondition(new ConditionExpression("IsEmployed", "==", true));
          
          bool eligible = rule.Evaluate(context); // true
          

          五、解释器模式的进阶话题

          1. 语法树构建

          通常需要配合解析器将输入文本转换为抽象语法树(AST):

          public class Parser
          {
              public IExpression Parse(string input)
              {
                  // 简单实现 - 实际需要更复杂的词法/语法分析
                  if (input.Contains("AND"))
                  {
                      var parts = input.Split(new[] {" AND "}, StringSplitOptions.None);
                      return new AndExpression(Parse(parts[0]), Parse(parts[1]));
                  }
                  else if (input.Contains("OR"))
                  {
                      var parts = input.Split(new[] {" OR "}, StringSplitOptions.None);
                      return new OrExpression(Parse(parts[0]), Parse(parts[1]));
                  }
                  else
                  {
                      return new VariableExpression(input.Trim());
                  }
              }
          }
          
          // 使用
          var parser = new Parser();
          var expression = parser.Parse("A AND B OR C");
          

          2. 使用访问者模式遍历语法树

          public interface IExpressionVisitor
          {
              void Visit(VariableExpression exp);
              void Visit(AndExpression exp);
              void Visit(OrExpression exp);
          }
          
          public class PrintVisitor : IExpressionVisitor
          {
              public void Visit(VariableExpression exp) => Console.Write(exp.Name);
            
              public void Visit(AndExpression exp)
              {
                  Console.Write("(");
                  exp.Left.Accept(this);
                  Console.Write(" AND ");
                  exp.Right.Accept(this);
                  Console.Write(")");
              }
            
              public void Visit(OrExpression exp)
              {
                  Console.Write("(");
                  exp.Left.Accept(this);
                  Console.Write(" OR ");
                  exp.Right.Accept(this);
                  Console.Write(")");
              }
          }
          
          // 在表达式接口中添加Accept方法
          public interface IExpression
          {
              bool Interpret(Context context);
              void Accept(IExpressionVisitor visitor);
          }
          

          3. 解释器模式与编译器技术的区别

          特性解释器模式编译器
          执行方式直接执行语法树生成中间代码/机器码
          效率较低(每次解释)较高(预先编译)
          灵活性高(可动态修改)低(编译后固定)
          实现复杂度相对简单复杂
          适用场景简单DSL、动态需求通用编程语言

          六、解释器模式的最佳实践

          控制文法复杂度

          • 解释器模式适合相对简单的文法(BNF范式不超过一页)
          • 复杂文法考虑使用解析器生成器(如ANTLR)

          共享终结符

          • 终结符表达式通常是无状态的,可以共享实例

          分离解析与解释

          • 使用单独解析器构建语法树
          • 保持解释器专注于执行

          考虑性能优化

          • 缓存解释结果
          • 预编译常用表达式

          合理使用组合

          • 与访问者模式结合遍历语法树
          • 与享元模式共享终结符

          七、解释器模式与其他模式的关系

          与组合模式

          • 抽象语法树就是组合模式的应用
          • 非终结符表达式是组合节点,终结符表达式是叶节点

          与访问者模式

          • 访问者模式可用于在语法树上执行多种操作
          • 分离解释逻辑与语法树结构

          与享元模式

          • 共享终结符表达式实例
          • 减少内存使用

          与策略模式

          • 解释器模式可以看作是在语法树上应用的策略模式

          八、现代替代方案

          对于复杂语言处理,现代开发中更常用:

          解析器生成器

          • ANTLR
          • Yacc/Lex

          表达式树

          • C#的Expression<T>
          • 动态构建和执行表达式

          脚本引擎

          • Roslyn脚本API
          • Lua、python等嵌入式脚本

          总结一下:

          解释器模式在C#中适用于:

          • 特定领域语言:需要为特定领域定义简单语言
          • 灵活规则系统:业务规则需要动态配置
          • 数学表达式:需要解释执行公式

          关键优势

          ✅ 易于实现简单语言的解释执行

          ✅ 灵活扩展语法规则

          ✅ 分离语法定义与执行

          适用限制

          ❌ 不适合复杂文法(类爆炸问题)

          ❌ 性能不如编译执行

          ❌ 维护成本随文法复杂度增加

          在实际开发中,应权衡需求复杂度,对于简单DSL可以使用解释器模式快速实现,对于复杂语言处理建议使用专业解析工具。

          九、在Uniry中的应用

          示例1:简单数学表达式解释器

          using UnityEngine;
          using System.Collections.Generic;
          
          // 抽象表达式
          public abstract class Expression
          {
              public abstract int Interpret(Dictionary<string, int> context);
          }
          
          // 终结符表达式 - 变量
          public class VariableExpression : Expression
          {
              private string name;
            
              public VariableExpression(string name)
              {
                  this.name = name;
              }
            
              public override int Interpret(Dictionary<string, int> context)
              {
                  // 从上下文中获取变量值
                  if (context.ContainsKey(name))
                  {
                      return context[name];
                  }
                  throw new System.Exception($"变量 {name} 未定义");
              }
          }
          
          // 终结符表达式 - 常量
          public class ConstantExpression : Expression
          {
              private int value;
            
              public ConstantExpression(int value)
              {
                  this.value = value;
              }
            
              public override int Interpret(Dictionary<string, int> context)
              {
                  return value;
              }
          }
          
          // 非终结符表达式 - 加法
          public class AddExpression : Expression
          {
              private Expression left;
              private Expression right;
            
              public AddExpression(Expression left, Expression right)
              {
                  this.left = left;
                  this.right = right;
              }
            
              public override int Interpret(Dictionary<string, int> context)
              {
                  return left.Interpret(context) + right.Interpret(context);
              }
          }
          
          // 非终结符表达式 - 减法
          public class SubtractExpression : Expression
          {
              private Expression left;
              private Expression right;
            
              public SubtractExpression(Expression left, Expression right)
              {
                  this.left = left;
                  this.right = right;
              }
            
              public override int Interpret(Dictionary<string, int> context)
              {
                  return left.Interpret(context) - right.Interpret(context);
              }
          }
          
          // 非终结符表达式 - 乘法
          public class MultiplyExpression : Expression
          {
              private Expression left;
              private Expression right;
            
              public MultiplyExpression(Expression left, Expression right)
              {
                  this.left = left;
                  this.right = right;
              }
            
              public override int Interpret(Dictionary<string, int> context)
              {
                  return left.Interpret(context) * right.Interpret(context);
              }
          }
          
          // 表达式解析器
          public class ExpressionParser
          {
              private Dictionary<string, int> variables = new Dictionary<string, int>();
            
              // 解析表达式字符串
              public Expression Parse(string expression)
              {
                  // 这里简化处理,实际应用中需要更复杂的解析逻辑
                  if (expression.Contains("+"))
                  {
                      string[] parts = expression.Split('+');
                      return new AddExpression(Parse(parts[0]), Parse(parts[1]));
                  }
                  else if (expression.Contains("-"))
                  {
                      string[] parts = expression.Split('-');
                      return new SubtractExpression(Parse(parts[0]), Parse(parts[1]));
                  }
                  else if (expression.Contains("*"))
                  {
                      string[] parts = expression.Split('*');
                      return new MultiplyExpression(Parse(parts[0]), Parse(parts[1]));
                  }
                  else if (int.TryParse(expression, out int value))
                  {
                      return new ConstantExpression(value);
                  }
                  else
                  {
                      return new VariableExpression(expression);
                  }
              }
            
              // 设置变量值
              public void SetVariable(string name, int value)
              {
                  variables[name] = value;
              }
            
              // 获取当前变量表
              public Dictionary<string, int> GetContext()
              {
                  return variables;
              }
          }
          
          // 测试代码
          public class MathInterpreterTest : MonoBehaviour
          {
              void Start()
              {
                  ExpressionParser parser = new ExpressionParser();
            
                  // 设置变量
                  parser.SetVariable("x", 10);
                  parser.SetVariable("y", 5);
            
                  // 解析并计算表达式
                  TestExpression(parser, "x+y");       // 10 + 5 = 15
                  TestExpression(parser, "x-y");       // 10 - 5 = 5
                  TestExpression(parser, "x*y");       // 10 * 5 = 50
                  TestExpression(parser, "x+y*2");     // 10 + (5 * 2) = 20
              }
            
              void TestExpression(ExpressionParser parser, string expression)
              {
                  Expression exp = parser.Parse(expression);
                  int result = exp.Interpret(parser.GetContext());
                  Debug.Log($"{expression} = {result}");
              }
          }
          

          示例2:简单AI行为脚本解释器

          using UnityEngine;
          using System.Collections.Generic;
          
          // 抽象行为表达式
          public abstract class AIActionExpression
          {
              public abstract void Interpret(AIContext context);
          }
          
          // 移动行为
          public class MoveAction : AIActionExpression
          {
              private string direction;
              private float distance;
            
              public MoveAction(string direction, float distance)
              {
                  this.direction = direction.ToLower();
                  this.distance = distance;
              }
            
              public override void Interpret(AIContext context)
              {
                  Vector3 moveVector = Vector3.zero;
            
                  switch (direction)
                  {
                      case "forward":
                          moveVector = context.AITransform.forward * distance;
                          break;
                      case "back":
                          moveVector = -context.AITransform.forward * distance;
                          break;
                      case "left":
                          moveVector = -context.AITransform.right * distance;
                          break;
                      case "right":
                          moveVector = context.AITransform.right * distance;
                          break;
                      case "up":
                          moveVector = context.AITransform.up * distance;
                          break;
                      case "down":
                          moveVector = -context.AITransform.up * distance;
                          break;
                  }
            
                  context.AITransform.position += moveVector;
                  Debug.Log($"AI移动: {direction} {distance}米");
              }
          }
          
          // 等待行为
          public class WaitAction : AIActionExpression
          {
              private float seconds;
            
              public WaitAction(float seconds)
              {
                  this.seconds = seconds;
              }
            
              public override void Interpret(AIContext context)
              {
                  Debug.Log($"AI等待: {seconds}秒");
                  // 实际游戏中可以使用协程实现等待
              }
          }
          
          // 攻击行为
          public class AttackAction : AIActionExpression
          {
              private string target;
            
              public AttackAction(string target)
              {
                  this.target = target;
              }
            
              public override void Interpret(AIContext context)
              {
                  Debug.Log($"AI攻击: {target}");
                  // 实际游戏中这里会实现攻击逻辑
              }
          }
          
          // AI行为序列
          public class ActionSequence : AIActionExpression
          {
              private List<AIActionExpression> actions = new List<AIActionExpression>();
            
              public void AddAction(AIActionExpression action)
              {
                  actions.Add(action);
              }
            
              public override void Interpret(AIContext context)
              {
                  foreach (var action in actions)
                  {
                      action.Interpret(context);
                  }
              }
          }
          
          // AI上下文
          public class AIContext
          {
              public Transform AITransform { get; set; }
              public Dictionary<string, object> Variables { get; } = new Dictionary<string, object>();
          }
          
          // AI脚本解析器
          public class AIScriptParser
          {
              public AIActionExpression Parse(string script)
              {
                  ActionSequence sequence = new ActionSequence();
            
                  // 分割脚本为多行
                  string[] lines = script.Split(new[] { '\n', ';' }, System.StringSplitOptions.RemoveEmptyEntries);
            
                  foreach (string line in lines)
                  {
                      string trimmedLine = line.Trim();
                      if (string.IsNullOrEmpty(trimmedLine)) continue;
                
                      // 分割命令和参数
                      string[] parts = trimmedLine.Split(new[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries);
                      if (parts.Length == 0) continue;
                
                      string command = parts[0].ToLower();
                
                      switch (command)
                      {
                          case "move":
                              if (parts.Length 编程客栈>= 3)
                              {
                                  string direction = parts[1];
                                  if (float.TryParse(parts[2], out float distance))
                                  {
                                      sequence.AddAction(new MoveAction(direction, distance));
                                  }
                              }
                              break;
                    
                          case "wait":
                              if (parts.Length >= 2 && float.TryParse(parts[1], out float seconds))
                              {
                                  sequence.AddAction(new WaitAction(seconds));
                              }
                              break;
                    
                          case "attack":
                              if (parts.Length >= 2)
                              {
                                  sequence.AddAction(new AttackAction(parts[1]));
                              }
                              break;
                      }
                  }
            
                  return sequence;
              }
          }
          
          // AI控制器
          public class AIController : MonoBehaviour
          {
              public string aiScript = @"
                  move forward 5
                  wait 2
                  attack player
                  move back 3
                  wait 1
              ";
            
              private AIContext context;
              private AIActionExpression behavior;
            
              void Start()
              {
                  context = new AIContext { AITransform = transform };
            
                  AIScriptParser parser = new AIScriptParser();
                  behavior = parser.Parse(aiScript);
            
                  // 执行AI脚本
                  behavior.Interpret(context);
              }
          }
          

          示例3:对话条件解释器

          using UnityEngine;
          using System.Collections.Generic;
          
          // 抽象条件表达式
          public abstract class ConditionExpression
          {
              public abstract bool Interpret(DialogueContext context);
          }
          
          // 变量条件
          public class VariableCondition : ConditionExpression
          {
              private string variableName;
              private int expectedValue;
              private string comparison; // "==", ">", "<", etc.
            
              public VariableCondition(string variableName, string comparison, int expectedValue)
              {
                  this.variableName = variableName;
                  this.comparison = comparison;
                  this.expectedValue = expectedValue;
              }
            
              public override bool Interpret(DialogueContext context)
              {
                  if (!context.Variables.ContainsKey(variableName))
                  {
                      Debug.LogWarning($"变量 {variableName} 未定义");
                      return false;
                  }
            
                  int actualValue = context.Variables[variableName];
            
                  switch (comparison)
                  {
                      case "==": return actualValue == expectedValue;
                      case "!=": return actualValue != expectedValue;
                      case ">": return actualValue > expectedValue;
                      case "<": return actualValue < expectedValue;
                      case ">=": return actualValue >= expectedValue;
                      case "<=": return actualValue <= expectedValue;
                      default:
                          Debug.LogWarning($"未知比较运算符: {comparison}");
                          return false;
                  }
              }
          }
          
          // 逻辑与条件
          public class AndCondition : ConditionExpression
          {
              private ConditionExpression left;
              private ConditionExpression right;
            
              public AndCondition(ConditionExpression left, ConditionExpression right)
              {
                  this.left = left;
                  this.right = right;
              }
            
              public override bool Interpret(DialogueContext context)
              {
                  return left.Interpret(context) && right.Interpret(context);
              }
          }
          
          // 逻辑或条件
          public class OrCondition : ConditionExpression
          {
              private ConditionExpression left;
              private ConditionExpression right;
            
              public OrCondition(ConditionExpression left, ConditionExpression right)
              {
                  this.left = left;
                  this.right = right;
              }
            
              public override bool Interpret(DialogueContext context)
              {
                  return left.Interpret(context) || right.Interpret(context);
              }
          }
          
          // 非条件
          public class NotCondition : ConditionExpression
          {
              private ConditionExpression condition;
            
              public NotCondition(ConditionExpression condition)
              {
                  this.condition = condition;
              }
            
              public override bool Interpret(DialogueContext context)
              {
                  return !condition.Interpret(context);
              }
          }
          
          // 对话上下文
          public class DialogueContext
          {
              public Dictionary<string, int> Variables { get; } = new Dictionary<string, int>();
          }
          
          // 条件解析器
          public class ConditionParser
          {
              public ConditionExpression Parse(string conditionStr)
              {
                  // 这里简化处理,实际应用中需要更复杂的解析逻辑
                  if (conditionStr.Contains("&&"))
                  {
                      string[] parts = conditionStr.Split(new[] { "&&" }, System.StringSplitOptions.RemoveEmptyEntries);
                      return new AndCondition(Parse(parts[0]), Parse(parts[1]));
                  }
                  else if (conditionStr.Contains("||"))
                  {
                      string[] parts = conditionStr.Split(new[] { "||" }, System.StringSplitOptions.RemoveEmptyEntries);
                      return new OrCondition(Parse(parts[0]), Parse(parts[1]));
                  }
                  else if (conditionStr.StartsWith("!"))
                  {
                      return new NotCondition(Parse(conditionStr.Substring(1)));
                  }
                  else
                  {
                      // 解析变量条件 如: "health > 50"
                      string[] parts = conditionStr.Split(new[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries);
                      if (parts.Length == 3)
                      {
                          string varName = parts[0];
                          string op = parts[1];
                          if (int.TryParse(parts[2], out int value))
                          {
                              return new VariableCondition(varName, op, value);
                          }
                      }
                  }
            
                  throw new System.Exception($"无法解析条件: {conditionStr}");
              }
          }
          
          // 对话选项
          public class DialogueOption
          {
              public string Text { get; }
              public ConditionExpression Condition { get; }
            
              public DialogueOption(string text, ConditionExpression condition = null)
              {
                  Text = text;
                  Condition = condition;
              }
            
              public bool IsAvailable(DialogueContext context)
              {
                  return Condition == null || Condition.Interpret(context);
              }
          }
          
          // 测试代码
          public class DialogueConditionTest : MonoBehaviour
          {
              void Start()
              {
                  DialogueContext context = new DialogueContext();
                  context.Variables["health"] = 75;
                  context.Variables["hasKey"] = 1;
                  context.Variables["karma"] = -10;
            
                  ConditionParser parser = new ConditionParser();
            
                  TestCondition(parser, context, "health > 50");  // true
                  TestCondition(parser, context, "hasKey == 1"); // true
                  TestCondition(parser, context, "karma >= 0");   // false
                  TestCondition(parser, context, "health > 50 && hasKey == 1"); // true
                  TestCondition(parser, context, "health > 50 || karma >= 0");  // true
                  TestCondition(parser, context, "!hasKey == 1"); // false
            
                  // 创建对话选项
                  DialogueOption option1 = new DialogueOption("攻击敌人", parser.Parse("health > 50"));
                  DialogueOption option2 = new DialogueOption("和平解决", parser.Parse("karma >= 0"));
                  DialogueOption option3 = new DialogueOption("逃跑", null); // 无条件
            
                  Debug.Log($"选项1可用: {option1.IsAvailable(context)}"); // true
                  Debug.Log($"选项2可用: {option2.IsAvailable(context)}"); // false
                  Debug.Log($"选项3可用: {option3.IsAvailable(context)}"); // true
              }
            
              void TestCondition(ConditionParser parser, DialogueContext context, string conditionStr)
              {
                  ConditionExpression condition = parser.Parse(conditionStr);
                  bool result = condition.Interpret(context);
                  Debug.Log($"{conditionStr} = {result}");
              }
          }
          

          在Unity中的实现建议

          1. 结合ScriptableObject:可以将表达式配置为ScriptableObject,便于在编辑器中设置
          2. 使用解析器生成器:对于复杂文法,考虑使用ANTLR等解析器生成器
          3. 限制文法复杂度:保持解释的语言简单,避免过度设计
          4. 缓存解析结果:对于频繁使用的表达式,可以缓存解析结果提高性能
          5. 与事件系统结合:将解释结果转换为游戏事件,降低耦合度

          总结

          以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

          0

          上一篇:

          下一篇:

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          最新开发

          开发排行榜