首页 > 其他分享 >CryEngine引擎开发:角色控制与状态机_CryEngine中的AI角色控制

CryEngine引擎开发:角色控制与状态机_CryEngine中的AI角色控制

时间:2024-12-02 21:29:57浏览次数:6  
标签:const 角色 -- self 状态机 CryEngine end

CryEngine中的AI角色控制

在上一节中,我们探讨了CryEngine的基本架构和如何设置开发环境。接下来,我们将深入探讨CryEngine中的AI角色控制,这是动作游戏开发中至关重要的一部分。AI角色控制不仅决定了NPC(非玩家角色)的行为模式,还直接影响游戏的沉浸感和玩家的体验。在这一节中,我们将详细介绍CryEngine中的AI角色控制机制,包括状态机的设计、行为树的使用以及如何实现复杂的AI逻辑。

AI角色控制概述

AI角色控制是游戏开发中的一项复杂任务,涉及到多个子系统的协同工作。在CryEngine中,AI角色控制主要通过以下几种方式实现:

  1. 状态机(State Machine):用于管理角色的不同状态及其转换。

  2. 行为树(Behavior Tree):用于定义角色的行为逻辑。

  3. 动画系统:与AI控制紧密结合,实现角色的动作表现。

  4. 物理系统:处理角色的物理交互和运动。

状态机

状态机是一种常用的AI控制方法,通过定义不同的状态和状态之间的转换来管理角色的行为。在CryEngine中,状态机可以通过Lua脚本或C++代码实现。

状态机的基本原理

状态机由多个状态和状态之间的转换规则组成。每个状态可以包含一系列的动作或逻辑,当满足特定条件时,角色可以从一个状态转换到另一个状态。

状态机的实现

在CryEngine中,可以通过Lua脚本来实现状态机。以下是一个简单的例子,展示了如何定义一个状态机并管理角色的状态转换。


-- 定义状态机

local StateMachine = {

  states = {},

  currentState = nil

}



-- 定义状态

local IdleState = {

  name = "Idle",

  update = function(self, deltaTime)

    -- 检查是否有敌人进入视野

    if self:isEnemyInSight() then

      self:changeState(AlertState)

    end

  end,

  isEnemyInSight = function(self)

    -- 检查是否有敌人在视野范围内

    return false

  end,

  changeState = function(self, newState)

    -- 切换到新状态

    self.currentState = newState

    newState:enter()

  end

}



local AlertState = {

  name = "Alert",

  enter = function(self)

    -- 进入警戒状态时的初始化操作

    print("进入警戒状态")

  end,

  update = function(self, deltaTime)

    -- 检查是否有敌人离开视野

    if not self:isEnemyInSight() then

      self:changeState(IdleState)

    end

  end,

  isEnemyInSight = function(self)

    -- 检查是否有敌人在视野范围内

    return true

  end,

  changeState = function(self, newState)

    -- 切换到新状态

    self.currentState = newState

    newState:enter()

  end

}



-- 初始化状态机

function StateMachine:init()

  self.states["Idle"] = IdleState

  self.states["Alert"] = AlertState

  self:changeState(IdleState)

end



-- 更新状态机

function StateMachine:update(deltaTime)

  self.currentState:update(deltaTime)

end



-- 切换状态

function StateMachine:changeState(newState)

  self.currentState:changeState(newState)

end



-- 创建并初始化状态机实例

local aiStateMachine = StateMachine

aiStateMachine:init()



-- 在每一帧更新状态机

function Update(deltaTime)

  aiStateMachine:update(deltaTime)

end

行为树

行为树是一种更高级的AI控制方法,通过树状结构来定义角色的行为逻辑。行为树可以实现更复杂的决策和任务执行,适用于需要精细控制的AI角色。

行为树的基本原理

行为树由多个节点组成,每个节点可以是任务节点或控制节点。任务节点执行具体的动作,控制节点决定任务节点的执行顺序和条件。常见的控制节点包括选择节点、序列节点和条件节点。

行为树的实现

在CryEngine中,行为树可以通过C++代码实现。以下是一个简单的例子,展示了如何定义一个行为树并管理角色的行为逻辑。


#include "CryEngine/CryAISystem/IAIObject.h"

#include "CryEngine/CryAISystem/IAIActor.h"

#include "CryEngine/CryAISystem/IAIActorProxy.h"

#include "CryEngine/CryAISystem/IAIAction.h"

#include "CryEngine/CryAISystem/IAIActionTree.h"



// 定义行为树节点

class IdleAction : public IAIAction

{

public:

  AIACTION_IMPLEMENT(IdleAction);



  virtual EAIActionResult Execute(const SAIActionParams& params) override

  {

    // 检查是否有敌人进入视野

    if (params.pAI->GetAIObject()->IsEnemyInSight())

    {

      // 如果有敌人,返回失败

      return eAIAR_Failure;

    }



    // 否则,继续执行

    return eAIAR_Running;

  }

};



class AlertAction : public IAIAction

{

public:

  AIACTION_IMPLEMENT(AlertAction);



  virtual EAIActionResult Execute(const SAIActionParams& params) override

  {

    // 检查是否有敌人离开视野

    if (!params.pAI->GetAIObject()->IsEnemyInSight())

    {

      // 如果没有敌人,返回成功

      return eAIAR_Success;

    }



    // 否则,继续执行

    return eAIAR_Running;

  }

};



// 定义行为树

class SimpleBehaviorTree : public IAIActionTree

{

public:

  AIACTIONTREE_IMPLEMENT(SimpleBehaviorTree);



  virtual void Initialize() override

  {

    // 初始化行为树

    AddAction("Idle", new IdleAction());

    AddAction("Alert", new AlertAction());



    // 定义行为树结构

    AddSequence("IdleSequence");

    AddActionToSequence("IdleSequence", "Idle");



    AddSelector("AlertSelector");

    AddActionToSelector("AlertSelector", "Alert");



    SetRootAction("AlertSelector");

  }

};



// 注册行为树

CRYREGISTER_AIACTIONTREE(SimpleBehaviorTree, "SimpleBehaviorTree");



// AI对象类

class SimpleAIObject : public CAIObject

{

public:

  SimpleAIObject(const char* name) : CAIObject(name) {}



  bool IsEnemyInSight() const

  {

    // 检查是否有敌人在视野范围内

    return false;

  }

};



// 在游戏中使用AI对象

void CreateAIObject()

{

  SimpleAIObject* aiObject = new SimpleAIObject("SimpleAI");

  gAIObjectUpr->RegisterAIObject(aiObject);



  // 设置行为树

  aiObject->SetActionTree("SimpleBehaviorTree");

}

动画系统与AI控制的结合

动画系统是AI角色控制的重要组成部分,它决定了角色在不同状态下的动作表现。在CryEngine中,动画系统通过动画片段(Animation Clips)和动画图(Animation Graphs)来实现。以下是如何将动画系统与状态机结合的示例。

动画片段

动画片段是角色在特定状态下执行的一系列动画。在CryEngine中,可以通过动画编辑器(Animation Editor)来创建和管理动画片段。

动画图

动画图是一种高级的动画控制方法,通过图状结构来定义动画片段的过渡和混合。以下是一个简单的动画图示例,展示了如何在状态机中使用动画图。

动画图的定义

在CryEngine的动画编辑器中,创建一个名为EnemyAI的动画图,并定义以下状态和过渡:

  • Idle State:角色在闲逛时的动画。

  • Alert State:角色在警戒时的动画。

  • Transition:从Idle状态到Alert状态的过渡动画。

动画图的使用

在状态机中,可以通过设置动画图的状态来控制角色的动画表现。


-- 定义状态机

local StateMachine = {

  states = {},

  currentState = nil,

  aiObject = nil

}



-- 定义Idle状态

local IdleState = {

  name = "Idle",

  update = function(self, deltaTime)

    -- 检查是否有敌人进入视野

    if self:isEnemyInSight() then

      self:changeState(AlertState)

    end



    -- 设置动画图状态

    self.aiObject:PlayAnimation("Idle")

  end,

  isEnemyInSight = function(self)

    -- 检查是否有敌人在视野范围内

    return false

  end,

  changeState = function(self, newState)

    -- 切换到新状态

    self.currentState = newState

    newState:enter()

  end

}



-- 定义Alert状态

local AlertState = {

  name = "Alert",

  enter = function(self)

    -- 进入警戒状态时的初始化操作

    print("进入警戒状态")

  end,

  update = function(self, deltaTime)

    -- 检查是否有敌人离开视野

    if not self:isEnemyInSight() then

      self:changeState(IdleState)

    end



    -- 设置动画图状态

    self.aiObject:PlayAnimation("Alert")

  end,

  isEnemyInSight = function(self)

    -- 检查是否有敌人在视野范围内

    return true

  end,

  changeState = function(self, newState)

    -- 切换到新状态

    self.currentState = newState

    newState:enter()

  end

}



-- 初始化状态机

function StateMachine:init(aiObject)

  self.aiObject = aiObject

  self.states["Idle"] = IdleState

  self.states["Alert"] = AlertState

  self:changeState(IdleState)

end



-- 更新状态机

function StateMachine:update(deltaTime)

  self.currentState:update(deltaTime)

end



-- 切换状态

function StateMachine:changeState(newState)

  self.currentState:changeState(newState)

end



-- 创建并初始化状态机实例

local aiObject = AI.CreateObject("EnemyAI")

local aiStateMachine = StateMachine

aiStateMachine:init(aiObject)



-- 在每一帧更新状态机

function Update(deltaTime)

  aiStateMachine:update(deltaTime)

end

物理系统

物理系统处理角色的物理交互和运动,是AI角色控制的重要组成部分。在CryEngine中,物理系统通过物理引擎(Physics Engine)来实现。以下是一个简单的例子,展示了如何在状态机中使用物理系统。

物理系统的初始化

在创建AI对象时,需要初始化物理系统。


#include "CryEngine/CryEntitySystem/IEntity.h"

#include "CryEngine/CryPhysics/PhysicalEntity.h"



// AI对象类

class SimpleAIObject : public CAIObject

{

public:

  SimpleAIObject(const char* name) : CAIObject(name)

  {

    // 初始化物理系统

    IEntity* entity = gEnv->pEntitySystem->CreateEntity(name, 0);

    entity->LoadFromXML("Objects/EnemyAI/EnemyAI.xml");



    // 获取物理实体

    IPhysicalEntity* physicalEntity = entity->GetPhysics();

    if (physicalEntity)

    {

      // 设置物理参数

      physicalEntity->SetParams(pe_params);

    }

  }



  bool IsEnemyInSight() const

  {

    // 检查是否有敌人在视野范围内

    return false;

  }



  void MoveToPosition(const Vec3& position)

  {

    // 移动到指定位置

    IPhysicalEntity* physicalEntity = GetEntity()->GetPhysics();

    if (physicalEntity)

    {

      physicalEntity->SetPos(position);

    }

  }

};

物理系统的使用

在状态机中,可以通过调用AI对象的方法来控制角色的物理运动。


-- 定义状态机

local StateMachine = {

  states = {},

  currentState = nil,

  aiObject = nil

}



-- 定义Idle状态

local IdleState = {

  name = "Idle",

  update = function(self, deltaTime)

    -- 检查是否有敌人进入视野

    if self:isEnemyInSight() then

      self:changeState(AlertState)

    end



    -- 设置动画图状态

    self.aiObject:PlayAnimation("Idle")

  end,

  isEnemyInSight = function(self)

    -- 检查是否有敌人在视野范围内

    return false

  end,

  changeState = function(self, newState)

    -- 切换到新状态

    self.currentState = newState

    newState:enter()

  end

}



-- 定义Alert状态

local AlertState = {

  name = "Alert",

  enter = function(self)

    -- 进入警戒状态时的初始化操作

    print("进入警戒状态")

  end,

  update = function(self, deltaTime)

    -- 检查是否有敌人离开视野

    if not self:isEnemyInSight() then

      self:changeState(IdleState)

    end



    -- 设置动画图状态

    self.aiObject:PlayAnimation("Alert")



    -- 移动到敌人位置

    local enemyPosition = self:getEnemyPosition()

    if enemyPosition then

      self.aiObject:MoveToPosition(enemyPosition)

    end

  end,

  isEnemyInSight = function(self)

    -- 检查是否有敌人在视野范围内

    return true

  end,

  getEnemyPosition = function(self)

    -- 获取敌人的位置

    return Vec3(100, 100, 0)

  end,

  changeState = function(self, newState)

    -- 切换到新状态

    self.currentState = newState

    newState:enter()

  end

}



-- 初始化状态机

function StateMachine:init(aiObject)

  self.aiObject = aiObject

  self.states["Idle"] = IdleState

  self.states["Alert"] = AlertState

  self:changeState(IdleState)

end



-- 更新状态机

function StateMachine:update(deltaTime)

  self.currentState:update(deltaTime)

end



-- 切换状态

function StateMachine:changeState(newState)

  self.currentState:changeState(newState)

end



-- 创建并初始化状态机实例

local aiObject = CreateAIObject()

local aiStateMachine = StateMachine

aiStateMachine:init(aiObject)



-- 在每一帧更新状态机

function Update(deltaTime)

  aiStateMachine:update(deltaTime)

end

高级AI角色控制

在动作游戏中,AI角色控制不仅仅是简单的状态转换和动画播放,还需要处理更复杂的逻辑,如路径规划、目标选择和任务管理。以下是一些高级AI角色控制的示例。

路径规划

路径规划是AI角色控制中的一项重要任务,用于计算角色从当前位置到目标位置的最佳路径。在CryEngine中,可以通过导航网格(Navigation Mesh)和路径查找算法(Pathfinding Algorithm)来实现路径规划。

导航网格

导航网格是一种用于路径规划的数据结构,它可以表示游戏世界中可行走的区域。在CryEngine中,导航网格可以通过导航编辑器(Navigation Editor)来创建和管理。导航编辑器允许开发者定义可行走区域、障碍物和路径点,从而生成导航网格。

路径查找

路径查找算法用于计算从当前位置到目标位置的路径。在CryEngine中,可以使用A算法来实现路径查找。A算法是一种启发式算法,能够高效地找到从起点到终点的最短路径。


#include "CryEngine/CryAISystem/INavigationSystem.h"

#include "CryEngine/CryAISystem/INavigationMesh.h"

#include "CryEngine/CryAISystem/INavigationQuery.h"



// AI对象类

class SimpleAIObject : public CAIObject

{

public:

  SimpleAIObject(const char* name) : CAIObject(name)

  {

    // 初始化导航系统

    m_navigationSystem = gAIEnv.pNavigationSystem;

  }



  bool IsEnemyInSight() const

  {

    // 检查是否有敌人在视野范围内

    return false;

  }



  void MoveToPosition(const Vec3& position)

  {

    // 计算路径

    INavigationQuery* query = m_navigationSystem->CreateQuery();

    PathFinder::Path path;

    if (query->FindPath(m_position, position, path))

    {

      // 沿路径移动

      for (auto& node : path)

      {

        MoveToNode(node);

      }

    }



    // 释放查询

    m_navigationSystem->ReleaseQuery(query);

  }



  void MoveToNode(const Vec3& node)

  {

    // 移动到指定节点

    IPhysicalEntity* physicalEntity = GetEntity()->GetPhysics();

    if (physicalEntity)

    {

      physicalEntity->SetPos(node);

    }

  }



private:

  INavigationSystem* m_navigationSystem;

  Vec3 m_position;

};

目标选择

目标选择是AI角色控制中的一项重要任务,用于决定角色的目标。在CryEngine中,可以通过目标评价系统(Goal Evaluation System)来实现目标选择。

目标评价系统

目标评价系统通过评估不同的目标,选择最合适的行动目标。在CryEngine中,可以通过编写自定义的评价函数来实现目标选择。评价函数可以根据目标的多种属性(如距离、优先级、威胁程度等)来计算目标的得分,并选择得分最高的目标。


#include "CryEngine/CryAISystem/IAIObject.h"

#include "CryEngine/CryAISystem/IAIActor.h"

#include "CryEngine/CryAISystem/IAIActorProxy.h"

#include "CryEngine/CryAISystem/IAIAction.h"

#include "CryEngine/CryAISystem/IAIActionTree.h"



// 目标评价函数

float EvaluateGoal(const Vec3& goalPosition)

{

  // 计算目标位置的距离

  float distance = (gEnv->pAIObjectUpr->GetAIObject("Player")->GetPosition() - goalPosition).GetLength();



  // 距离越近,评价越高

  return 1.0f / (1.0f + distance);

}



// AI对象类

class SimpleAIObject : public CAIObject

{

public:

  SimpleAIObject(const char* name) : CAIObject(name) {}



  bool IsEnemyInSight() const

  {

    // 检查是否有敌人在视野范围内

    return false;

  }



  void SelectGoal()

  {

    // 获取所有目标

    std::vector<Vec3> goals = GetGoals();



    // 选择评价最高的目标

    Vec3 bestGoal = goals[0];

    float bestScore = EvaluateGoal(goals[0]);

    for (size_t i = 1; i < goals.size(); ++i)

    {

      float score = EvaluateGoal(goals[i]);

      if (score > bestScore)

      {

        bestGoal = goals[i];

        bestScore = score;

      }

    }



    // 移动到最佳目标

    MoveToPosition(bestGoal);

  }



  std::vector<Vec3> GetGoals()

  {

    // 获取所有可能的目标位置

    std::vector<Vec3> goals;

    // 示例中假设目标位置是固定的

    goals.push_back(Vec3(100, 100, 0));

    goals.push_back(Vec3(200, 200, 0));

    return goals;

  }



  void MoveToPosition(const Vec3& position)

  {

    // 计算路径

    INavigationQuery* query = m_navigationSystem->CreateQuery();

    PathFinder::Path path;

    if (query->FindPath(m_position, position, path))

    {

      // 沿路径移动

      for (auto& node : path)

      {

        MoveToNode(node);

      }

    }



    // 释放查询

    m_navigationSystem->ReleaseQuery(query);

  }



  void MoveToNode(const Vec3& node)

  {

    // 移动到指定节点

    IPhysicalEntity* physicalEntity = GetEntity()->GetPhysics();

    if (physicalEntity)

    {

      physicalEntity->SetPos(node);

    }

  }



private:

  INavigationSystem* m_navigationSystem;

  Vec3 m_position;

};

任务管理

任务管理是AI角色控制中的另一项重要任务,用于分配和管理角色的任务。在CryEngine中,可以通过任务调度器(Task Scheduler)和任务队列(Task Queue)来实现任务管理。

任务调度器

任务调度器负责根据当前情况和任务的优先级来分配任务。它可以动态地调整任务的顺序,确保角色始终执行最合适的任务。

任务队列

任务队列用于存储和管理角色的任务列表。每个任务可以包含一系列的动作和条件,角色会依次执行这些任务。


#include "CryEngine/CryAISystem/IAIObject.h"

#include "CryEngine/CryAISystem/IAIActor.h"

#include "CryEngine/CryAISystem/IAIActorProxy.h"

#include "CryEngine/CryAISystem/IAIAction.h"

#include "CryEngine/CryAISystem/IAIActionTree.h"

#include "CryEngine/CrySystem/ITaskScheduler.h"



// 任务类

class Task

{

public:

  Task(const char* name, const Vec3& position) : m_name(name), m_position(position) {}



  const char* GetName() const { return m_name; }

  const Vec3& GetPosition() const { return m_position; }



private:

  const char* m_name;

  Vec3 m_position;

};



// 任务队列类

class TaskQueue

{

public:

  void AddTask(const Task& task)

  {

    m_tasks.push_back(task);

  }



  Task GetNextTask()

  {

    if (!m_tasks.empty())

    {

      Task task = m_tasks.front();

      m_tasks.erase(m_tasks.begin());

      return task;

    }

    return Task("None", Vec3(0, 0, 0));

  }



private:

  std::vector<Task> m_tasks;

};



// AI对象类

class SimpleAIObject : public CAIObject

{

public:

  SimpleAIObject(const char* name) : CAIObject(name), m_taskQueue(new TaskQueue()) {}



  bool IsEnemyInSight() const

  {

    // 检查是否有敌人在视野范围内

    return false;

  }



  void SelectGoal()

  {

    // 获取所有目标

    std::vector<Vec3> goals = GetGoals();



    // 选择评价最高的目标

    Vec3 bestGoal = goals[0];

    float bestScore = EvaluateGoal(goals[0]);

    for (size_t i = 1; i < goals.size(); ++i)

    {

      float score = EvaluateGoal(goals[i]);

      if (score > bestScore)

      {

        bestGoal = goals[i];

        bestScore = score;

      }

    }



    // 添加移动任务

    m_taskQueue->AddTask(Task("MoveToGoal", bestGoal));

  }



  std::vector<Vec3> GetGoals()

  {

    // 获取所有可能的目标位置

    std::vector<Vec3> goals;

    // 示例中假设目标位置是固定的

    goals.push_back(Vec3(100, 100, 0));

    goals.push_back(Vec3(200, 200, 0));

    return goals;

  }



  void MoveToPosition(const Vec3& position)

  {

    // 计算路径

    INavigationQuery* query = m_navigationSystem->CreateQuery();

    PathFinder::Path path;

    if (query->FindPath(m_position, position, path))

    {

      // 沿路径移动

      for (auto& node : path)

      {

        MoveToNode(node);

      }

    }



    // 释放查询

    m_navigationSystem->ReleaseQuery(query);

  }



  void MoveToNode(const Vec3& node)

  {

    // 移动到指定节点

    IPhysicalEntity* physicalEntity = GetEntity()->GetPhysics();

    if (physicalEntity)

    {

      physicalEntity->SetPos(node);

    }

  }



  void Update(float deltaTime)

  {

    // 获取下一个任务

    Task task = m_taskQueue->GetNextTask();

    if (strcmp(task.GetName(), "MoveToGoal") == 0)

    {

      MoveToPosition(task.GetPosition());

    }

  }



private:

  INavigationSystem* m_navigationSystem;

  Vec3 m_position;

  TaskQueue* m_taskQueue;

};

结合状态机、行为树和任务管理

在实际应用中,状态机、行为树和任务管理通常会结合使用,以实现更复杂和灵活的AI控制。以下是一个综合示例,展示了如何将状态机、行为树和任务管理结合在一起。


#include "CryEngine/CryAISystem/IAIObject.h"

#include "CryEngine/CryAISystem/IAIActor.h"

#include "CryEngine/CryAISystem/IAIActorProxy.h"

#include "CryEngine/CryAISystem/IAIAction.h"

#include "CryEngine/CryAISystem/IAIActionTree.h"

#include "CryEngine/CrySystem/ITaskScheduler.h"

#include "CryEngine/CryAISystem/INavigationSystem.h"

#include "CryEngine/CryAISystem/INavigationMesh.h"

#include "CryEngine/CryAISystem/INavigationQuery.h"



// 任务类

class Task

{

public:

  Task(const char* name, const Vec3& position) : m_name(name), m_position(position) {}



  const char* GetName() const { return m_name; }

  const Vec3& GetPosition() const { return m_position; }



private:

  const char* m_name;

  Vec3 m_position;

};



// 任务队列类

class TaskQueue

{

public:

  void AddTask(const Task& task)

  {

    m_tasks.push_back(task);

  }



  Task GetNextTask()

  {

    if (!m_tasks.empty())

    {

      Task task = m_tasks.front();

      m_tasks.erase(m_tasks.begin());

      return task;

    }

    return Task("None", Vec3(0, 0, 0));

  }



private:

  std::vector<Task> m_tasks;

};



// 定义行为树节点

class IdleAction : public IAIAction

{

public:

  AIACTION_IMPLEMENT(IdleAction);



  virtual EAIActionResult Execute(const SAIActionParams& params) override

  {

    // 检查是否有敌人进入视野

    if (params.pAI->GetAIObject()->IsEnemyInSight())

    {

      // 如果有敌人,返回失败

      return eAIAR_Failure;

    }



    // 否则,继续执行

    return eAIAR_Running;

  }

};



class AlertAction : public IAIAction

{

public:

  AIACTION_IMPLEMENT(AlertAction);



  virtual EAIActionResult Execute(const SAIActionParams& params) override

  {

    // 检查是否有敌人离开视野

    if (!params.pAI->GetAIObject()->IsEnemyInSight())

    {

      // 如果没有敌人,返回成功

      return eAIAR_Success;

    }



    // 选择目标

    params.pAI->GetAIObject()->SelectGoal();



    // 继续执行

    return eAIAR_Running;

  }

};



// 定义行为树

class SimpleBehaviorTree : public IAIActionTree

{

public:

  AIACTIONTREE_IMPLEMENT(SimpleBehaviorTree);



  virtual void Initialize() override

  {

    // 初始化行为树

    AddAction("Idle", new IdleAction());

    AddAction("Alert", new AlertAction());



    // 定义行为树结构

    AddSequence("IdleSequence");

    AddActionToSequence("IdleSequence", "Idle");



    AddSelector("AlertSelector");

    AddActionToSelector("AlertSelector", "Alert");



    SetRootAction("AlertSelector");

  }

};



// 注册行为树

CRYREGISTER_AIACTIONTREE(SimpleBehaviorTree, "SimpleBehaviorTree");



// AI对象类

class SimpleAIObject : public CAIObject

{

public:

  SimpleAIObject(const char* name) : CAIObject(name), m_taskQueue(new TaskQueue())

  {

    // 初始化导航系统

    m_navigationSystem = gAIEnv.pNavigationSystem;

  }



  bool IsEnemyInSight() const

  {

    // 检查是否有敌人在视野范围内

    return false;

  }



  void SelectGoal()

  {

    // 获取所有目标

    std::vector<Vec3> goals = GetGoals();



    // 选择评价最高的目标

    Vec3 bestGoal = goals[0];

    float bestScore = EvaluateGoal(goals[0]);

    for (size_t i = 1; i < goals.size(); ++i)

    {

      float score = EvaluateGoal(goals[i]);

      if (score > bestScore)

      {

        bestGoal = goals[i];

        bestScore = score;

      }

    }



    // 添加移动任务

    m_taskQueue->AddTask(Task("MoveToGoal", bestGoal));

  }



  std::vector<Vec3> GetGoals()

  {

    // 获取所有可能的目标位置

    std::vector<Vec3> goals;

    // 示例中假设目标位置是固定的

    goals.push_back(Vec3(100, 100, 0));

    goals.push_back(Vec3(200, 200, 0));

    return goals;

  }



  void MoveToPosition(const Vec3& position)

  {

    // 计算路径

    INavigationQuery* query = m_navigationSystem->CreateQuery();

    PathFinder::Path path;

    if (query->FindPath(m_position, position, path))

    {

      // 沿路径移动

      for (auto& node : path)

      {

        MoveToNode(node);

      }

    }



    // 释放查询

    m_navigationSystem->ReleaseQuery(query);

  }



  void MoveToNode(const Vec3& node)

  {

    // 移动到指定节点

    IPhysicalEntity* physicalEntity = GetEntity()->GetPhysics();

    if (physicalEntity)

    {

      physicalEntity->SetPos(node);

    }

  }



  void Update(float deltaTime)

  {

    // 获取下一个任务

    Task task = m_taskQueue->GetNextTask();

    if (strcmp(task.GetName(), "MoveToGoal") == 0)

    {

      MoveToPosition(task.GetPosition());

    }

  }



private:

  INavigationSystem* m_navigationSystem;

  Vec3 m_position;

  TaskQueue* m_taskQueue;

};



// 在游戏中使用AI对象

void CreateAIObject()

{

  SimpleAIObject* aiObject = new SimpleAIObject("SimpleAI");

  gAIObjectUpr->RegisterAIObject(aiObject);



  // 设置行为树

  aiObject->SetActionTree("SimpleBehaviorTree");

}

总结

在CryEngine中,AI角色控制是一个多方面的任务,涉及到状态机、行为树、动画系统和物理系统的协同工作。通过这些子系统的结合,可以实现复杂且灵活的AI逻辑,从而提升游戏的沉浸感和玩家的体验。状态机用于管理角色的不同状态及其转换,行为树用于定义角色的行为逻辑,动画系统用于实现角色的动作表现,物理系统用于处理角色的物理交互和运动。此外,路径规划和目标选择也是实现高级AI控制的关键技术。

通过上述示例,我们可以看到如何在CryEngine中实现这些功能,并将它们结合在一起,以创建更加智能和动态的NPC。希望这些内容能够帮助你更好地理解和应用CryEngine中的AI角色控制机制。
在这里插入图片描述

标签:const,角色,--,self,状态机,CryEngine,end
From: https://blog.csdn.net/chenlz2007/article/details/144119223

相关文章

  • CryEngine引擎开发:角色控制与状态机_高级角色控制技术
    高级角色控制技术在上一节中,我们介绍了角色控制的基本原理和实现方法,包括输入处理、物理模拟和动画融合。在这一节中,我们将深入探讨高级角色控制技术,这些技术将帮助您创建更加复杂和逼真的人物角色。我们将重点讨论以下几个方面:角色状态机设计角色动作平滑过渡环境交......
  • 【Unity 插件】Visual State Machine 通过图形化的界面帮助开发者设计和管理复杂的状
    VisualStateMachine是一款用于Unity编辑器中的插件,旨在通过图形化的界面帮助开发者设计和管理复杂的状态机逻辑。它为Unity提供了一个直观的拖拽式状态机系统,可以用来控制角色行为、AI、动画、UI交互等各种状态转换。主要特点:图形化界面:使用拖拽式界面来创建和管理......
  • 人工智能:在传统行业中的挑战、机遇与数据科学家角色的演变
    生成式人工智能(GenAI)为我们开启了更快的开发周期、更少的技术和维护工作,以及之前看起来无法实现的创新应用场景的大门。但与此同时,它也带来了新的风险——比如幻觉问题,以及对第三方API的依赖。对于数据科学家和机器学习团队来说,这一变革直接影响了他们的工作方式。一种新的AI项......
  • 基于SSM + Vue的架的校园外卖管理系统(角色:用户、商家、管理员)
    文章目录前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论五、项目代码参考六、数据库代码参考七、项目论文示例结语前言......
  • 基于SSM + Vue的酒店管理系统(角色:用户、员工、管理员)
    文章目录前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论五、项目代码参考六、数据库代码参考七、项目论文示例结语前言......
  • 从“整理”到“思考”:文档管理工具的新角色
    在信息爆炸的时代,文档管理的核心挑战已不再是存储,而是高效组织和提取知识。传统文档管理工具通常以文件夹和标签为基础,这种层级化结构容易造成知识孤岛。然而,语义网络的引入为知识管理开辟了新的路径:它不再以孤立的文档为单元,而是基于内容、上下文和关联性建立知识图谱,使信息真正......
  • Unity中的数学应用 之 插值函数处理角色朝向 (初中难度 +Matlab)
            CodeMonkey教程:https://www.youtube.com/watch?v=QDWlGOocKm8    Siki学院汉化教程:如何使用Unity开发分手厨房(胡闹厨房)-Unity2023-SiKi学院|SiKi学堂-unity|u3d|虚幻|ue4/5|java|python|人工智能|视频教程|在线课程版本:Unity6模板:3D核心(渲......
  • python+Django+MySQL+echarts+bootstrap制作的教学质量评价系统,包括学生、老师、管理
    项目介绍该教学质量评价系统基于Python、Django、MySQL、ECharts和Bootstrap技术,旨在为学校或教育机构提供一个全面的教学质量评估平台。系统主要包括三种角色:学生、老师和管理员,每个角色有不同的功能权限。学生角色:学生可以通过该平台对所选课程进行评价,评价内容包括老师的......
  • 8 位 RISC 模型机 状态机控制 ALU双端口
    8位RISC模型机状态机控制双端口项目地址:8位RISC模型机状态机控制双端口从8位寄存器(D触发器)开始DDD:8位输入......
  • 【状态机DP】力扣309. 买卖股票的最佳时机含冷冻期
    给定一个整数数组prices,其中第prices[i]表示第i天的股票价格。​设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):卖出股票后,你无法在第二天买入股票(即冷冻期为1天)。注意:你不能同时参与多笔交易(你必须在再次购......