八股

  • 对象池是什么:

    • 对象池维护了一组可重复使用的对象集合。当游戏需要一个新对象时,它首先检查对象池中是否有空闲的对象可用,如果有,则重新配置该对象并将其激活使用,而不是创建一个新的实例。当对象不再需要时,它不会被销毁,而是返回到池中,等待下次重用。
    • 优点:减少内存分配;提高性能;减少垃圾收集
  • unity资源动态加载方式

    • Resources.Load:从 Resources 文件夹中加载资源。(缺点:所有放在 Resources 文件夹中的资源都会被打包进最终的游戏包中,可能会导致游戏包体积增大,且运行时管理较为复杂。)Sprite sprite = Resources.Load<Sprite>("Sprites/MySprite");
    • AssetBundle 是一种更为高级的资源打包和加载机制。通过这种方式,可以将多个资源打包成一个单独的文件,在运行时按需加载。
  • NavMesh 寻路原理

    • 首先生成 NavMesh,根据角色大小、可爬坡的坡度等,生成可行走区域的导航网格(用简化的多边形网格覆盖所有可行走的表面)
    • 寻路:在导航网格上找到一系列连接两点的多边形,这些多边形的边缘构成了路径(为了更加自然,还需要对路径进行平滑处理)
    • A*找不到路时的处理:如寻找近似路径,考虑寻找距离目标最近的可达点
  • AI 状态机实现方式

    • 基本组成:
      • 状态(State):代表 AI 在特定时间点的行为或者状态。
      • 转换(Transition):定义了从一个状态转换到另一个状态的条件。
      • 事件(Event):触发状态转换的外部输入。
    • 通常使用枚举类型来表示所有可能的状态
    • 实现原理:
      • 初始化:在 AI 启动时,初始化状态机,创建所有状态的实例,并填充状态字典。同时,设置一个变量来保存当前状态。
      • 状态更新:在 AI 的更新循环中,根据当前状态执行对应的行为(例如,调用当前状态对象的 Update 方法)。
      • 状态转换:当满足转换条件时(例如,在 Update 方法中检测到玩家进入追击范围),AI 将切换到新的状态。这通常涉及调用当前状态的 Exit 方法,更改当前状态变量,然后调用新状态的 Enter 方法。
      • 事件处理:状态机可以订阅游戏事件(如玩家的行为、游戏环境变化等),并在事件发生时评估是否需要进行状态转换。
        //接口定义
        public interface IState
        {
            void OnEnter();
            void OnExit();
            void Update();
        }
        //状态类
        public class PatrolState : IState
        {
            private readonly EnemyController enemyController;
        
            public PatrolState(EnemyController enemyController)
            {
                this.enemyController = enemyController;
            }
        
            public void OnEnter()
            {
                Debug.Log("Enter Patrol State");
            }
        
            public void OnExit()
            {
                Debug.Log("Exit Patrol State");
            }
        
            public void Update()
            {
                // 实现巡逻逻辑
                // 检查是否满足转换到其他状态的条件
                if (enemyController.IsPlayerInSight())
                {
                    enemyController.SetState(new ChaseState(enemyController));
                }
            }
        }
        //状态控制器
        public class EnemyController : MonoBehaviour
        {
            public float patrolRotateSpeed = 30f;
            private IState currentState;
        
            private void Start()
            {
                SetState(new PatrolState(this));
            }
        
            private void Update()
            {
            //状态的自动转移
                currentState?.Update();
            }
        
            public void SetState(IState newState)
            {
                currentState?.OnExit();
                currentState = newState;
                currentState.OnEnter();
            }
        }
        
  • AI 行为树的实现方式

    • 节点的分类:
      • 根节点(Root):行为树的起点,整个行为树只有一个根节点。
      • 组合节点(Composite Nodes):控制子节点的执行顺序。
        • 序列节点(Sequence):按顺序执行子节点,直到一个子节点失败或所有子节点成功。
        • 选择节点(Selector):也称为优先级选择器,按顺序执行子节点,直到一个子节点成功或所有子节点失败。
        • 并行节点(Parallel)同时执行所有子节点,直到特定数目的子节点成功或失败。
      • 叶子节点(Leaf Nodes):实际执行任务的节点
        • 动作节点(Action):执行具体的行为,如移动、攻击等。
        • 条件节点(Condition):检查某个条件是否满足
    • 工作原理:行为树从根节点开始执行,通过递归遍历树中的节点来控制AI的行为。每个节点根据其类型和逻辑决定执行哪个子节点,直到达到叶子节点执行具体动作或判断条件。节点执行的结果通常是成功、失败或运行中这三种状态之一。
      //定义节点基类
      public abstract class BTNode
      {
          public abstract bool Execute();
      }
      //实现组合节点
      // 选择器节点
      public class Selector : BTNode
      {
          private List<BTNode> children = new List<BTNode>();
      
          public Selector(List<BTNode> children)
          {
              this.children = children;
          }
      
          public override bool Execute()
          {
              foreach (var child in children)
              {
                  if (child.Execute())
                  {
                      return true;
                  }
              }
              return false;
          }
      }
      
      // 序列节点
      public class Sequence : BTNode
      {
          private List<BTNode> children = new List<BTNode>();
      
          public Sequence(List<BTNode> children)
          {
              this.children = children;
          }
      
          public override bool Execute()
          {
              foreach (var child in children)
              {
                  if (!child.Execute())
                  {
                      return false;
                  }
              }
              return true;
          }
      }
      //实现行为节点
      // 一个简单的行为节点示例:成功节点
      public class SucceedNode : BTNode
      {
          public override bool Execute()
          {
              // 实现具体行为
              Debug.Log("Action Succeeded");
              return true; // 总是返回成功
          }
      }
      
      // 条件节点示例:检查条件
      public class CheckConditionNode : BTNode
      {
          private Func<bool> condition;
      
          public CheckConditionNode(Func<bool> condition)
          {
              this.condition = condition;
          }
      
          public override bool Execute()
          {
              return condition();
          }
      }
      //构建行为树并执行
      public class BehaviourTreeController : MonoBehaviour
      {
          private BTNode root;
      
          private void Start()
          {
              BuildBehaviourTree();
          }
      
          private void BuildBehaviourTree()
          {
              // 构建行为树结构
              root = new Selector(new List<BTNode>
              {
                  new Sequence(new List<BTNode>
                  {
                      new CheckConditionNode(() => true), // 条件示例
                      new SucceedNode() // 行为示例
                  })
                  // 在这里添加更多的节点
              });
          }
      
          private void Update()
          {
              if (root != null)
              {
                  root.Execute();
              }
          }
      }
      
  • A*算法的优化

    • 分层路径规划(Hierarchical Path Planning):在复杂的环境中,可以将地图分解为几个层次,先在一个较粗糙的层次上进行寻路,然后在细节层次上进行局部优化。这种方法可以大大减少需要考虑的节点数量。
    • 增量式路径搜索(Incremental Search):当环境发生轻微变化时,可以利用之前的搜索结果来加快寻路。例如,D* Lite 算法就是基于 A*的增量式搜索算法,适用于动态环境下的路径规划。
    • 对于格点地图优化:在特定的场景中,如格点地图上,跳点搜索(JPS)是对 A*算法的一种优化。它通过跳过某些节点来减少需要考虑的节点总数,显著提高了搜索效率,尤其是在开放区域较多的地图上。