前言
大家好,如题目所说的,我给自己开(wa)了一个坑,专门讲讲和游戏AI有关的内容。难度不高,会从非常非常基础开始,假定用户是我家的大猫 (´・ω・`) 。
现在Unity方面的教程和视频可以说是汗牛充栋,为了找到有特点的角度作者我也是煞费苦心。机缘巧合最近在做一些游戏AI相关的内容,于是就开了这个坑。
废话不说,第一节作为适应课程,内容相对很少,但是之后有不少例子是基于这种俯视角游戏的,俯视角游戏在观察AI行为方面很直观很好用,所以要先搭一个学习用的工程。没基础的同学跟着自己做一下就能搞定,有基础的同学可以一遍扫过去毫无压力。
一、场景搭建
按照上图所示,搭建一个简单的场景
1、创建一个平面作为地板,地板放大一些,3倍左右,地板默认有Mesh Collider组件。
2、放几个方块Cube作为障碍物,Cube默认有碰撞体Box Collider组件。
3、创建一个胶囊体代表玩家,正面最好加上一个彩色的方块以区分正面在哪。下面有主角特写,感觉有点像小黄人。
4、创建材质可以用来改变贴图的颜色。在Assets目录里创建Material,然后调个颜色,拖到物体上即可。下面有截图。
5、为方便起见,给主角加上Rigid Body刚体组件,这是一种物理有关的组件。有了它就可以用速度、力等方法控制角色了。但是这里注意取消重力,也就是取消Use Gravity。
前面的步骤非常基本,我家的猫已经做完了。接下来要写点代码控制主角的移动。
6、在Project窗口Assets文件夹点击右键——Create新建——C# Script,创建一个新的C#脚本,命名为Player,拖拽到场景里的Player上(胶囊体)。
7、双击这个脚本,开始编辑吧。我们的代码都经过了简化,力求简单。
public class Player : MonoBehaviour {
// 用于控制移动速度,public变量方便在编辑器里修改
public float moveSpeed = 6;
// 代表刚体组件的变量
Rigidbody myRigidbody;
// Player GameObject初始化时调用
void Start()
{
// 在这里给myRigidbody变量赋值,方便后面的使用。
// 如果不用这个变量也可以,那每次都需要GetComponent<Rigidbody>,会很麻烦。
myRigidbody = GetComponent<Rigidbody>();
}
// 每帧被引擎调用一次,下面详细说明
void Update()
{
// 后面添加
}
}
8、我们打算用鼠标+键盘控制Player的移动,和大量流行的俯视角射击游戏是一样的,鼠标用来指方向、开火。键盘的WASD用来移动。首先解决鼠标指哪,主角就转向哪的问题:
根据鼠标位置,创建一个射线:
// 说明:鼠标在屏幕上有一个位置Input.mousePosition,这个位置和游戏无关
// 就是你windows鼠标的位置而已
// 通过Camera.main,也就是主摄像机的,就可以把鼠标位置转换到游戏中去,制造一条射线
// 这个射线很好理解,你拿一根针,垂直屏幕,戳在鼠标的位置,就是这条射线ray了。
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
我们拿着这个射线让它往垂直屏幕的方向射过去,就会碰到物体(准确的说是有Collider碰撞组件或者Rigid Body刚体组件的物体),然后碰撞的交点就是我们输入的点:
// 先创建一个RaycastHit变量,也就是射线碰撞信息,在下面一句用到。
RaycastHit hitt = new RaycastHit();
// 这句话的意思:让射线ray打出去,距离100(很长的距离),把碰撞结果返回到hitt变量中。
// out参数就是用来输出结果的,是C#特有的写法。
Physics.Raycast(ray, out hitt, 100, LayerMask.GetMask("Ground"));
如果不严谨地做,最后的LayerMask.GetMask("Ground")参数是不需要的,不写的话如果鼠标当前位置正好是Player或者障碍物,就可能会造成偏差。所以我们限定射线只能和地板碰撞,穿过其他东西。这里需要设置一下地板的Layer,如下图操作:
在任意一个空白的Layer上写上Ground,就创建了一个Ground层。然后把地板的Layer设置为Ground层即可。
接着写代码:
// 打印Log,方便查看碰撞是否成功了。如果不成功八成是Layer设置的问题
Debug.Log("hitt", hitt.transform);
// 如果碰撞到了东西
if (hitt.transform != null)
{
// 让当前物体(也就是挂着这个脚本的Player)转向目标点。注意目标点的写法。
transform.LookAt(new Vector3(hitt.point.x, transform.position.y, hitt.point.z));
}
Update函数整个代码如下:
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitt = new RaycastHit();
Physics.Raycast(ray, out hitt, 100, LayerMask.GetMask("Ground"));
Debug.Log("hitt", hitt.transform);
if (hitt.transform != null)
{
transform.LookAt(new Vector3(hitt.point.x, transform.position.y, hitt.point.z));
}
}
9、经过步骤8的详细说明,我们已经可以能让主角跟随鼠标转动了,播放一下,看看效果。
10、之后添加用WASD移动的代码,很简单只有一句,加在Update函数的最后面一句即可:
myRigidbody.velocity = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized * moveSpeed;
这一句对新手很不友好,可以解释为以下N句:
// 获得输入的H轴和V轴,也就是横轴和纵轴,也就是W、S键或是A、D键的状态。
float input_h = Input.GetAxisRaw("Horizontal");
float input_v = Input.GetAxisRaw("Vertical");
// 输入是一个-1~+1之间的浮点数,把它转化成方向向量
Vector3 vec = new Vector3(input_h, 0, input_v);
// 当W键和D键同时按下时,vec会比单按W键要长一些,你可以想想为什么。
// 所以这里要把输入归一化,无论怎么按键,vec长度都要一致。
vec = vec.normalized;
// 乘以moveSpeed可以让调整vec的长度
vec = vec * moveSpeed;
// 把vec赋值给刚体的速度,就可以让刚体运动起来了
myRigidbody.velocity = vec;
以上两种方法,任选一种,初学者建议把后面这段,粘贴到Update函数里面,最后的位置。
11、这样,我们的主角就动起来咯~~
小结
本节课程基础到没朋友,前半部分我真怀疑大猩猩经过训练也能做出来 o(*≧▽≦)ツ┏━┓
主要是让我自己也熟悉一下,下节课就开车咯,大家要亲手做一下才能上车。
————————————————————————————————————
对游戏开发感兴趣的同学,欢迎围观我们:【皮皮关游戏开发教育】 线下教育自不必说,还会定期更新各种教程,干货。
我们的官网地址:http://levelpp.com/
我们的游戏开发技术交流群:610475807
我们的微信公众号:皮皮关
暂无关于此日志的评论。