`
cqphper
  • 浏览: 23715 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
最近访客 更多访客>>
社区版块
存档分类
最新评论

(转)LUA脚本实现角色AI的新方法(一、二)

    博客分类:
  • Lua
阅读更多
在用Lua写AI脚本这一块,这是我从网上找到的唯一一篇文章,而且写的非常好,读后受宜菲浅!让我少走很多弯路。但文章源出处找不到了,在这里对这篇文章的作者表示非常的感谢!

LUA实现角色AI的新方法


怪物AI只需要提供3种条件集:

1. 无目标的条件集

2. 有目标的条件集

3. 无论是有目标还是无目标, 都必须检测的条件集. 或者叫做定时器条件集.


假设目前我们为游戏提供如下类型的怪物表现: [来自ai_define.lua]

--ai类型 : 废材型 表现为被打也不还手, 继续随机走动

ai_useless = { no_target = as_idle,    has_target = as_forget, tick = as_tick}


--ai类型 : 标准型 表现为被打了就还手并追击, 自己不会主动搜敌

ai_standard = { no_target = as_idle, has_target = as_chase , tick = as_tick}


--ai类型 : 进攻型 表现为保持警戒搜敌,有目标就追击

ai_attacker = { no_target = as_guard, has_target = as_chase , tick = as_tick}


--ai类型 : 胆小型 表现为被打了就反方向逃跑了

ai_flee   = { no_target = as_idle, has_target = as_flee , tick = as_tick}


--ai类型 : 机智型 表现为保持警戒搜敌, 如果目标靠近, 就躲远点继续攻击,

用于高级远程攻击怪

ai_smart = { no_target = as_guard,has_target = as_around, tick = as_tick}


--ai类型 : 巡逻型 表现为两点间巡逻, 并保持警戒搜敌, 有目标就追击

ai_patrol   = { no_target = as_patrol, has_target = as_chase, tick = as_tick}


然后写出如下两个AI运行的核心函数

function handle_state(c, state) --处理条件集(state), 参数c表示角色对象

      if state==nil then return end

      for con, event in state do    --遍历条件集中的所有条件

           if con==1 then           

                 event(c)               --永为真的条件, 必然执行事件

else

                 local r = con(c)

                 if r~=0 then event(c, r) end –条件满足, 执行事件

           end    

      end

end

function ai_loop(c) --每个角色都会循环执行的ai函数

   local ai_t = GetAIType(c)    --取出角色的ai类型定义, 例如废材,标准

    local t    = GetChaTarget(c) --取出当前角色的目标

      if t~=nil then

        handle_state(c, ai_t.has_target) --有目标的处理

    else

          handle_state(c, ai_t.no_target) --无目标的处理

    end

   handle_state(c, ai_t.tick) –无论有目标还是无目标, 都要进行的处理

end


打完收功, AI就实现完毕了. 除了这两个总计21行的lua函数, 剩下的事情应该交给脚本策划了……虽然很残忍, 但是很清晰, 下面我们来看看脚本策划应该实现的部分:
1. 组合条件集
2. 编写具体的条件以及条件产生的事件


下面我们来看看脚本策划应该实现的部分:
1. 组合条件集
2. 编写具体的条件以及条件产生的事件

第一步 : 组合条件集

--AI状态条件集 : 各种AI通用的tick

--无论有无目标, 角色都会进入这些条件检查

--只要角色回到了出生点附近, 则清除'回家'的标志, 当角色被置上此标志时, 是不搜敌的

as_tick = {}

as_tick[aic_near_spawnpos] = ai_event_clear_gohome


--AI状态条件集 : 忘记目标

as_forget = {}

as_forget[1] = ai_event_clear_target  --( 条件为1表示必然执行 )


--AI状态条件集 : 警戒

as_guard = {}

as_guard[aic_seek_target] = ai_event_find_target


--AI状态条件集 : 休息(随机移动)

as_idle = {}

as_idle[aic_rand_8_1] = ai_event_rand_move


--AI状态条件集 : 巡逻

--如果回到巡逻起点, 则开始在起点休息

--如果休息结束, 应该开始巡逻了, 则开始巡逻

--如果抵达巡逻目标点, 则在目标点开始休息

--巡逻的同时, 保持警戒

--巡逻内部子状态的说明:

--patrol_state = 0 表示可以开始前往巡逻目标点

--patrol_state = 1 正在前往目标点的路上

--patrol_state = 2 表示可以回到起始点

--patrol_state = 3 表示正在从回到起始点的路上


as_patrol = {}

as_patrol[aic_patrol_begin]   = ai_event_patrol_begin

as_patrol[aic_patrol_arrive]  = ai_event_patrol_end_idle

as_patrol[aic_patrol_return]  = ai_event_patrol_return

as_patrol[aic_patrol_back_ok] = ai_event_patrol_start_idle

as_patrol[aic_seek_target]    = ai_event_find_target


--AI状态条件集 : 追击

--如果距离出生点太远, 则往回走

--如果目标已经超出视野, 则清除目标

as_chase = {}

as_chase[aic_at_spawn_toofar]= ai_event_go_home

as_chase[aic_target_outofsight] = ai_event_clear_target

as_chase[aic_update_target]   = ai_event_update_target

as_chase[1]                    = ai_event_use_skill


第二步. 编写具体的条件以及条件满足后产生的事件
这里的代码较多, 列举几个例子说明问题就好了, 总的原则是来自c/c++的接口函数我们称之为sdk, 脚本策划自己实现的函数我们称之为2次封装, 这些条件函数有的是各种AI都可以使用的, 有的是某种AI专用的. 来自[ai_condition.lua]
-------------------------------------通用条件列表-----------------------------------

--条件 : 角色位于出生点

function aic_at_spawnpos(c)

      local x, y = GetChaSpawnPos(c)

if is_near_pos(c, x, y, 100)==1 then

          return 1

    end

    return 0

end


--条件 : 距离出生点太远

function aic_at_spawn_toofar(c)

      local chase_r = GetChaChaseRange(c)

      local x, y = GetChaSpawnPos(c)

      local now_x, now_y = GetChaPos(c)

   local dis = (now_x - x) * (now_x - x) + (now_y - y) * (now_y - y)

   if dis > chase_r * chase_r then

          return 1

   end

   return 0

end


--条件 : 目标超出视野

function aic_target_outofsight(c)

      local t = GetChaTarget(c)               --取出当前角色的目标

      local vision = GetChaVision(c)         --取出角色的视野

      if is_near(c, t, vision)==0 then       --目标距离已经太远

        return 1

    end

    return 0

end


--条件 : 发现目标

function aic_seek_target(c)

      if is_moving_back(c)==1 then return 0 end

      local t = find_target(c, 0) --没有目标, 则寻找一个, 没有找到则t为空

    if t~=nil then

          return t

    end

    return 0

end

……



下面代码来自[ai_event.lua]
--事件 : 发现目标

function ai_event_find_target(c, t)

      SetChaTarget(c, t)

     ai_event_use_skill(c)

end

--事件 : 随机移动

function ai_event_rand_move(c)

      birth_rand_move(c, 600) –在周围6米的范围内随机移动

end

--事件 : 开始新一轮的巡逻

function ai_event_patrol_begin(c)

local px, py = GetChaPatrolPos(c) --取出巡逻点

    ChaMove(c, px, py)

    SetChaPatrolState(c, 1) --修改巡逻标记, 设置为移动中

end

--事件 : 回出生点

function ai_event_go_home(c)

      clear_target(c)      --清除目标

    local x, y = GetChaSpawnPos(c)

    ChaMoveToSleep(c, x, y)

    set_moving_back(c, 1)

      LG("ai_debug", "event go home", GetChaPatrolState(c))

end

--事件 : 清除目标

function ai_event_clear_target(c)

      clear_target(c)  --清除目标

end

--事件 : 目标更新(仇恨度相关检查)

function ai_event_update_target(c)

      local t = GetChaTarget(c) --取出当前角色的目标

      local tNew = GetChaFirstTarget(c) --通过伤害判断取得优先目标

   if tNew~=nil and tNew~=t then

       clear_target(c)         --清除原目标

       SetChaTarget(c, tNew)   --设置新目标

        return 1

   end

   return 0


end


--事件 : 对目标使用技能

function ai_event_use_skill(c)

      local t = GetChaTarget(c)     --取出当前角色的目标

      local skill_id = select_skill(c) --怪物按照比率选择自己的技能

     ChaUseSkill(c, t, skill_id)     --向目标移动并使用技能

end


--事件 : 清除回家的状态

function ai_event_clear_gohome(c)

      set_moving_back(c, 0)

      if GetChaTypeID(c)==41 then

           LG("ai_debug", "event clear gohome", GetChaPatrolState(c))

      end

end
……

当需要扩充新的ai类型, 就重复以上的步骤:
1. 组合条件集
2. 编写具体的条件以及条件产生的事件

结束!


对于游戏中怪物的运行逻辑而言, 主要是检测出怪物此时的状态, 然后确定该状态下需要检测哪些行为条件, 每当符合一个行为条件, 就执行一个事件, 所以在实现AI的时候, 可以认为 状态 = 条件集合. 按照这种思路, 结合LUA独特的语法特点, 就可以把AI实现为如下的形式.
分享到:
评论

相关推荐

    Lua脚本在游戏引擎中的应用

    通过堆栈来实现引擎与Lua脚本之间的信息传递,这一中间层的设计允许引擎调用Lua脚本中定义的函数,同时也允许Lua脚本调用引擎中定义的功能函数。这种机制的一个显著优势是,可以在不改变引擎核心代码的前提下,增加...

    Jill——Java编写的Lua脚本引擎

    Jill是一个用Java语言实现的Lua脚本引擎,它为Java应用程序提供了一种高效且灵活的方式来运行Lua代码。Lua是一种轻量级的、解释型的脚本语言,因其简洁的语法和强大的功能在游戏开发、配置管理、系统脚本等领域广泛...

    Lua程序设计第二版最新

    《Lua程序设计第二版》是一本深入探讨Lua编程语言的权威指南,对于想要在游戏开发领域,特别是使用Unity引擎的开发者来说,这本书是极其宝贵的资源。Lua因其轻量级、高效且易于嵌入的特点,被广泛应用于游戏脚本编写...

    unity xlua lua5.4.4最新版lua库文件

    XLua是一个高效、强大的Lua脚本绑定工具,它使得开发者可以在Unity项目中利用Lua语言的强大功能,同时保持与C#代码的无缝集成。在本案例中,我们讨论的是"unity xlua lua5.4.4最新版lua库文件",这意味着你已经获取...

    象棋桥的脚本

    用户可以自定义这些选项,增加新的功能,比如快速还原到某个历史状态、保存当前棋局、开启AI分析等。 5. **SetBoard.cbs**:这个脚本可能涉及"棋盘设置",用于设定棋盘的外观、大小、颜色等视觉元素,也可能包含...

    Lua 脚本语言

    Lua是一种轻量级的、高效的、可扩展的脚本语言,尤其在游戏开发领域中广泛应用。它的设计目标是提供简洁的语法,易于学习和使用,同时也具有强大的功能,能够嵌入到其他应用程序中作为配置语言或者扩展语言。下面将...

    unity-lua 2.0

    在游戏发布后,如果发现某些Lua脚本有错误或者需要更新,无需重新发布整个游戏,只需推送新的Lua脚本,即可实现对游戏逻辑的动态更新。这对于iOS等封闭环境,无法做到热更新的平台来说,具有极大的价值。 3. 性能...

    使用Lua控制应用程序

    - **实现控制逻辑**:尝试编写一个控制应用程序行为的Lua脚本,如打开/关闭特定功能。 - **与C/C++交互**:编译一个C/C++程序,实现加载和执行Lua脚本的功能。 6. **资源推荐** - **官方文档**:Lua官方文档是...

    lua 学习 源代码 加demo 封装

    - **热更新**:在Webgame场景下,使用Lua可以实现热更新,游戏逻辑的修改无需重新编译和发布客户端,只需更新Lua脚本即可。 4. **最佳实践** - **分离接口与实现**:保持C++接口简洁,避免过多的逻辑混杂,以提高...

    Lua5.1.5-lib库

    之后,可以使用`luaL_loadbuffer`或`luaL_dofile`加载和运行Lua脚本。通过`lua_pcall`执行函数,`lua_gettop`、`lua_settop`等函数来管理堆栈,以及`lua_toxxx`和`lua_pushxxx`系列函数来转换和操作数据。 在游戏...

    unity lua例子

    6. **错误处理和调试**:由于Lua和Unity是独立的环境,调试Lua脚本可能需要特定的工具或方法。Unity可能需要打印日志或使用特定的调试器来追踪Lua代码的运行。 7. **性能优化**:虽然Lua执行速度快,但在Unity中...

    Tyr:《暗黑破坏神II》但带有Lua脚本

    而“Tyr”是一个基于《暗黑破坏神II》的项目,它引入了Lua脚本语言,使得游戏的自定义性和扩展性大大增强。Lua是一种轻量级的、动态类型的脚本语言,常用于游戏开发中的逻辑控制和内容扩展。 在这个项目中,Tyr通过...

    hgelua脚本引擎

    通过阅读和分析这些代码,开发者可以了解到如何在Lua脚本中调用HGE的API,如何处理游戏对象,以及如何实现复杂的逻辑流程。这对于初学者来说是极好的入门教材,对于经验丰富的开发者则提供了参考和灵感。 文档资料...

    Lua游戏开发实践指南

    你还将了解到如何调试Lua脚本,以及优化脚本性能的技巧。 此外,书中的实践部分会介绍一些典型的游戏开发场景,比如碰撞检测、物理模拟、AI行为树等,这些都是游戏开发中的常见问题,通过Lua来解决这些问题,可以...

    Detours与Lua5.2库 与头文件

    通过Detours,你可以拦截游戏引擎的相应函数,然后调用Lua脚本来执行自定义逻辑。 在提供的压缩包中,"配置方法.txt"文件应该包含了详细的安装和使用指导,帮助用户快速上手这两个库。"lua"目录很可能包含了Lua5.2...

    Lua程序开发

    - **配置文件**:通过Lua脚本管理游戏的配置数据,方便修改和调试。 - **热更新**:利用Lua的动态性,可以实现在不重新发布客户端的情况下更新部分游戏逻辑。 5. **学习资源** - `Lua程序设计.chm`:这是一个...

    游戏开发-lua-linux源码安装包

    - 脚本配置:通过Lua脚本,开发者可以快速调整游戏参数,实现动态配置。 - 用户界面:Lua也可用于创建和控制游戏的用户界面,提供更灵活的交互设计。 3. **在Linux下源码安装Lua**: - 首先,你需要下载lua-...

    CryEngine3脚本手册

    - **1.10.1 AI Wander Behavior**: 深入介绍如何实现人工智能角色的漫游行为。漫游是游戏中常见的一种行为模式,可以让NPC看起来更自然。 - **1.10.2 Behavior Scripts**: 行为脚本是控制NPC行为的核心组成部分。这...

    LUA5.33支持库1.2版(Lua.fne)-易语言

    通过阅读和运行这些示例,开发者可以快速掌握如何将LUA脚本嵌入到易语言程序中,实现特定功能,例如数据处理、逻辑控制或者界面交互。 2. **帖子说明.txt**:这通常包含了对支持库的详细说明,包括安装步骤、使用...

Global site tag (gtag.js) - Google Analytics