介绍
本篇博文,我们介绍2种新的机关——冰锥。根据设计,冰锥有大冰锥和小冰锥2种,下面我们来依次介绍。
小冰锥
在冰属性地图中,在地图上方会生成若干冰锥,当玩家进入一定区域后,冰锥会落下,对玩家造成伤害。一定时间后,冰锥会重新生成。
为满足小冰锥的功能,我们还需要一个冰锥管理器。因为冰锥掉落后会在一定时间后重新生成,所以我们需要一个管理器来控制冰锥的生成。那么冰锥管理器有2个主要方法,一个是让冰锥掉落(可以写在update中),一个是让冰锥重新生成。小冰锥仍然需要对象池去生成。
冰锥管理器代码
/**
* @Description: SmallIceConeManager为小冰锥管理器,在一定范围内随机生成小冰锥
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmallIceConeManager : Mechanism
{
[Header("生成参数")]
public int generateNumber = 3;
private int flowNum = 0;
private Vector2 generatePosition = new Vector2(0, 0);
[Header("时间参数")]
public float flowIntervalTime = 1.0f;
private float passTime = 0.0f;
private Collider2D coll;
private SmallIceCone[] cones;
private PoolManager poolManager;
protected override void Start()
{
base.Start();
poolManager = GameObject.Find("PoolManager").GetComponent<PoolManager>();
if (poolManager == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到PoolManager");
}
coll = GetComponent<Collider2D>();
if (coll == null)
{
Debug.LogError("在" + gameObject.name + "中,获取collider失败");
}
cones = new SmallIceCone[generateNumber];
//生成冰锥
GenerateIceCone();
enabled = false;
}
// Update is called once per frame
void Update()
{
//计时
passTime += Time.deltaTime;
if (passTime > flowIntervalTime)
{
cones[flowNum].Trigger(TiggerType.Other);
flowNum++;
passTime = 0.0f;
}
//检测是否冰锥都掉落
if (flowNum == generateNumber)
{
//掉落数置为0
flowNum = 0;
//cones.Clear();
//生成新冰锥
GenerateIceCone();
enabled = false;
isTriggered = false;
}
}
public override void Trigger(TiggerType triggerType)
{
if (TriggerDetect())
{
isTriggered = true;
enabled = true;
}
}
protected override bool TriggerDetect()
{
return !isTriggered;
}
/// <summary>
/// 在指定范围内随机生成冰锥
/// </summary>
private void GenerateIceCone()
{
for (int i = 0; i < generateNumber; i++)
{
Debug.Log(i);
GameObject cone = poolManager.GetGameObject(SmallIceCone.SMALL_ICE_CONE);
SmallIceCone a = cone.GetComponent<SmallIceCone>();
//随机生成位置
float x = Random.Range(coll.bounds.min.x, coll.bounds.max.x);
float y = Random.Range(coll.bounds.min.y, coll.bounds.max.y);
generatePosition.x = x;
generatePosition.y = y;
a.SetPosition(generatePosition);
//加入列表
cones[i] = a;
}
}
}
小冰锥设计
关于小冰锥,它有下落和生成2种方法。小冰锥掉落在地面上时,会消失,为了模拟消失,我们可以让它变为透明的。一定时间后,会重新生成,这里可以使用协程。
/**
* @Description: SmallIceCone为小冰锥,由冰锥管理器管理,掉落地面后消失
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmallIceCone : Mechanism
{
public const string SMALL_ICE_CONE = "SmallIceCone";
private Collider2D coll;
private CanFight canFight;
private SpriteRenderer spriteRenderer;
[Header("颜色参数")]
private Color originalColor;
private Color transparentColor;
[Header("运动参数")]
public float originalFlowSpeed = 3.0f;
private float speed;
private Vector3 direction = Vector3.down;
private Vector3 startPosition;
[Header("伤害参数")]
public int damage = 2;
private List<LayerMask> layers = new List<LayerMask>();
[Header("时间参数")]
public float generateTime = 2.0f;
private LayerMask ground;
protected override void Start()
{
base.Start();
speed = originalFlowSpeed;
startPosition = transform.position;
ground = LayerMask.GetMask("Platform");
spriteRenderer = GetComponent<SpriteRenderer>();
if (spriteRenderer == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到spriteRenderer");
}
//颜色初始化
originalColor = spriteRenderer.color;
transparentColor = spriteRenderer.color;
transparentColor.a = 0.0f;
//碰撞体初始化
coll = GetComponent<Collider2D>();
if (coll == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到collider");
}
//初始化目标层级
layers.Add(LayerMask.NameToLayer("Player"));
layers.Add(LayerMask.NameToLayer("Enemy"));
//初始化canFight
canFight = GetComponent<CanFight>();
if (canFight == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到canFight");
}
string[] targetLayer = new string[2];
targetLayer[0] = "Player";
targetLayer[1] = "Enemy";
canFight.Initiailize(targetLayer);
enabled = false;
}
private void Update()
{
//下落
transform.position += direction * speed * Time.deltaTime;
speed += 1.0f;
//检测碰到地图
RaycastHit2D hit;
hit = Physics2D.Raycast(transform.position, direction, 0.2f, ground);
if (hit && speed > 0.0f)
{
//消失
spriteRenderer.color = transparentColor;
//速度置为0
speed = 0.0f;
StartCoroutine(nameof(FlowToFloor));
}
}
/// <summary>
/// 设置生成位置
/// </summary>
/// <param name="startPosition">生成位置</param>
public void SetPosition(Vector2 startPosition)
{
transform.position = startPosition;
}
public override void Trigger(TiggerType triggerType)
{
if (TriggerDetect())
{
//触发
isTriggered = true;
//恢复速度
speed = originalFlowSpeed;
//开启脚本
enabled = true;
}
}
protected override bool TriggerDetect()
{
return !isTriggered;
}
/// <summary>
/// 落到地板上,被对象池收回
/// </summary>
private IEnumerator FlowToFloor()
{
yield return new WaitForSeconds(generateTime);
//消失
//gameObject.SetActive(false);
//等待重新生成
Generate();
}
private void OnTriggerEnter2D(Collider2D collision)
{
//层级检测
if (speed > 0 && layers.Contains(collision.gameObject.layer))
{
//检测是否可以被攻击
CanBeFighted beFought;
if (collision.TryGetComponent<CanBeFighted>(out beFought))
{
canFight.Attack(beFought, damage);
Debug.Log(gameObject.name + "攻击到了" + beFought.gameObject.name);
}
}
}
/// <summary>
/// 重新生成
/// </summary>
/// <returns></returns>
private void Generate()
{
enabled = false;
transform.position = startPosition;
//恢复颜色
spriteRenderer.color = originalColor;
//gameObject.SetActive(true);
isTriggered = false;
}
}
效果
大冰锥
大冰锥与小冰锥的不同为,大冰锥掉落后不会消失,而是会变成一种地形,玩家可以踩在上面。而且大冰锥掉落后不可重新生成。
那么大冰锥有2个方法,掉落(可以写在update种)和变为地形,造成伤害的代码可以写在OnTriggerEnter2D中。
代码
/**
* @Description: LargeIceCone为大冰锥类,掉落会变成地形,碰到敌人或玩家会造成伤害
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LargeIceCone : Mechanism
{
private Collider2D coll;
private CanFight canFight;
[Header("运动参数")]
public float flowSpeed = 3.0f;
private Vector3 direction = Vector3.down;
[Header("伤害参数")]
public int damage = 2;
private List<LayerMask> layers = new List<LayerMask>();
private LayerMask ground;
protected override void Start()
{
base.Start();
ground = LayerMask.GetMask("Platform");
coll = GetComponent<Collider2D>();
if (coll == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到collider");
}
//初始化目标层级
layers.Add(LayerMask.NameToLayer("Player"));
layers.Add(LayerMask.NameToLayer("Enemy"));
//初始化canFight
canFight = GetComponent<CanFight>();
if (canFight == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到canFight");
}
string[] targetLayer = new string[2];
targetLayer[0] = "Player";
targetLayer[1] = "Enemy";
canFight.Initiailize(targetLayer);
enabled = false;
}
private void Update()
{
//下落
transform.position += direction * flowSpeed * Time.deltaTime;
flowSpeed += 1.0f;
//检测碰到地图
RaycastHit2D hit;
hit = Physics2D.Raycast(transform.position, direction, 1.0f, ground);
if (hit)
{
StartCoroutine(nameof(FlowToFloor));
flowSpeed = 0.0f;
}
}
public override void Trigger(TiggerType triggerType)
{
if (TriggerDetect())
{
//触发
isTriggered = true;
//开启脚本
enabled = true;
}
}
protected override bool TriggerDetect()
{
return !isTriggered;
}
/// <summary>
/// 落到地板上
/// </summary>
private IEnumerator FlowToFloor()
{
yield return new WaitForSeconds(2.0f);
gameObject.layer = LayerMask.NameToLayer("Platform");
coll.isTrigger = false;
}
private void OnTriggerEnter2D(Collider2D collision)
{
//层级检测
if (flowSpeed > 0 && layers.Contains(collision.gameObject.layer))
{
//检测是否可以被攻击
CanBeFighted beFought;
if (collision.TryGetComponent<CanBeFighted>(out beFought))
{
canFight.Attack(beFought, damage);
beFought.BeatBack(transform, 1.0f, 10.0f);
Debug.Log(gameObject.name + "攻击到了" + beFought.gameObject.name);
}
}
}
}