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相关推荐

  1. Unity2D学习笔记Day9:添加敌人——受伤效果及反弹效果(补8.16)

    学习资源:B站 M_Studio<Unity教程2D入门>14 Unity Assets:Sunnyland Day9 受伤并反弹 预期效果:若在地面上碰到敌人,会触发受伤动画并反弹. p ...

  2. ROS学习笔记九:用C++编写ROS发布与订阅

    ROS学习笔记九:用C++编写ROS发布与订阅 本节主要介绍如何用C++编写一个简单的ROS发布与订阅. 编写发布节点 在之前创建的例子beginner_tutorials软件包中,在其目录下的src ...

  3. ROS2_Foxy学习10——多机激光SLAM准备篇

    ROS2_Foxy学习10--多机激光SLAM准备篇 1 安装Ubuntu20.04 mate 2 安装ROS noetic 3 安装cartographer 4 详细配置cartographer 5 ...

  4. 小白的奇幻数学课堂(part2)--敌人的敌人就是朋友,这其实就是负负得正法则

    学习笔记 学习书目:<x的奇幻之旅>–史蒂夫•斯托加茨 敌人的敌人就是朋友 绕开负数 减法运算其实给我们制造了一些加法运算中不会出现的复杂问题:减法会产生负数.减法的出现,使得人类不得不扩 ...

  5. ROS 创建msg和srv 编写发布者和订阅者节点 编写服务端和客户端节点(python版本)

    ROS 创建msg和srv 编写发布者和订阅者节点 编写服务端和客户端节点-python版本 rosed msg和srv 创建msg 使用rosmsg 创建srv 使用rossrv 重新make一下软 ...

  6. ROS学习笔记十:用C++编写一个简单的服务和客户端

    ROS学习笔记十:用C++编写一个简单的服务和客户端 这一节主要介绍如何使用C++编写一个简单的服务和客户端节点. 编写服务节点 由于在前面的练习中,已经向beginner_tutorials软件包中 ...

  7. unity2D学习笔记-角色动画

    unity2D学习笔记-角色动画 角色移动 动画效果(重点!!!!!) 创建:Animator与Animation 状态转换 跳跃 从fall到idle Hierarchy中创建一个Sprite作为载 ...

  8. 2021-08-09-ROS学习-消息创建,发布者和订阅者实现及测试

    2.ROS中创建msg 在软件包里定义一个新的消息 $ roscd beginner_tutorials $ mkdir msg $ echo "int64 num" > m ...

  9. 深度学习-10:人工智能简史及三剑客

    深度学习-10:人工智能简史及三剑客 深度学习原理与实践(开源图书)-总目录 1 人工智能简史 深度学习理论的突破和深度学习硬件加速能力的突破,使AI在模式识别.无人驾驶.智力游戏领域取得空前的成功. ...

最新文章

  1. 数学建模之图像处理---颜色建模
  2. .net2.0下数据库连接字符串的使用
  3. java读取 info.plist源码_Java 解析 IPA 文件,读取 Info.plist 信息-Go语言中文社区
  4. [leetcode-515-Find Largest Value in Each Tree Row]
  5. Opencms中要注意的地方
  6. Flowable学习笔记(一、入门)
  7. 线程:synchronized方法
  8. 哈工大计算机学院历史,历史沿革
  9. Java实现冒泡排序及逆序冒泡排序
  10. 听说阎王爷要做个生死簿后台管理系统,我们派去了一个程序员……
  11. Python的包管理工具
  12. Linux TTY 串口 struct termios结构体参数
  13. android studio代理设置
  14. python批量合并mp4视频
  15. IP 地址冲突检测程序源码(解决某种情况下检测无效的问题)
  16. arcgis绘核密度分布图
  17. MANIFEST.MF是个什么?
  18. STM32之中断的使用
  19. Java的方式生成条形码
  20. C++游戏服务器开发视频教程

热门文章

  1. 传智播客成都java培训中心的发展
  2. 「迁怒」也许不只是没忍住
  3. POJ 1511 Invitation Cards(最短路径,dijkstra 模板题)
  4. Python+Django+Mysql实现在线电影推荐系统 基于用户、项目的协同过滤推荐在线电影系统 代码实现 源代码下载
  5. python 字符串和数字组合变量名
  6. 计算机打印机提示无法打印,打印机无法打印_打印机无法打印怎么办【步骤|图文教程】-太平洋IT百科...
  7. STC单片机简单控制直流电机正反转
  8. 软件逆向工程学习(一)
  9. 实现isPrime()函数,参数为整数,要有异常处理。如果整数是质数,返回True,否则返回False
  10. 杭电ACM-LCY算法进阶培训班-专题训练(计算几何入门)