unity2D学习(10)创建敌人、为敌人编写简单的AI
1 创建敌人
按照之前创建Player角色的方法,一样创建出敌人,并为角色添加刚体、碰撞、动画。具体可以参考我之前的unity2D学习(4)(5),具体的细节就不放在这里了。
素材包里面有三种敌人(crab、jumper、octopus),我选择crab来做示范动画状态转移。把Animation新建在Asserts->Animation->Enemies->Crab里面,其它类型的敌人以此类推。
参数判断:
- Walk->Idie:speed小于0.01f
- Idie->Walk:speed大于0.01f
2 为敌人设置简单ai
我的想法:如果Player角色出现在某一范围内,敌人就会朝玩家走去碰撞,然后走到边缘就会停下来。因为我后面想写一个玩家碰到敌人就会受伤的效果,所以我希望敌人会主动去碰撞玩家。
思路:
- 敌人判断Player是否是在敌人的某个范围内:可以用Physics2D.OverlapCircle,来判断角色的碰撞体是否在圆形范围里面,然后根据Player在敌人左边还是右边来改变方向。
利用Physics2D.OverlapCircle判断玩家是否进入视野,和上一章unity2D学习(9)中判断碰墙的方法一样。
但是这次有点不同就是,如果用Collider2D类型来获取Physics2D.OverlapCircle就可以得到碰撞对象Collider2D,上一章里面使用Bool类型来获取得到就是“是否碰撞到”。还有需要为Player玩家设置一个Layer层来做判断用。
Collider2D isPlayerView()//判断玩家是否进入了视野{return Physics2D.OverlapCircle((Vector2)transform.position, collisionRadius,playerLayer);//判断是否碰到玩家}
利用获取的Collider2D类型来判断敌人在玩家的那个方向。但是要注意敌人的动画的朝向初始是朝向左边的和主角不一样。敌人初始的横向向量虽然是正,但是动画的朝向起始对应的是左边。
void AccordingDirectionFlip(Collider2D playerColl)//根据玩家是否出现在视野中,安排敌人转向{if (playerColl != null)//如果玩家出现视野中{int direction;if (playerColl.transform.position.x < transform.position.x){direction = -1;//玩家在敌人的左边}else{direction = 1;//玩家在敌人的右边}if (direction != face)//表示方向不一致{//Debug.Log(direction);Flip();}}}void Flip()//翻转角色方向{face = (face == 1) ? -1 : 1;transform.localScale = new Vector2(face*(-1), 1);//乘-1是因为初始动画朝向是朝着左边的,但是初始坐标却是1,是相反的}
- 敌人跟随Player会走到边缘,需要停下:用射线Physics2D.Raycast来判断是否走到了边缘。
Physics2D.Raycast介绍
作用:检查对撞机是否落在射线上。
public static RaycastHit2D Raycast(Vector2 origin, Vector2 direction, float distance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, float minDepth = -Mathf.Infinity, float maxDepth = Mathf.Infinity);
origin | 二维空间中射线起源的点 |
direction | 表示射线方向的向量 |
distance | 投射射线的最大距离 |
layerMask | 检测的特定Layer的对象 |
minDepth | z轴大于或等于此值的对象 |
maxDepth | z轴小于或等于此值的对象 |
设置Physics2D.Raycast的射线方向的向量为45°(斜着向下),然后检测的特殊Layer层为之前创建的Ground的Layer(之前TileMap的Layer层),然后起始源点为敌人自己的坐标。
涉及到的变量Vector2 down = new Vector2(0, -1);//控制射线角度的向量private float radialLength = 1.5f;//射线的长度beg = transform.position;//射线起点,这个要每帖更新核心代码bool isBorder()//判断是否已经抵达边境{//也可以采用Debug的方式可视化射线//Debug.DrawLine(beg, beg + (new Vector2(face, 0) + down) * radialLength, Color.red);if (!Physics2D.Raycast(beg,new Vector2(face,0)+down, radialLength, LayerMask.GetMask("Ground")))//抵达边境{return true;}return false;}
这种方法射线和圈不好调整,为了方便调整参数,绘制辅助线来可视化。(具体代码看文章的末尾)
3 总代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnamyController : MonoBehaviour {private Rigidbody2D rig;//刚体private Animator Anim;//动画[Header("Layers")]public LayerMask playerLayer;//用来开启layer[Space][Header("Collision")]private Collider2D coll;//碰撞器[SerializeField] private float collisionRadius = 5f;//检测碰撞半径Vector2 beg;//射线起点Vector2 down = new Vector2(0, -1);//控制射线角度的向量[SerializeField] private float radialLength = 1.1f;//射线的长度[Space][Header("Speed")]private float moveSpeed = 100f;//移动速度[SerializeField] private float face;//朝向void Start () {rig = GetComponent<Rigidbody2D>();//获取刚体组件Anim = GetComponent<Animator>();//获取动画组件coll = GetComponent<Collider2D>();//获取碰撞器face = -1;//初始朝向是负的,和角色不同的地方,face-1代表朝向左边playerLayer = 1 << 9;//把玩家Layer放在Layer9}void FixedUpdate(){beg = transform.position;Collider2D playerColl = isPlayerView();if (isBorder())//是否到边缘{Debug.Log("hello");rig.velocity = new Vector2(0,0);AccordingDirectionFlip(playerColl);}else //不到边缘就可以移动{AccordingDirectionFlip(playerColl);Move();}}void AccordingDirectionFlip(Collider2D playerColl)//根据玩家是否出现在视野中,安排敌人转向{if (playerColl != null)//如果玩家出现视野中{int direction;if (playerColl.transform.position.x < transform.position.x){direction = -1;//玩家在敌人的左边}else{direction = 1;//玩家在敌人的右边}if (direction != face)//表示方向不一致{//Debug.Log(direction);Flip();}}}void Flip()//翻转角色方向{face = (face == 1) ? -1 : 1;transform.localScale = new Vector2(face*(-1), 1);//乘-1是因为初始动画朝向是朝着左边的,但是初始坐标却是1,是相反的}bool isBorder()//判断是否已经抵达边境{//也可以采用Debug的方式可视化射线//Debug.DrawLine(beg, beg + (new Vector2(face, 0) + down) * radialLength, Color.red);if (!Physics2D.Raycast(beg,new Vector2(face,0)+down, radialLength, LayerMask.GetMask("Ground")))//抵达边境{return true;}return false;}Collider2D isPlayerView()//判断玩家是否进入了视野{return Physics2D.OverlapCircle((Vector2)transform.position, collisionRadius,playerLayer);//判断是否碰到地面}void Move()//左右移动{rig.velocity = new Vector2(face*moveSpeed * Time.deltaTime, rig.velocity.y);//输入x,y向量,数值*方向}void ChangeAnimator()//动画状态转换{Anim.SetFloat("speed", Mathf.Abs(rig.velocity.x));//速度是向量}void OnDrawGizmos()//绘制辅助线{Gizmos.color = Color.red;//辅助线颜色Gizmos.DrawWireSphere((Vector2)transform.position, collisionRadius);//绘制射线Gizmos.DrawLine((Vector2)transform.position, (Vector2)transform.position+(new Vector2(face, 0) + down)*radialLength);//绘制圆形}}
unity2D学习(10)创建敌人、为敌人编写简单的AI相关推荐
- Unity2D学习笔记Day9:添加敌人——受伤效果及反弹效果(补8.16)
学习资源:B站 M_Studio<Unity教程2D入门>14 Unity Assets:Sunnyland Day9 受伤并反弹 预期效果:若在地面上碰到敌人,会触发受伤动画并反弹. p ...
- ROS学习笔记九:用C++编写ROS发布与订阅
ROS学习笔记九:用C++编写ROS发布与订阅 本节主要介绍如何用C++编写一个简单的ROS发布与订阅. 编写发布节点 在之前创建的例子beginner_tutorials软件包中,在其目录下的src ...
- ROS2_Foxy学习10——多机激光SLAM准备篇
ROS2_Foxy学习10--多机激光SLAM准备篇 1 安装Ubuntu20.04 mate 2 安装ROS noetic 3 安装cartographer 4 详细配置cartographer 5 ...
- 小白的奇幻数学课堂(part2)--敌人的敌人就是朋友,这其实就是负负得正法则
学习笔记 学习书目:<x的奇幻之旅>–史蒂夫•斯托加茨 敌人的敌人就是朋友 绕开负数 减法运算其实给我们制造了一些加法运算中不会出现的复杂问题:减法会产生负数.减法的出现,使得人类不得不扩 ...
- ROS 创建msg和srv 编写发布者和订阅者节点 编写服务端和客户端节点(python版本)
ROS 创建msg和srv 编写发布者和订阅者节点 编写服务端和客户端节点-python版本 rosed msg和srv 创建msg 使用rosmsg 创建srv 使用rossrv 重新make一下软 ...
- ROS学习笔记十:用C++编写一个简单的服务和客户端
ROS学习笔记十:用C++编写一个简单的服务和客户端 这一节主要介绍如何使用C++编写一个简单的服务和客户端节点. 编写服务节点 由于在前面的练习中,已经向beginner_tutorials软件包中 ...
- unity2D学习笔记-角色动画
unity2D学习笔记-角色动画 角色移动 动画效果(重点!!!!!) 创建:Animator与Animation 状态转换 跳跃 从fall到idle Hierarchy中创建一个Sprite作为载 ...
- 2021-08-09-ROS学习-消息创建,发布者和订阅者实现及测试
2.ROS中创建msg 在软件包里定义一个新的消息 $ roscd beginner_tutorials $ mkdir msg $ echo "int64 num" > m ...
- 深度学习-10:人工智能简史及三剑客
深度学习-10:人工智能简史及三剑客 深度学习原理与实践(开源图书)-总目录 1 人工智能简史 深度学习理论的突破和深度学习硬件加速能力的突破,使AI在模式识别.无人驾驶.智力游戏领域取得空前的成功. ...
最新文章
- 数学建模之图像处理---颜色建模
- .net2.0下数据库连接字符串的使用
- java读取 info.plist源码_Java 解析 IPA 文件,读取 Info.plist 信息-Go语言中文社区
- [leetcode-515-Find Largest Value in Each Tree Row]
- Opencms中要注意的地方
- Flowable学习笔记(一、入门)
- 线程:synchronized方法
- 哈工大计算机学院历史,历史沿革
- Java实现冒泡排序及逆序冒泡排序
- 听说阎王爷要做个生死簿后台管理系统,我们派去了一个程序员……
- Python的包管理工具
- Linux TTY 串口 struct termios结构体参数
- android studio代理设置
- python批量合并mp4视频
- IP 地址冲突检测程序源码(解决某种情况下检测无效的问题)
- arcgis绘核密度分布图
- MANIFEST.MF是个什么?
- STM32之中断的使用
- Java的方式生成条形码
- C++游戏服务器开发视频教程
热门文章
- 传智播客成都java培训中心的发展
- 「迁怒」也许不只是没忍住
- POJ 1511 Invitation Cards(最短路径,dijkstra 模板题)
- Python+Django+Mysql实现在线电影推荐系统 基于用户、项目的协同过滤推荐在线电影系统 代码实现 源代码下载
- python 字符串和数字组合变量名
- 计算机打印机提示无法打印,打印机无法打印_打印机无法打印怎么办【步骤|图文教程】-太平洋IT百科...
- STC单片机简单控制直流电机正反转
- 软件逆向工程学习(一)
- 实现isPrime()函数,参数为整数,要有异常处理。如果整数是质数,返回True,否则返回False
- 杭电ACM-LCY算法进阶培训班-专题训练(计算几何入门)