ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从0到1开发goa/goap自定义Action:以ChopTreeAction为例的完整教程

从0到1开发goa/goap自定义Action:以ChopTreeAction为例的完整教程

从0到1开发goa/goap自定义Action:以ChopTreeAction为例的完整教程

【免费下载链接】goapGoal Oriented Action Planning AI in Unity项目地址: https://gitcode.com/gh_mirrors/goa/goap

goa/goap是一个基于Unity的Goal Oriented Action Planning(GOAP)AI系统,它允许开发者为游戏角色创建智能决策逻辑。本文将以ChopTreeAction为例,详细介绍如何从零开始开发自定义Action,帮助新手快速掌握GOAP系统的核心开发技能。

什么是GOAP Action?

GOAP Action是GOAP系统的核心组成部分,它定义了智能体可以执行的具体行为。每个Action包含前置条件、执行效果、目标对象和执行逻辑等关键要素。在goa/goap项目中,所有Action都继承自抽象基类GoapAction,该类位于Assets/Standard Assets/Scripts/AI/GOAP/GoapAction.cs。

GoapAction基类定义了以下必须实现的抽象方法:

  • reset():重置Action状态
  • isDone():检查Action是否完成
  • checkProceduralPrecondition():检查过程性前置条件
  • perform():执行Action逻辑
  • requiresInRange():是否需要靠近目标对象

开发ChopTreeAction的完整步骤

1. 创建Action类并继承GoapAction

首先,创建一个名为ChopTreeAction的类,并继承GoapAction。在goa/goap项目中,所有自定义Action都存放在Assets/Standard Assets/Scripts/GameData/Actions/目录下。

public class ChopTreeAction : GoapAction { // 实现抽象方法和自定义逻辑 }

2. 定义Action的状态变量

ChopTreeAction中,我们需要定义一些状态变量来跟踪砍树过程:

private bool chopped = false; private TreeComponent targetTree; // 目标树组件 private float startTime = 0; public float workDuration = 2; // 砍树所需时间(秒)

3. 实现构造函数和前置条件/效果

在构造函数中,我们需要设置Action的前置条件和执行效果。对于砍树动作,前置条件是"拥有工具"且"没有木材",执行效果是"获得木材":

public ChopTreeAction() { addPrecondition("hasTool", true); // 需要工具 addPrecondition("hasLogs", false); // 没有木材 addEffect("hasLogs", true); // 获得木材 }

4. 实现reset()方法

reset()方法用于重置Action的状态,在每次Action被规划时都会调用:

public override void reset() { chopped = false; targetTree = null; startTime = 0; }

5. 实现isDone()方法

isDone()方法检查Action是否完成,这里我们通过chopped变量来判断:

public override bool isDone() { return chopped; }

6. 实现requiresInRange()方法

砍树动作需要靠近树木,因此requiresInRange()应返回true:

public override bool requiresInRange() { return true; // 需要靠近树木 }

7. 实现checkProceduralPrecondition()方法

该方法用于查找合适的目标对象(这里是树木)。我们需要找到距离智能体最近的树木:

public override bool checkProceduralPrecondition(GameObject agent) { // 查找所有树木组件 TreeComponent[] trees = (TreeComponent[])UnityEngine.GameObject.FindObjectsOfType(typeof(TreeComponent)); TreeComponent closest = null; float closestDist = 0; foreach (TreeComponent tree in trees) { if (closest == null) { closest = tree; closestDist = (tree.gameObject.transform.position - agent.transform.position).magnitude; } else { float dist = (tree.gameObject.transform.position - agent.transform.position).magnitude; if (dist < closestDist) { closest = tree; closestDist = dist; } } } if (closest == null) return false; targetTree = closest; target = targetTree.gameObject; return closest != null; }

8. 实现perform()方法

perform()方法包含Action的核心执行逻辑。在这里,我们处理砍树过程、获取木材以及工具损耗:

public override bool perform(GameObject agent) { if (startTime == 0) startTime = Time.time; if (Time.time - startTime > workDuration) { // 完成砍树,获取木材 BackpackComponent backpack = (BackpackComponent)agent.GetComponent(typeof(BackpackComponent)); backpack.numLogs += 1; chopped = true; // 使用工具并检查工具是否损坏 ToolComponent tool = backpack.tool.GetComponent(typeof(ToolComponent)) as ToolComponent; tool.use(0.34f); if (tool.destroyed()) { Destroy(backpack.tool); backpack.tool = null; } } return true; }

将自定义Action添加到智能体

要让智能体能够使用新创建的ChopTreeAction,需要将其添加到相应的智能体组件中。以Logger(伐木工人)为例,在Assets/Standard Assets/Scripts/GameData/Labourers/Logger.cs中,ChopTreeAction被用于实现伐木目标。

自定义Action开发最佳实践

  1. 保持单一职责:每个Action应只完成一个具体任务,如砍树、采矿、锻造等
  2. 合理设置前置条件和效果:确保条件和效果的逻辑一致性,这直接影响GOAP规划器的决策
  3. 优化目标选择:在checkProceduralPrecondition()中高效查找目标,避免性能问题
  4. 处理资源消耗:如工具损耗、时间成本等,使AI行为更真实
  5. 状态重置:在reset()方法中确保所有状态变量都被正确重置

总结

通过本文的教程,你已经了解了如何基于goa/goap项目开发自定义Action。从继承GoapAction基类,到实现各种抽象方法,再到定义具体的执行逻辑,每个步骤都至关重要。掌握Action开发是构建复杂GOAP AI系统的基础,希望这个以ChopTreeAction为例的教程能帮助你快速上手goa/goap的开发。

现在,你可以尝试开发其他类型的Action,如采矿(MineOreAction)、锻造工具(ForgeToolAction)等,这些Action都可以在Assets/Standard Assets/Scripts/GameData/Actions/目录下找到参考实现。

【免费下载链接】goapGoal Oriented Action Planning AI in Unity项目地址: https://gitcode.com/gh_mirrors/goa/goap

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表