Aimbot-ParallelEnv/README.md
2024-01-24 17:02:48 +09:00

20 KiB
Raw Blame History

Aimbot-ParallelEnv

这是一个基于Unity ML-Agents的基于FPS游戏的多智能体训练环境用于生成指定目标和对应难度并且根据Agent的Action反馈Reward来训练强化学习Agent的环境。

Chinese badge Japanese badge

Description

项目基于ML-Agents 2.0.1使用Unity 2021.3.14f1开发。 Python侧则使用mlagents-envs 0.30.0与环境进行通信。

快速开始

在项目Aimbot-PPO使用了本环境进行了PPO算法的训练其中在AimbotEnv.py中给出了本环境的使用方法。

游戏简介

这是一个模仿初代Doom的基本模式的FPS游戏环境Agent将会被给到不同的目标Agent需要根据目标的类型和位置以及自身的状态来决定是否开枪射击射击的方向以及移动方向。环境内包含两种模式和3种目标分别是训练模式和测试模式以及FreeTargetGotoTargetAttackTargetFreeTarget需要Agent使用武器击倒区域内所有的敌人GotoTargetAttackTarget会在区域内生成一个目标区块Agent需要对目标区块进行不同的对应来完成任务。同时GotoTargetAttackTarget根据生成目标区块的构造不同分为了5种不同的难度。

模式介绍

训练模式和测试模式都需要与Python侧进行通信根据从本环境中观测到的Observation生成Action并传递回本环境。在环境启动时需要使用者在游戏内进行操作来选择模式由于ML-Agents存在Time limit所以需要在45s内进行模式选择超过45s后将自动退出游戏环境。

训练模式

在进入训练模式前使用者需要从Start界面中只训练单个模式的Train-FreeTrain-GotoTrain-Attack和训练所有模式的Train-Mix中进行选择。在选择后,将会进入训练模式,并且注意该选择不能在之后进行更改。对于拥有多种难度的目标区块的模式Train-GotoTrain-Attack在Start界面将会有一个用来调整生成不同难易度目标区块的概率的面板默认的生成概率为平均。面板为了保证该模式各难易度生成概率总和为1在调整某一难度的生成概率时其他难度的生成概率将会被自动调整用户可以通过点击右侧锁定按钮以锁定或解锁某一难度的生成概率。该面板将在训练模式执行中也可见用户在训练模式执行中对概率面板进行调整后将会在应用在下次目标区块生成时。
TargetLevelProbabilityPanel

测试模式

测试模式中用户需要手动来对Agent下达命令用户可以通过点击右上角的菜单来执行生成目标区块或敌人切换目标模式等。在该模式中比训练模式多出一个新的Target为StayTarget当用户未指定目标或者清空游戏时将会以将该Target指派给Agent。通过点击右上角的菜单可以将鼠标的模式切换为生成Enemy或者生成对应难度Target区块的模式此时鼠标移动到游戏区域内后将会出现生成物件的预览内点击鼠标右键则可以在对应的位置生成对应的Enemy或者区块。当生成Target区块时会自动指派对应target给agent需要指派FreeTarget时则需要点击FreeMode按钮。通过点击ClearGame可以清空所有enemy和区块并将Agent的目标指派为StayTarget,通过点击StayMode则可以强制将Agent目标指派为StayTarget

目标介绍

FreeTarget

在Agent被指派到FreeTargetAgent需要使用武器击倒区域内所有的敌人。在该模式中一个回合开始时将会在区域内随机生成一定数量的敌人默认为6Agent将会生成在区域的随机位置Agent朝向继承上一回合如果是第一回合则是默认角度为0。Agent在成功击倒所有敌人后被判断为胜利或者超过30s未能成功击倒所有敌人则被判断为失败。

GotoTarget

在Agent被指派到GotoTargetAgent的目标是移动到指定目标区块的指定位置。在该模式中一个回合开始时Agent的位置总是继承上一个回合如果是第一回合将会默认生成在地图的左下角。Goto的目标区块将会根据难度概率在区域内随机生成对应难度的预设区块不同难易度拥有多个已保存好的预设区块这些预设区块通过SceneBlocksSet保存在Prefab文件夹中。所有目标区块的总大小为10*10生成目标区块时区块将会避开Agent的所在位置。指定目标区域是名为FireBase的圆形区域该区域所覆盖的范围不会超过目标区块但是它的位置和大小会根据预设区块的不同而不同。Agent在成功移动到目标区块中心位置后被判断为胜利或者超过30s未能成功移动到目标区块中心位置则被判断为失败。

AttackTarget

在Agent被指派到AttackTargetAgent的目标是对目标区域进行火力压制同时主要目标是击倒区块内所有敌人。在该模式中Agent与目标区块的生成策略还有FireBase的构成与GotoTarget相同。但是在AttackTargetFireBase区域内必定会有Enemy生成。Agent在成功击倒区块内所有敌人后被判断为胜利或者超过30s未能成功击倒区块内所有敌人则被判断为失败。


Environment

Observation Space

在本强化学习训练设置中,观测数据是理解和交互环境的关键。观测环境由三个主要部分组成:TargetState(目标状态)、AgentState(自机状态)和RaycastState射线探测状态。这些观测数据通过ML-Agents的VectorSensor类进行收集并发送给Python侧为决策提供必要的信息。Observation的Source Code位于MLAgentsCustomController.cs中被override的CollectObservations函数中。

TargetState目标状态

TargetState包含了Agent接收的目标指令和相关信息,总大小为6。其中包含Target的类型Target的x,y,z坐标TargetArea的直径以及Agent是否处于TargetArea和本回合剩余时间内这些信息。

Num Observation Size State Space Description
0 Target类型 1 0,1,2,3,4 描述被指派的Target类型0=FreeTarget1=GotoTarget2=AttackTarget3=DefenceTarget未使用4=StayTarget
1~3 Target坐标 3 0~47 描述Target中Firebase的连续空间坐标取值范围为0到47之间的连续值
4 FireBaseDiameter 1 1~10 描述FireBase的直径取值范围为在1到10之间的连续值
5 InFireBaseState 1 0,1 描述Agent是否处于FireBase中0=False1=True
6 RemainTime 1 0~30 描述本回合剩余时间取值范围为在0到30之间的连续值

AgentState自机状态

AgentState包含了Agent的武器可攻击状态Agent的x,y,z坐标和Agent的朝向角度。为了避免直接使用Agent GameObject朝向角度时0到360度变化时值的大幅度跳变同时为了实现更好的周期性表示这里使用了Agent GameObject旋转角度的余弦和正弦值来表示Agent的朝向。

Num Observation Size State Space Description
7 GunState 1 0,1 描述Agent武器是否处于可使用状态。0=False1=True
8~10 Agent坐标 3 0~47 描述Agent的连续空间坐标取值范围为0到47之间的连续值
11~12 Agent朝向 2 -1~1 通过计算Agent GameObject旋转角度的余弦和正弦以描述Agent的正面朝向。

RaycastState射线探测状态

RaycastState记录了视野内发射的射线探测到的Object的Tag及其距离、其中Tag可以通过Label Encoding和OneHot Encoding两种方式来记录默认使用Label Encoding可以在ObjectCommonParameterContainer中进行调整。RaycastStateRaySensors类管理。它实现了射线的非均匀分布默认视野中间15%的区域射线分布更密集两侧则较为稀疏默认中间密集部分共射出5条两侧稀疏部分各7条。 每个射线可探测的对象最远距离为100个单位超过探测距离则返回0。其中视野中间区域的覆盖范围区域内RayCast数量以及可探测距离均可以在每个AgentGameObject的Inspector中进行调整。
射线分布方式

Num Observation Size State Space Description
11~Raynum+11 TagType(Label) Number of Raycasts 0, 1, 2 描述Raycast所探测到物体的Tag, 0=Wall, 1=Enemy, 2=Player, -1=Nothing
11~Raynum * 3+11 TagType(Onehot) Raynum * 3 0, 1 描述Raycast所探测到物体的Tag, 使用Onehot编码记录
Raynum+12~2* Raynum+12(Label),
3* Raynum+12~4* Raynum+12(OneHot)
Distance Number of Raycasts 0~MaxDistance 描述Raycast所探测到物体的距离取值范围在0~MaxDistance其中MaxDistance默认为100

n为每个Agent的RayCast数量MaxDistance为每个Agent的RayCast最大探测距离

Action Space

为了模拟FPS游戏中玩家对于键盘和鼠标的同时操作本环境中的Action Space分为两个部分分别是Discrete ActionContinuous Action。其中Discrete Action用于模拟玩家对于键盘的离散操作,Continuous Action用于模拟玩家对于鼠标的连续操作。两个Action Space的对应操作可以参考于MLAgentsCustomController.cs中被override的Heuristic函数。具体实现则于AgentController.cs中的MoveAgentCameraControl函数中。

Discrete Action

Discrete ActionAgent可以对各方向的移动和攻击进行离散操作其中移动操作包括垂直移动操作和水平移动操作攻击操作可以对武器进行操。

Num Action Action Space Description
0 Vertical Move 0,1,-1 用于控制Agent在其正面方向的垂直轴上移动。0=停止1=向前移动,-1=向后移动
1 Horizontal Move 0,1,-1 用于控制Agent在其正面方向的水平轴上移动。0=停止1=向右移动,-1=向左移动
2 Attack 0,1 用于控制Agent的攻击操作。0=不攻击1=执行攻击

Continuous Action

Continuous Action可以对Agent的视角进行操作。由于本环境是模拟早期Doom的FPS环境所以Agent的视角被设定为仅能在水平方向上进行旋转。

Num Action Action Space Description
0 Vertical Rotation -Inf~Inf 控制Agent在水平方向左右上的视角旋转。正值使视角向右负值则使视角向左旋转。

Reward

在各给定的目标中为了让Agent注重于完成不同的任务Reward的设计也有所不同。在训练模式中Reward由共同RewardCommon Reward和各个目标的专用Reward组成。

Common Reward

为了引导Agent在训练过程中执行对完成目标有帮助的操作和避免无意义的动作Common Reward环境为Agent设计了以下的Reward和Penalty。其中由于ML-Agents不能向Python直接传递回合结束的结果同时为了避免其他Reward数值过小或者过大导致无法判断胜利或者失败因此在回合结束的Reward中添加了极大数和极小数来表示胜利和失败。

Reward/Penalty Value/Symbol Description
NonTargetHit 3 当Agent击中或者击倒不作为Target的敌人时所获得Reward
TargetHit 25 当Agent击中或者击倒作为Target的敌人时所获得Reward
MovePenalty -0.5 当Agent在场地中移动时给到的Penalty
SpinPenalty P_s 当Agent进行视角旋转时给到的Penalty
WinReward 999 当回合结束并且本回合Agent达成目标时给到的Reward
LoseReward 999 当回合结束并且本回合Agent失败时给到的Reward

为了防止Agent在训练中出现无意义的旋转和旋转过快这里用下列函数来给到Agent一个SpinPenalty。当40个Action的旋转记录未达到阈值时会给到一个较小的Penalty而当超过阈值时我们可以知道Agent正在向同一方向持续旋转则给到一个较大的Penalty。其中Pst为在t时刻时的旋转的PenaltymouseXtt时刻Agent的Contunuouse Action中的旋转Action数值。


P_{st} = 
\begin{cases} 
  -|mouseX_t| \cdot 0.06 &, & \left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| < 10 \\
  -\left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| & , & \left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| \geq 10 
\end{cases}

FreeTarget

FreeTarget主要目标是消灭所有敌人因此追踪敌人的能力非常关键。本模式设置了两种奖励机制当视野中心探测到敌人时给到Agent一个为2的Reward当未探测到敌人时则根据探测到的敌人距离视野中心的距离 D 给到一个小于2的Reward。距离的计算仅考虑通过 Raycast 探测到的敌人且当距离越接近0.5即Enemy半径则Reward越接近2。例如,在图中,只计算了与Enemy1Enemy3的距离,并且取用最短距离 D_1 来计算Reward。未探测到的Enemy2Enemy4被排除在外。在这个模式下所有敌人都被视为目标当敌人被击败或击中时Agent 将获得Common Reward中的TargetHit Reward
FacingReward

Reward/Penalty Value/Symbol Description
FacingReward R_f 视野中心与所探测到最近敌人距离的Reward

R_{f} =
\begin{cases} 
  2 &, &min(D) \leq 0.5 \\
  \frac{1}{\sqrt{\frac{min(D)}{2}}} &,& min(D) \gt 0.5
\end{cases}

GotoTarget

GotoTarget中,主要目标是向指定的FireBase移动。根据在t时刻和t-1时刻的玩家与目标间的距离 D_tD_{t-1} 的差值,设置了每个 Step 可获得的距离奖励 R_d 。当Agent接近目标时将获得正向Reward远离目标时则获得小于0的Penalty。当玩家处于FireBase内时,可以获得更高的固定奖励,然而此时DistanceReward将不会生效。在此模式中,所有敌人均不被视为攻击目标,但在击中或击败敌人时,可以获得Common Reward中的NonTargetHit

Reward/Penalty Value/Symbol Description
DistanceReward R_d Agent不在目标内时和目标的距离差Reward
InAreaReward 5 Agent处于目标内时的持续奖励

R_{d} = (D_{t-1} - D_{t}) \cdot 20

AttackTarget

在 Attack Mode 中主要目的是消灭目标地点的敌人并鼓励Agent对目标地点进行设计。因此与FreeTarget类似将视线移动到目标地点同样重要。当Agent面对目标地点并且进行攻击时将会被视为压制行为并获得较低的SuppressiveReward。面对目标地点但未进行攻击时,获得持续获得更低的FacingAreaReward。处于FireBase中的Enemy将会被视为目标当敌人被击败或击中时Agent 将获得Common Reward中的TargetHit Reward。而FireBase外的敌人则不会被视为目标当敌人被击败或击中时Agent 将只能获得Common Reward中的NonTargetHit Reward

Reward/Penalty Value/Symbol Description
SuppressiveReward 5 Agent对FireBase进行压制攻击时获得奖励
FacingAreaReward 2 Agent面朝目标时获得的持续奖励

Side Channel

为了方便对于环境的调试和实现Unity与Python间非实时通信本环境中使用了ML-Agents提供的Side Channel用于向Python侧传递一些额外的信息。这里我参考了huggingface的Custom Side Channels。在Unity端Side Channel的实现位于AimbotSideChannel.csAimBotSideChannelController.cs中。每个Log信息将会以|来分隔字段其中第一个字段为Log的类型随后字段为自定义Log信息。在本环境中Unity的SideChannel将会发送所有LogType.WarningLogType.Error类型的Log到Python侧。其中LogType.Warning会传递一回合结束后的的胜败信息和从Unity发送至Python的指令。胜败信息将类似于Warning|Result|WinWarning|Result|Lose。而指令则传递了在下一训练结束后保存模型的命令,它的内容为Warning|Command