介绍
机关是在本游戏中除了技能外又一个重要的部分。解密是本游戏的设计初衷之一,所以机关可以说是游戏中很关键的部分,游戏开发到现在,技能方面已经比较成熟,接下来重要的就是机关方面。一些初步的机关完成后,即可设计地图。所以本篇博客,我会介绍部分机关的设计。
在设计中,我们的技能分为火、冰、雷、风4个元素,每种属性的元素有自己属性的特征,我们可以把这些属性与机关结合起来,相应的属性可以触发相应的机关,例如,地图中的火把可以靠火属性去触发,部分机关可以靠雷球去触发。
类图
目前想到的机关有火把、开关、一些可触发的地形等。这些机关要与技能结合起来,意味着在技能与机关碰撞的时候,要触发机关。
在技能中,我们攻击敌人使用OnTriggerEnter2D方法去判断碰撞体,我们仍然可以在这一方法中判断是否触发机关,所以可被攻击的怪物有CanBeFighted组件,同理,我们可以把这一设计应用于机关,让所有机关拥有一个类似的组件,我们把这个组件命名为CanBeFoughtMechanism(继承自CanBeFighted)。为满足面向对象设计原则,我们可以让所有的机关拥有一个固定的接口,在触发机关时,调用该接口即可,这样做可以方便扩展。
为此,我设计了机关的抽象类Mechanism和组件CanBeFoughtMechanism,抽象类中有Trigger方法,为触发机关时要调用的方法,这样做就实现了接口的统一。
部分机关的类图如下:
机关类的父类设计
机关类的父类首先要有Trigger方法,该方法保证了所有的机关拥有统一的触发接口。
触发机关的方式有很多,每一种机关都需要对应的方式去触发,在技能碰撞机关后,我们还要检测机关是否受到了正确的触发条件,为此,我增加了枚举类型TriggerType。
有些机关的触发条件可能是多种的,当几个条件都满足时才能出发,所以调用Trigger后还要判断是否满足所有的触发条件,为此,我又增加了TriggerDetect方法。
/**
* @Description: Mechanism类为所有可以触发的机关的父类,包含触发机关的方法
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Mechanism : MonoBehaviour
{
public enum TiggerType { Fire, Ice, Wind, Thunder, Switch, Other};
private Collider2D coll;
protected bool isTriggered = false;
// Start is called before the first frame update
protected virtual void Start()
{
coll = GetComponent<Collider2D>();
if (coll == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到collider");
}
}
/// <summary>
/// 触发机关
/// </summary>
public abstract void Trigger(TiggerType triggerType);
/// <summary>
/// 检测机关是否可以触发
/// </summary>
/// <returns>机关是否可以触发</returns>
protected abstract bool TriggerDetect();
/// <summary>
/// 机关是否被触发
/// </summary>
/// <returns></returns>
public virtual bool IsTriggered()
{
return isTriggered;
}
}
CanBeFoughtMechanism类设计
当技能触碰开关时,会根据技能的类型,调用Trigger方法。该类继承CanBeFighted,我们只需要更改BeAttacked方法即可。
/**
* @Description: CanBeFoughtMachanism类是机关被击类,继承CanBeFighted类,主要用于检测机关的触发条件
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CanBeFoughtMachanism : CanBeFighted
{
/// <summary>
/// 该机关要接收的元素
/// </summary>
private Mechanism mechanism;
private void Start()
{
mechanism = GetComponent<Mechanism>();
if (mechanism == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到Machanism组件");
}
}
/// <summary>
/// 判断攻击类型,并触发机关
/// </summary>
/// <param name="who"></param>
/// <param name="damage"></param>
/// <param name="interruptType"></param>
/// <param name="element"></param>
/// <returns></returns>
public override int BeAttacked(GameObject who, int damage, AttackInterruptType interruptType, ElementAbilityManager.Element element = ElementAbilityManager.Element.NULL)
{
if (element == ElementAbilityManager.Element.Fire)
{
mechanism.Trigger(Mechanism.TiggerType.Fire);
}
else if (element == ElementAbilityManager.Element.Ice)
{
mechanism.Trigger(Mechanism.TiggerType.Ice);
}
else if (element == ElementAbilityManager.Element.Wind)
{
mechanism.Trigger(Mechanism.TiggerType.Wind);
}
else if (element == ElementAbilityManager.Element.Thunder)
{
mechanism.Trigger(Mechanism.TiggerType.Thunder);
}
return 0;
}
}
火把机关设计
基本架构设计完成后,我设计了第一个机关——火把。当火元素技能触碰火把时,会点亮火把。火把物体会有一个点光源,当触发后,开启该点光源。
/**
* @Description: Torch是火把类,是机关的一种,被火属性攻击后会被点燃
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
public class Torch : Mechanism
{
private CanBeFoughtMachanism canBeFought;
private new Light2D light;
private bool isAttackedByFire = false;
protected override void Start()
{
base.Start();
canBeFought = GetComponent<CanBeFoughtMachanism>();
if (canBeFought == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到CanBeFoughtMachanism组件");
}
light = GetComponent<Light2D>();
if (light == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到Light组件");
}
//初始化灯光
light.enabled = false;
}
public override void Trigger(TiggerType triggerType)
{
//判断攻击类型是否为火
if (triggerType == Mechanism.TiggerType.Fire)
{
isAttackedByFire = true;
}
//检测触发条件
if (TriggerDetect())
{
light.enabled = true;
}
}
protected override bool TriggerDetect()
{
return isAttackedByFire;
}
}