提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、制作敌人另个爬虫Crawler
- 1.公式化导入制作另个爬虫Crawler素材
- 2.制作另个爬虫Crawler的Crawler.cs状态机
- 3.制作敌人另个爬虫Crawler的playmaker状态机
- 二、制作敌人飞虫Fly
- 1.公式化导入制作飞虫Fly素材
- 2.制作敌人飞虫Fly的playmaker状态机
- 总结
前言
如标题所示,最近感觉有些没活了,或者说是趁热打铁再制作更多的敌人,于是本期的主角就决定是两个大家刚进入空洞骑士就经常看到的敌人另一个爬虫Crawler和飞虫Fly。
一、制作敌人另一个爬虫Crawler
1.公式化导入制作另个爬虫Crawler素材
首先我们先完成Crawler的完整行为,第一步导入素材,分别为它制作tk2dspritecollection和tk2dspriteanimation,
然后就到了公式化设置一个敌人的时候了Rb2d , audiosource, boxcollider2d:
可以看到它不需要其它的子物体,因为只需要执行行走,死亡,转向的状态。
2.制作另一个爬虫Crawler的Crawler.cs状态机
创建同名函数给该游戏对象
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Crawler : MonoBehaviour
{
public float speed;
[Space]
private Transform wallCheck; //墙面检测的位置
private Transform groundCheck; //地面检测的位置
private Vector2 velocity; //记录速度
private CrawlerType type;
private Rigidbody2D body;
private tk2dSpriteAnimator anim;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
anim = GetComponent<tk2dSpriteAnimator>();
}
private void Start()
{
float z = transform.eulerAngles.z;
//通过transform.eulerAngles.z来判断哪种类型的Crawler
if (z >= 45f && z <= 135f)
{
type = CrawlerType.Wall;
velocity = new Vector2(0f, Mathf.Sign(-transform.localScale.x) * speed);
}
else if (z >= 135f && z <= 225f)
{
type = ((transform.localScale.y > 0f) ? CrawlerType.Roof : CrawlerType.Floor);
velocity = new Vector2(Mathf.Sign(transform.localScale.x) * speed, 0f);
}
else if (z >= 225f && z <= 315f)
{
type = CrawlerType.Wall;
velocity = new Vector2(0f, Mathf.Sign(transform.localScale.x) * speed);
}
else
{
type = ((transform.localScale.y > 0f) ? CrawlerType.Floor : CrawlerType.Roof);
velocity = new Vector2(Mathf.Sign(-transform.localScale.x) * speed, 0f);
}
//TODO:
CrawlerType crawlerType = type;
if(crawlerType != CrawlerType.Floor)
{
if(crawlerType - CrawlerType.Roof <= 1)
{
body.gravityScale = 0;//如果在墙面面上rb2d的重力就设置为1
}
}
else
{
body.gravityScale = 1; //如果在地面上rb2d的重力就设置为1
//TODO:
}
StartCoroutine(Walk());
}
/// <summary>
/// 使用协程实现Walk函数,循环直至hit=true后挂起然后启用协程Turn()
/// </summary>
/// <returns></returns>
private IEnumerator Walk()
{
for(; ; )
{
anim.Play("Walk");
body.velocity = velocity;
bool hit = false;
while (!hit)
{
if(CheckRayLocal(wallCheck.localPosition,transform.localScale.x > 0f ? Vector2.left : Vector2.right, 1f))
{
hit = true;
break;
}
if (!CheckRayLocal(groundCheck.localPosition, transform.localScale.y > 0f ? Vector2.down : Vector2.up, 1f))
{
hit = true;
break;
}
yield return null;
}
yield return StartCoroutine(Turn());
yield return null;
}
}
/// <summary>
/// 使用协程实现转向函数
/// </summary>
/// <returns></returns>
private IEnumerator Turn()
{
body.velocity = Vector2.zero;
yield return StartCoroutine(anim.PlayAnimWait("Turn"));
transform.SetScaleX(transform.localScale.x * -1f);
velocity.x = velocity.x * -1f;
velocity.y = velocity.y * -1f;
}
/// <summary>
/// 发射射线,检测是否有LayerMask.GetMask("Terrain").collider
/// </summary>
/// <param name="originLocal"></param>
/// <param name="directionLocal"></param>
/// <param name="length"></param>
/// <returns></returns>
public bool CheckRayLocal(Vector3 originLocal, Vector2 directionLocal, float length)
{
Vector2 vector = transform.TransformPoint(originLocal);
Vector2 vector2 = transform.TransformDirection(directionLocal);
RaycastHit2D raycastHit2D = Physics2D.Raycast(vector, vector2, length, LayerMask.GetMask("Terrain"));
Debug.DrawLine(vector, vector + vector2 * length);
return raycastHit2D.collider != null;
}
private enum CrawlerType
{
Floor,
Roof,
Wall
}
}
回到Unity编辑器中,如果你的是开始往左走的话,记得设置speed为负数
只需要这个就行了。我们不需要挂载Lineofsightdetector.cs,这个就是敌人发现敌人到自己攻击范围的脚本
3.制作敌人另个爬虫Crawler的playmaker状态机
创建一个名字叫Crawler的playmaker状态机:
变量和事件如下所示: