今天给各位带来的是游戏中一种常见的交互玩法---------QTE玩法。首先给大家解释一些什么是QTE呢?玩过PS游戏的都知道,里面有许多的QTE事件,手游上面不能说是没有,只是比较少。QTE是Quick Time Event(快速反应事件)的缩写。要求玩家要对游戏画面上出现的按键迅速作出反应,并按下与画面所对应的按键,其出现的按键有单个的按键也有组合按键。这就是QTE玩法了。那么如何在我们的unity中实现我们的QTE效果呢?
废话不多说,直接看代码吧!
不过前提是大家需要拼接好指针这样的QTE的UI界面哦,毕竟是一个2D的界面。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestQTE : MonoBehaviour
{
private void Awake()
{
_Init();
}
private void Start()
{
//调用示范
OpenQteView(KeyCode.O, () => PressQTE(), 50, () =>
{
Debug.Log("未及时按下键QTE按键失败");
}, () =>
{
Debug.Log("QTE按键成功");
});
}
/// <summary>
/// QTE按键的类型
/// </summary>
enum E_QTEKey
{
Triangle = 0,
Circle = 1,
Squre = 2,
Cross = 3
}
WildQTEBtn[] wildQteBtns;
Dictionary<KeyCode, int> btnMap;
KeyCode key;
protected void _Init()
{
//初始化不同类型的按键对应的形状的按钮
wildQteBtns = new WildQTEBtn[] {
new WildQTEBtn(KeyCode.Q, transform.Find("Btn01")),
new WildQTEBtn(KeyCode.T, transform.Find("Btn02")),
new WildQTEBtn(KeyCode.O, transform.Find("Btn03")),
new WildQTEBtn(KeyCode.K, transform.Find("Btn04"))
};
btnMap = new Dictionary<KeyCode, int>();
btnMap.Add(KeyCode.Q, (int)E_QTEKey.Triangle);
btnMap.Add(KeyCode.T, (int)E_QTEKey.Circle);
btnMap.Add(KeyCode.O, (int)E_QTEKey.Squre);
btnMap.Add(KeyCode.K, (int)E_QTEKey.Cross);
}
/// <summary>
/// 打开QTE视图
/// </summary>
/// <param name="key">绑定的键名</param>
/// <param name="BindKeyCommand">绑定的键要执行的事情</param>
/// <param name="areaAngle">qQTE区域触发的角度</param>
/// <param name="failCallback">失败的回调</param>
/// <param name="successCallBack">成功的回调</param>
public void OpenQteView(KeyCode key, Action BindKeyCommand, int areaAngle, Action failCallback, Action successCallBack)
{
this.key = key;
if (btnMap.ContainsKey(key))
{
WildQTEBtn qteBtn = wildQteBtns[btnMap[key]];
qteBtn.BindKeyUpExcuteCommand(BindKeyCommand);
qteBtn.angle = 0;
qteBtn.isRotation = true;
qteBtn.Open(areaAngle, () =>
{
qteBtn.angle = 0;
failCallback?.Invoke();
}, () =>
{
if (null != successCallBack)
successCallBack();
});
Open();
}
else
{
Debug.LogError("QteView Error ");
}
}
public void PressQTE()
{
WildQTEBtn qteBtn = wildQteBtns[btnMap[key]];
qteBtn.IsPerss = true;
}
private void Open()
{
}
private void Close()
{
if (btnMap.ContainsKey(key))
{
WildQTEBtn qteBtn = wildQteBtns[btnMap[key]];
qteBtn.Close();
}
}
class WildQTEBtn
{
public bool IsShown { get; set; }
public bool isRotation = true;
public bool IsPerss = false;
/// <summary>
/// 绑定的事件触发键
/// </summary>
private KeyCode _Key;
/// <summary>
/// QTE失败回调
/// </summary>
private Action TimeOver;
/// <summary>
/// QTE成功回调
/// </summary>
private Action SucceedCallback;
/// <summary>
/// QTE绑定执行事件
/// </summary>
private Action BindKeyCommand;
private GameObject _Obj;
/// <summary>
/// 指针
/// </summary>
private GameObject pointer;
/// <summary>
/// 中心点
/// </summary>
private GameObject centerPoint;
/// <summary>
/// 可触发的区域位置
/// </summary>
private GameObject area;
/// <summary>
/// 限定QTE左右边角度范围
/// </summary>
private int leftangle = 16;
private int rightangle = -14;
/// <summary>
/// 角度值
/// </summary>
public int angle = 0;
private int areaAngle;
/// <summary>
/// 指针旋转速度
/// </summary>
private int speed = 250;
/// <summary>
/// 初始化组件
/// </summary>
/// <param name="key"></param>
/// <param name="root"></param>
public WildQTEBtn(KeyCode key, Transform root)
{
_Key = key;
_Obj = root.gameObject;
pointer = _Obj.transform.Find("pointer").gameObject;
centerPoint = _Obj.transform.Find("centerdot").gameObject;
area = _Obj.transform.Find("area").gameObject;
Close();
}
/// <summary>
/// 绑定QTE事件
/// </summary>
/// <param name="BindKeyCommand"></param>
public void BindKeyUpExcuteCommand(Action BindKeyCommand)
{
this.BindKeyCommand = BindKeyCommand;
}
/// <summary>
/// 执行QTE事件
/// </summary>
public void ExcuteCommand()
{
if (Input.GetKeyUp(_Key))
{
BindKeyCommand?.Invoke();
}
}
/// <summary>
/// 打开QTE面板
/// </summary>
/// <param name="areaAngle"></param>
/// <param name="failCallback"></param>
/// <param name="succeedCallback"></param>
public void Open(int areaAngle, Action failCallback, Action succeedCallback)
{
this.areaAngle = areaAngle;
area.transform.RotateAround(centerPoint.transform.position, Vector3.forward, areaAngle);
angle = 0;
TimeOver = failCallback;
SucceedCallback = succeedCallback;
_Obj.SetActive(true);
IsShown = true;
}
/// <summary>
/// 关闭QTE面板
/// </summary>
public void Close()
{
area.transform.RotateAround(centerPoint.transform.position, Vector3.forward, -areaAngle);
TimeOver = null;
SucceedCallback = null;
_Obj.SetActive(false);
IsShown = false;
}
/// <summary>
/// 每帧QTE事件检测判断
/// </summary>
public void OnTick()
{
if (isRotation)
{
if (angle <= (360 / (speed * Time.deltaTime)))
{
angle += 1;
pointer.transform.RotateAround(centerPoint.transform.position, Vector3.forward, -speed * Time.deltaTime);
}
else
{
if (TimeOver != null)
{
TimeOver();
}
}
}
if (IsPerss)
{
isRotation = false;
IsPerss = false;
if (areaAngle < 0)
{
if (this.pointer.transform.localEulerAngles.z > (areaAngle + rightangle + 360) && this.pointer.transform.localEulerAngles.z < (areaAngle + leftangle + 360))
{
if (SucceedCallback != null)
{
Debug.Log("按键成功");
SucceedCallback();
}
}
else
{
isRotation = true;
Debug.Log("按键失败!");
if (TimeOver != null)
{
TimeOver();
}
}
}
else
{
if (this.pointer.transform.localEulerAngles.z > (areaAngle + rightangle) && this.pointer.transform.localEulerAngles.z < (areaAngle + leftangle))
{
if (SucceedCallback != null)
{
Debug.Log("按键成功!");
SucceedCallback();
}
}
else
{
isRotation = true;
Debug.Log("按键失败!");
if (TimeOver != null)
{
TimeOver();
}
}
}
}
}
}
private void FixedUpdate()
{
WildQTEBtn qteBtn = wildQteBtns[btnMap[key]];
if (qteBtn != null)
{
qteBtn.ExcuteCommand();
}
if (wildQteBtns != null)
{
for (int i = 0; i < wildQteBtns.Length; ++i)
{
if (wildQteBtns[i].IsShown)
{
wildQteBtns[i].OnTick();
}
}
}
}
}
好了 以上就是关于QTE部分的实现过程源码啦!不足之处多多指出,高手请绕道!