手把手带你用机器学习写unity AI

2017unity机器学习社区挑战赛参加地址:https://connect.unity.com/challenges/ml-agents-1

打开下载的unity机器学习环境

里面有一些现成的demo,可以看一下这个插件到底能做什么。

这次皮皮陈带你做一个依靠角色视觉来寻找特定目标的demo

我们先新建一个Plane作为地板:

地板大小各位随意,我设为10

然后新建玩家角色和不同的目标对象,我用胶囊来代表角色,红色球体代表目标,绿色球体作为干扰目标。

新建3个空对象,分别作为随机生成ball的管理器,Academy和Brain

====================角色对象的设置=======================

先把环境中的Directional Light调暗

然后新建一个Spotlight作为角色虚拟视线范围

调好Spotlight的方向,然后挂到角色上

同时把角色的tag改为Player,再f给角色添加Rigidbody

========================两个ball的设置======================

给两个ball添加颜色材质,同时分别设置两个ball 的layer和Tag

比如红球

===================激动人心的代码部分========================

1,在地板上随机生成两个ball:

times -= Time.deltaTime;

if (times

{

int red_i = Random.Range(-50,50);

int red_j = Random.Range(-50,50);

int green_i = Random.Range(-50,50);

int green_j = Random.Range(-50,50);

GameObject red = (GameObject)Instantiate(red_ball);

GameObject green = (GameObject)Instantiate(green_ball);

red.transform.position= new Vector3(red_i,1, red_j);

green.transform.position= new Vector3(green_i,1, green_j);

times =2f;

用Random.Range()随机出特定区间的数值。

2,两个ball与角色碰撞后消失,然后把reward传回到agent

private void OnCollisionEnter(Collision collision)

{

FindAgent player = GameObject.Find("player").GetComponent();

if (transform.gameObject.layer== LayerMask.NameToLayer("Green_ball"))

{

player.reward= -1f;

}

else

{

player.reward= +5f;

}

if (collision.gameObject.tag=="Player")

{

Destroy(ball);

}

}

3,生成角色虚拟视线

void DrawFieldOfView()

{

// 获得最左边那条射线的向量,相对正前方,角度是-45

Vector3 forward_left = Quaternion.Euler(, -45,) * transform.forward* eye_distance;

for (int i =; i

{// 每条射线都在forward_left的基础上偏转一点,最后一个正好偏转90度到视线最右侧

Vector3 v = Quaternion.Euler(, (90.0f / eye_angle) * i,) * forward_left; ;

// 创建射线

Ray ray = new Ray(transform.position, v);

RaycastHit hitt = new RaycastHit();

// 射线只与两种层碰撞,注意名字和你添加的layer一致,其他层忽略

int mask = LayerMask.GetMask("Wall","Red_ball","Green_ball");

Physics.Raycast(ray,outhitt, eye_distance, mask);

// Player位置加v,就是射线终点pos

Vector3 pos = transform.position+ v;

if (hitt.transform!= null)

{

// 如果碰撞到什么东西,射线终点就变为碰撞的点了

pos = hitt.point;

}

// 从玩家位置到pos画线段,只会在编辑器里看到

Debug.DrawLine(transform.position, pos, Color.red); ;

// 如果真的碰撞到敌人,进一步处理

if (hitt.transform!= null && hitt.transform.gameObject.layer== LayerMask.NameToLayer("Red_ball"))

{

red_ball = hitt.transform.position;

}

if(hitt.transform!= null && hitt.transform.gameObject.layer== LayerMask.NameToLayer("Green_ball"))

{

green_ball = hitt.transform.position;

}

}

}

4,重点!agent的编写

InitializeAgent()类似Start()的初始化方法

publicoverridevoidInitializeAgent()

{

red_ball = get_from_PlayerMove.red_ball;

green_ball = get_from_PlayerMove.green_ball;

}

List CollectState()每一个训练相关的数值都要在这里,比如在这个demo中,我们要角色自动寻找目标同时还要区分干扰目标,那我们就要让Brain知道,角色的移动,朝向,所以添加了角色的position和rotation,还有两个ball的坐标。另外需要理解一点,不管你什么机器学习,一定是数值到算法层,比如图像识别,最后都是把图像降维成数值再处理。所以这里CollectState()内传到Brain的都是单个数值,比如要传角色的位置,传Vector3类型是不行的,因为Vector3是有3个值得向量(x,y,z),所以你要传角色位置,你把3个方向的数值一个个传。

AgentStep(float[] act)每一步的行动,比如在这个demo中,我们要角色一直移动,所以在AgentStep(float[] act)中添加角色移动,另外这里的act参数是怎么回事呢。act有两种模式,一种是离散,一种是连续。比如在这个demo中我把act设置为离散,因为角色的行为无非是左转右转和向前,那么我们把act为0时作为角色向前的信号,1和2作为角色向左和向右,用离散就合适了,离散和连续在Brain中的action设置即可。

public override void AgentStep(float[] act)

{

reward = -0.01f;

int action = Mathf.FloorToInt(act[]);

if (action ==)

{

player.transform.Translate(,,1, Space.Self);

}

if (action ==1)

{

player.transform.Rotate(, -10,, Space.Self);

}

if (action ==2)

{

player.transform.Rotate(,10,, Space.Self);

}

if (player.transform.position.x>=50player.transform.position.x=50player.transform.position.z

{

reward = -10f;

done = true;

}

}

AgentReset()重置方法,就是一次训练结束了,环境怎么重置。比如我们这个demo,什么时候需要重置?当然是角色跑到地板意外的地方啦,一旦角色离开地板,那么我们就重置环境,把角色重置在地板的中心位置,并给予角色惩罚,让它知道它的活动范围只能在地板范围上。

publicoverridevoidAgentReset()

{

transform.position =newVector3(,1,);

}

本文来自企鹅号 - CCH陈常鸿媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ThoughtWorks

TW洞见〡3D打印的各种问题及解决方案

文章作者来自ThoughtWorks:贺思聪 ,图片来自网络。 3D打印机已经买回来几个月了,基本上每天都要打印一些东西,期间遇到了很多的问题积累了很多的经验...

38812
来自专栏吉浦迅科技

DAY 60:阅读SIMD Video Instructions

我们正带领大家开始阅读英文的《CUDA C Programming Guide》,今天是第60天,我们正在讲解CUDA C语法,希望在接下来的40天里,您可以学...

801
来自专栏吉浦迅科技

DAY59:阅读 #pragma unroll

By default, the compiler unrolls small loops with a known trip count. The #pragm...

612
来自专栏Leetcode名企之路

服务端开发95th 99th 是什么意思?

作者:滔滔不绝 链接:https://www.zhihu.com/question/20575291/answer/22814728 来源:知乎

911
来自专栏PPV课数据科学社区

【教程】一小时向非程序员介绍 R 编程语言

(1)下载R和RStudio 我对RStudio的印象不错,对于初学者来说,它既方便又很有帮助,对专业人士也很有用。尤其对于初学者:鼠标指向-点击式(point...

2908
来自专栏数据小魔方

R语言学习笔记——柱形图

今天分享R语言中的柱形图,所有图表语法都基于ggplot2包中的ggplot函数完成 。 其实R语言本身就带有各种作图函数,比如plot、bar、pie等,而且...

48613
来自专栏机器学习和数学

[Tensorflow] TensorFlow之Hello World!(1)

哇!今天挺开心的,30天的时间,19篇文章,2459人阅读,5313人次阅读!今天开通的原创标识,恩!除了激动,就是非常感谢大家的支持!感谢大家的支持!大家的支...

3406
来自专栏生信技能树

生信技巧第3课-请你务必学好R语言

2383
来自专栏CDA数据分析师

如何高效地学好 R?

本文由知乎著名答主黄宝臣原创,CDA数据分析师已获得授权 学R主要在于5点三阶段: 第一阶段有一点:基础的文件操作(read.*,write.*)、数据结构知...

1955
来自专栏机器之心

学界 | 为代码自动添加注释,让 Java 程序的阅读和开发更高效

3577

扫码关注云+社区