介绍
在上一篇博文中,我们介绍了2款地形机关。在本篇文章中,我们继续介绍另外2中机型机关——计数机关和旋转机关。这两种机关与玩家的跳跃有关,所以,在介绍机关之前,我们需要先引入事件管理器。
事件管理器
介绍
在unity中,我们可能会遇到需要调用其他物体组件的方法的时候,我们通常的做法是使用GetComponent方法获取组件,之后再调用其中的某个方法。但是,如果一个事件触发,要调用好多个组件的方法,再用这样的方法去调用,就会非常麻烦。以本游戏为例,计数机关和旋转机关和玩家的跳跃数有关,每当玩家跳跃一次,就要调用所有该类机关的方法,这会显示非常麻烦。
一种好的方法是使用事件管理器,以本游戏为例,我们可以把玩家跳跃看成一种事件,把所有与该事件有关的对象/方法保存在一个容器中,即注册事件。当玩家跳跃时,通知事件管理器触发事件,就会调用之前注册过的方法。
类设计
根据描述,我们需要一个容器保存注册的对象/方法,这些方法对应同一个事件,所以应用字典去保存。
关于方法,根据以上的描述,我们可以得到添加事件和注册事件2个方法。
代码
/**
* @Description: EventManager类是事件管理器类,用于事件的注册与触发管理
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class EventManager : MonoBehaviour
{
/// <summary>
/// 存储事件
/// </summary>
private Dictionary<string, Func<object[], object>> events
= new Dictionary<string, Func<object[], object>>();
/// <summary>
/// 跳跃状态改变
/// </summary>
public const string OnJumpNumChange = "OnJumpNumChange";
/// <summary>
/// 添加事件
/// </summary>
/// <param name="eventName">时间名</param>
/// <param name="action">方法</param>
public void AddEvent(string eventName, Func<object[], object> action)
{
if (events.ContainsKey(eventName))
{
events[eventName] += action;
}
else
{
events.Add(eventName, action);
}
}
/// <summary>
/// 触发事件
/// </summary>
/// <param name="eventName">事件名</param>
/// <param name="o"></param>
/// <returns></returns>
public object TriggerEvent(string eventName, object[] o)
{
if (events.ContainsKey(eventName))
{
return events[eventName](o);
}
else
{
return null;
}
}
}
``
计数出现地形机关
介绍
在游戏中,玩家可能会遇到需要连续跳跃上升的地形,我们引入计数机关,当跳跃次数为奇数次时,地形出现,为偶数次时,地形消失;或者跳跃次数为偶数次时,地形消失,为奇数次时,地形出现。这就需要用到事件管理器,每当玩家跳跃时,通知该机关改变消失/消失状态。
代码
/**
* @Description: CounterPlatform类为跳跃计数地板机关类,根据人物的跳跃次数决定是否出现
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CounterPlatform : Mechanism
{
[Header("跳跃参数")]
/// <summary>
/// 出现时,跳跃次数的奇偶
/// </summary>
public int appearNum = 1;
private Vector3 scale = new Vector3(1, 1, 1);
private EventManager eventManager;
protected override void Start()
{
base.Start();
//初始化scale
scale = transform.localScale;
//初始化事件管理器
eventManager = GameObject.Find("EventManager").GetComponent<EventManager>();
if (eventManager == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到EventManager");
}
//添加事件监听
eventManager.AddEvent(EventManager.OnJumpNumChange, (object[] o)=>{
ChangeState((int)o[0]);
return null;
});
//初始化状态(奇数显示,偶数消失)
ChangeState(1);
}
/// <summary>
/// 此机关中不用
/// </summary>
/// <returns></returns>
protected override bool TriggerDetect()
{
return true;
}
/// <summary>
/// 此机关中不用
/// </summary>
/// <param name="triggerType"></param>
public override void Trigger(TiggerType triggerType)
{
}
/// <summary>
/// 根据跳跃次数改变状态(出现或消失)
/// </summary>
/// <param name="jumpNum"></param>
public void ChangeState(int jumpNum)
{
if (jumpNum == appearNum)
{
transform.localScale = scale;
}
else
{
transform.localScale = Vector3.zero;
}
}
}
计数旋转机关
介绍
与上一种机关类似,我们希望有一种地形,当玩家跳跃次数为奇数次时,为一个角度;为偶数次时,旋转至另一个角度。同样,该机关也需要添加事件至事件管理器,当玩家跳跃时,需要通知该机关改变自己的旋转状态。
代码
/**
* @Description: CounterRotationPlatform类事计数旋转平台类,会根据跳跃次数改变角度
* 奇数改变为angle1,偶数改变为angle2
* @Author: CuteRed
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CounterRotationPlatform : Mechanism
{
[Header("跳跃参数")]
/// <summary>
/// 跳跃次数的奇偶
/// </summary>
private int jumpNum = 0;
[Header("角度参数")]
public float angle1 = 0.0f;
public float angle2 = 0.0f;
private Vector3 rotationAngle = Vector3.zero;
private EventManager eventManager;
protected override void Start()
{
base.Start();
//初始化事件管理器
eventManager = GameObject.Find("EventManager").GetComponent<EventManager>();
if (eventManager == null)
{
Debug.LogError("在" + gameObject.name + "中,找不到EventManager");
}
//添加事件监听
eventManager.AddEvent(EventManager.OnJumpNumChange, (object[] o) => {
jumpNum = (int)o[0];
Trigger(TiggerType.Other);
return null;
});
//初始化状态(改变角度)
rotationAngle.z = angle1;
transform.rotation = Quaternion.Euler(rotationAngle);
}
/// <summary>
/// 此机关中不用
/// </summary>
/// <returns></returns>
protected override bool TriggerDetect()
{
return true;
}
/// <summary>
/// 触发机关,根据跳跃次数改变角度
/// </summary>
/// <param name="triggerType"></param>
public override void Trigger(TiggerType triggerType)
{
//跳跃次数为奇数
if (jumpNum == 1)
{
rotationAngle.z = angle1;
}
//跳跃次数为偶数
else if (jumpNum == 2)
{
rotationAngle.z = angle2;
}
//改变角度
transform.rotation = Quaternion.Euler(rotationAngle);
}
}