← 返回 Skills 市场
944
总下载
3
收藏
11
当前安装
1
版本数
在 OpenClaw 中安装
/install game-ai
功能描述
Game AI development guide covering behavior trees, state machines, pathfinding, and decision-making systems. Use when implementing enemy AI, NPC behaviors, f...
使用说明 (SKILL.md)
游戏 AI 开发指南
AI 架构选择
架构对比
有限状态机 (FSM):
优点: 简单、直观、易于调试
缺点: 状态多时难以维护
适用: 简单敌人、Boss 阶段
行为树 (BT):
优点: 模块化、可复用、易扩展
缺点: 需要框架支持
适用: 复杂 NPC、战术 AI
效用系统 (Utility AI):
优点: 灵活、智能决策
缺点: 参数调节困难
适用: 模拟人生类、策略游戏
GOAP:
优点: 目标导向、动态规划
缺点: 计算成本高
适用: 智能敌人、复杂行为
有限状态机 (FSM)
基础实现
public enum EnemyState
{
Idle,
Patrol,
Chase,
Attack,
Flee
}
public class EnemyFSM : Node
{
private EnemyState _currentState;
private Dictionary\x3CEnemyState, IState> _states;
public override void _Ready()
{
_states = new Dictionary\x3CEnemyState, IState>
{
[EnemyState.Idle] = new IdleState(this),
[EnemyState.Patrol] = new PatrolState(this),
[EnemyState.Chase] = new ChaseState(this),
[EnemyState.Attack] = new AttackState(this),
[EnemyState.Flee] = new FleeState(this)
};
ChangeState(EnemyState.Idle);
}
public void ChangeState(EnemyState newState)
{
_states[_currentState]?.Exit();
_currentState = newState;
_states[_currentState]?.Enter();
}
public override void _Process(double delta)
{
_states[_currentState]?.Update(delta);
}
}
public interface IState
{
void Enter();
void Update(double delta);
void Exit();
}
public class ChaseState : IState
{
private readonly EnemyFSM _fsm;
private readonly CharacterBody2D _owner;
private NavigationAgent2D _navAgent;
public ChaseState(EnemyFSM fsm)
{
_fsm = fsm;
_owner = fsm.GetParent\x3CCharacterBody2D>();
_navAgent = _owner.GetNode\x3CNavigationAgent2D>("NavigationAgent2D");
}
public void Enter()
{
// 开始追逐动画
_owner.GetNode\x3CAnimationPlayer>("AnimationPlayer").Play("run");
}
public void Update(double delta)
{
var player = GetTree().GetFirstNodeInGroup("player") as Node2D;
if (player == null) return;
// 更新目标位置
_navAgent.TargetPosition = player.GlobalPosition;
// 移动向玩家
var direction = _owner.ToLocal(_navAgent.GetNextPathPosition()).Normalized();
_owner.Velocity = direction * _owner.Speed;
_owner.MoveAndSlide();
// 检查距离
float distance = _owner.GlobalPosition.DistanceTo(player.GlobalPosition);
if (distance \x3C 50)
{
_fsm.ChangeState(EnemyState.Attack);
}
else if (distance > 500)
{
_fsm.ChangeState(EnemyState.Patrol);
}
}
public void Exit()
{
_owner.Velocity = Vector2.Zero;
}
}
行为树 (Behavior Tree)
节点类型
复合节点:
Sequence: 顺序执行(一个失败则失败)
Selector: 选择执行(一个成功则成功)
Parallel: 并行执行
装饰节点:
Inverter: 反转结果
Repeater: 重复执行
UntilFail: 直到失败
叶子节点:
Condition: 条件检查
Action: 执行动作
行为树实现
public enum NodeStatus
{
Running,
Success,
Failure
}
public abstract class BTNode
{
public abstract NodeStatus Execute();
}
public class Sequence : BTNode
{
private readonly List\x3CBTNode> _children = new();
private int _currentChild = 0;
public Sequence(params BTNode[] children)
{
_children.AddRange(children);
}
public override NodeStatus Execute()
{
while (_currentChild \x3C _children.Count)
{
var status = _children[_currentChild].Execute();
if (status == NodeStatus.Running)
return NodeStatus.Running;
if (status == NodeStatus.Failure)
{
_currentChild = 0;
return NodeStatus.Failure;
}
_currentChild++;
}
_currentChild = 0;
return NodeStatus.Success;
}
}
public class Selector : BTNode
{
private readonly List\x3CBTNode> _children = new();
private int _currentChild = 0;
public Selector(params BTNode[] children)
{
_children.AddRange(children);
}
public override NodeStatus Execute()
{
while (_currentChild \x3C _children.Count)
{
var status = _children[_currentChild].Execute();
if (status == NodeStatus.Running)
return NodeStatus.Running;
if (status == NodeStatus.Success)
{
_currentChild = 0;
return NodeStatus.Success;
}
_currentChild++;
}
_currentChild = 0;
return NodeStatus.Failure;
}
}
// 使用示例
public class EnemyAI : Node
{
private BTNode _behaviorTree;
public override void _Ready()
{
_behaviorTree = new Selector(
// 优先攻击
new Sequence(
new Condition(IsPlayerInRange),
new Condition(HasAmmo),
new Action(Attack)
),
// 追逐玩家
new Sequence(
new Condition(CanSeePlayer),
new Action(ChasePlayer)
),
// 巡逻
new Action(Patrol)
);
}
public override void _Process(double delta)
{
_behaviorTree.Execute();
}
}
寻路算法
A* 算法
public class AStar
{
private readonly Grid _grid;
public List\x3CPoint> FindPath(Point start, Point end)
{
var openSet = new PriorityQueue\x3CPoint>();
var cameFrom = new Dictionary\x3CPoint, Point>();
var gScore = new Dictionary\x3CPoint, float>();
var fScore = new Dictionary\x3CPoint, float>();
openSet.Enqueue(start, 0);
gScore[start] = 0;
fScore[start] = Heuristic(start, end);
while (openSet.Count > 0)
{
var current = openSet.Dequeue();
if (current == end)
return ReconstructPath(cameFrom, current);
foreach (var neighbor in _grid.GetNeighbors(current))
{
float tentativeGScore = gScore[current] + _grid.GetCost(current, neighbor);
if (!gScore.ContainsKey(neighbor) || tentativeGScore \x3C gScore[neighbor])
{
cameFrom[neighbor] = current;
gScore[neighbor] = tentativeGScore;
fScore[neighbor] = gScore[neighbor] + Heuristic(neighbor, end);
if (!openSet.Contains(neighbor))
openSet.Enqueue(neighbor, fScore[neighbor]);
}
}
}
return null; // 无路径
}
private float Heuristic(Point a, Point b)
{
// 曼哈顿距离
return Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y);
}
private List\x3CPoint> ReconstructPath(Dictionary\x3CPoint, Point> cameFrom, Point current)
{
var path = new List\x3CPoint> { current };
while (cameFrom.ContainsKey(current))
{
current = cameFrom[current];
path.Insert(0, current);
}
return path;
}
}
Godot NavigationAgent2D
public class EnemyNavigation : CharacterBody2D
{
private NavigationAgent2D _navAgent;
private Node2D _target;
public override void _Ready()
{
_navAgent = GetNode\x3CNavigationAgent2D>("NavigationAgent2D");
// 配置
_navAgent.PathDesiredDistance = 10.0f;
_navAgent.TargetDesiredDistance = 10.0f;
_navAgent.Radius = 20.0f;
// 连接信号
_navAgent.VelocityComputed += OnVelocityComputed;
}
public void SetTarget(Node2D target)
{
_target = target;
UpdatePath();
}
private async void UpdatePath()
{
if (_target == null) return;
// 异步计算路径
_navAgent.TargetPosition = _target.GlobalPosition;
await ToSignal(_navAgent, NavigationAgent2D.SignalName.PathChanged);
}
public override void _PhysicsProcess(double delta)
{
if (_navAgent.IsNavigationFinished())
return;
var nextPos = _navAgent.GetNextPathPosition();
var direction = GlobalPosition.DirectionTo(nextPos);
var velocity = direction * Speed;
// 避障
_navAgent.Velocity = velocity;
}
private void OnVelocityComputed(Vector2 safeVelocity)
{
Velocity = safeVelocity;
MoveAndSlide();
}
}
群体行为
Boids 算法
public class Boid : Node2D
{
private Vector2 _velocity;
private List\x3CBoid> _neighbors = new();
public override void _Process(double delta)
{
// 更新邻居列表
UpdateNeighbors();
// 计算三个力
var separation = CalculateSeparation();
var alignment = CalculateAlignment();
var cohesion = CalculateCohesion();
// 合并力
var acceleration = separation * 1.5f + alignment * 1.0f + cohesion * 1.0f;
// 更新速度和位置
_velocity += acceleration * (float)delta;
_velocity = _velocity.LimitLength(MaxSpeed);
Position += _velocity * (float)delta;
}
private Vector2 CalculateSeparation()
{
var steer = Vector2.Zero;
int count = 0;
foreach (var neighbor in _neighbors)
{
float distance = Position.DistanceTo(neighbor.Position);
if (distance > 0 && distance \x3C SeparationRadius)
{
var diff = Position - neighbor.Position;
diff = diff.Normalized() / distance;
steer += diff;
count++;
}
}
if (count > 0)
steer /= count;
return steer;
}
private Vector2 CalculateAlignment()
{
var avgVelocity = Vector2.Zero;
int count = 0;
foreach (var neighbor in _neighbors)
{
if (Position.DistanceTo(neighbor.Position) \x3C AlignmentRadius)
{
avgVelocity += neighbor._velocity;
count++;
}
}
if (count > 0)
{
avgVelocity /= count;
avgVelocity = avgVelocity.Normalized() * MaxSpeed;
return avgVelocity - _velocity;
}
return Vector2.Zero;
}
private Vector2 CalculateCohesion()
{
var center = Vector2.Zero;
int count = 0;
foreach (var neighbor in _neighbors)
{
if (Position.DistanceTo(neighbor.Position) \x3C CohesionRadius)
{
center += neighbor.Position;
count++;
}
}
if (count > 0)
{
center /= count;
return (center - Position).Normalized() * MaxSpeed - _velocity;
}
return Vector2.Zero;
}
}
决策系统
效用 AI
public class UtilityAI
{
private readonly List\x3CUtilityAction> _actions = new();
public void AddAction(UtilityAction action)
{
_actions.Add(action);
}
public UtilityAction ChooseBestAction()
{
float bestScore = float.MinValue;
UtilityAction bestAction = null;
foreach (var action in _actions)
{
float score = action.CalculateScore();
// 添加随机性
score += GD.Randf() * 0.1f;
if (score > bestScore)
{
bestScore = score;
bestAction = action;
}
}
return bestAction;
}
}
public abstract class UtilityAction
{
public abstract float CalculateScore();
public abstract void Execute();
}
public class AttackAction : UtilityAction
{
private readonly Enemy _enemy;
public AttackAction(Enemy enemy)
{
_enemy = enemy;
}
public override float CalculateScore()
{
float score = 0f;
// 玩家距离近,分数高
float distance = _enemy.DistanceToPlayer();
score += Mathf.Clamp(1.0f - distance / 200.0f, 0, 1) * 0.5f;
// 有弹药,分数高
score += _enemy.HasAmmo ? 0.3f : 0.0f;
// 生命值高,更倾向于攻击
score += _enemy.HealthPercent * 0.2f;
return score;
}
public override void Execute()
{
_enemy.Attack();
}
}
感知系统
视觉感知
public class VisionSensor : Node2D
{
[Export] public float ViewDistance = 300.0f;
[Export] public float ViewAngle = 90.0f;
[Export] public LayerMask VisionLayer;
public Node2D Target { get; private set; }
public override void _Process(double delta)
{
Target = null;
var players = GetTree().GetNodesInGroup("player");
foreach (Node2D player in players)
{
if (CanSee(player))
{
Target = player;
break;
}
}
}
private bool CanSee(Node2D target)
{
var direction = target.GlobalPosition - GlobalPosition;
float distance = direction.Length();
// 检查距离
if (distance > ViewDistance)
return false;
// 检查角度
float angle = Mathf.RadToDeg(direction.Angle());
float angleDiff = Mathf.Abs(Mathf.AngleDifference(angle, GlobalRotationDegrees));
if (angleDiff > ViewAngle / 2)
return false;
// 射线检测
var space = GetWorld2D().DirectSpaceState;
var query = new PhysicsRayQueryParameters2D
{
From = GlobalPosition,
To = target.GlobalPosition,
CollisionMask = VisionLayer
};
var result = space.IntersectRay(query);
if (result.Count > 0)
{
var collider = result["collider"].As\x3CNode>();
return collider == target;
}
return true;
}
// 可视化调试
public override void _Draw()
{
// 绘制视野扇形
DrawArc(Vector2.Zero, ViewDistance, -ViewAngle / 2, ViewAngle / 2, 32, Colors.Yellow, 1.0f);
}
}
参考资源
- 行为树模式: references/behavior-trees.md
- 寻路算法: references/pathfinding.md
- 高级技术: references/advanced-ai.md
安全使用建议
This skill is an offline guide with code samples and appears safe and coherent for the stated purpose. Before enabling it for autonomous agent use, you may: (1) review the SKILL.md yourself to confirm it contains only the expected guidance, (2) be cautious if future versions add install scripts or request environment variables, and (3) prefer skills from a known source if you require provenance guarantees.
功能分析
Type: OpenClaw Skill
Name: game-ai
Version: 1.0.0
The skill bundle is benign. It contains standard metadata and a comprehensive markdown document providing educational content and C# code examples for game AI development using the Godot engine. There is no evidence of prompt injection attempts, malicious code, data exfiltration, or any other harmful behaviors targeting the OpenClaw agent or its environment. All code snippets are illustrative game logic, and internal links point to other documentation within the same bundle.
能力评估
Purpose & Capability
The name and description match the SKILL.md content: game AI design and Godot/C# examples. There are no unexpected credentials, binaries, or unrelated dependencies requested.
Instruction Scope
SKILL.md contains code examples and design guidance only. It does not instruct the agent to read system files, access environment variables, send data to external endpoints, or perform actions outside the stated domain.
Install Mechanism
No install spec or code files are present—this is instruction-only and nothing will be written to disk or downloaded during install.
Credentials
No environment variables, credentials, or config paths are requested; the skill does not ask for secrets or unrelated access.
Persistence & Privilege
always is false and model invocation is allowed (default). This is normal for a user-invocable instructional skill and does not grant elevated, persistent privileges.
如何使用
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install game-ai - 安装完成后,直接呼叫该 Skill 的名称或使用
/game-ai触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.0
FSM, behavior trees, pathfinding
元数据
常见问题
Game AI Systems 是什么?
Game AI development guide covering behavior trees, state machines, pathfinding, and decision-making systems. Use when implementing enemy AI, NPC behaviors, f... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 944 次。
如何安装 Game AI Systems?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install game-ai」即可一键安装,无需额外配置。
Game AI Systems 是免费的吗?
是的,Game AI Systems 完全免费(开源免费),可自由下载、安装和使用。
Game AI Systems 支持哪些平台?
Game AI Systems 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Game AI Systems?
由 Mr.Tang(@thb32133451)开发并维护,当前版本 v1.0.0。
推荐 Skills