Не удалось найти понятный скрипт двойного касания, который использует функцию ввода Unity. GetAxisRaw («Горизонтально»). Ниже приведено мое чудовищное решение для левой и правой горизонтальной оси, которое заняло у меня слишком много часов ... Это служит моей цели, хотя все еще позволяет игроку нажимать sh в направлении, противоположном направлению движения, если у него быстрые пальцы .
Если кто-нибудь может показать мне более чистое решение или у него есть какой-нибудь совет, он будет очень признателен? Предпочтительно решение, которое может быть легко реализовано и для другой оси. Если бы кто-нибудь знал о стандартной функции единства, которая могла бы обеспечить такое же поведение двойного нажатия, это было бы еще лучше.
Если вы прикрепите скрипт к кубу, вы увидите поведение двойного касания, которое я ищу. Прикрепленное изображение показывает сигнал logi c поведения двойного нажатия.
Logi c сигнал Double Tap
using System.Collections;
using UnityEngine;
public class DoubleTap : MonoBehaviour
{
float translationSpeedX = 20;
float translationSpeedY = 20;
Vector3 playerPosition;
float maxKeyDownTime = 0.2f;
float maxKeyUpTime = 0.2f;
float delayBetweenDoubleTaps = 0.4f;
bool doubleTapped = false;
bool firstLeftDown = false;
bool firstLeftUp = false;
bool prevLeftDown = false;
bool firstRightDown = false;
bool firstRightUp = false;
bool prevRightDown = false;
// Start is called before the first frame update
void Start()
{
playerPosition = transform.position;
StartCoroutine(KeyInputBuffer());
}
// Update is called once per frame
void Update()
{
//Take keyboard input and translate the player in X and Y directions
playerPosition.x += Input.GetAxis("Horizontal") * translationSpeedX * Time.deltaTime;
playerPosition.x = Mathf.Clamp(playerPosition.x, -100, 100);
playerPosition.y += Input.GetAxis("Vertical") * translationSpeedY * Time.deltaTime;
playerPosition.y = Mathf.Clamp(playerPosition.y, -100, 100);
transform.position = playerPosition;
//Double tap left
if (firstLeftUp && Input.GetAxisRaw("Horizontal") < 0)
{
Debug.Log("Double Tap Left!");
playerPosition.x -= 10f;
firstLeftDown = false;
firstLeftUp = false;
StartCoroutine(DoubleTapDelayTimer());
}
else if (!firstLeftUp && firstLeftDown && Input.GetAxisRaw("Horizontal") == 0)
{
Debug.Log("firstLeftUp Left!");
firstLeftUp = true;
StartCoroutine(KeyUpTimer());
}
else if (!doubleTapped && !firstLeftDown && !prevLeftDown && Input.GetAxisRaw("Horizontal") < 0)
{
Debug.Log("firstLeftDown Left!");
firstLeftDown = true;
StartCoroutine(KeyDownTimer());
}
//Double tap right
if (firstRightUp && Input.GetAxisRaw("Horizontal") > 0)
{
Debug.Log("Double Tap Right!");
playerPosition.x += 10f;
firstRightDown = false;
firstRightUp = false;
StartCoroutine(DoubleTapDelayTimer());
}
else if (!firstRightUp && firstRightDown && Input.GetAxisRaw("Horizontal") == 0)
{
Debug.Log("firstRightUp Right!");
firstRightUp = true;
StartCoroutine(KeyRightUpTimer());
}
else if (!doubleTapped && !firstRightDown && !prevRightDown && Input.GetAxisRaw("Horizontal") > 0)
{
Debug.Log("firstRightDown Right!");
firstRightDown = true;
StartCoroutine(KeyRightDownTimer());
}
}
//Timer which controlls the minimun time between double taps
IEnumerator DoubleTapDelayTimer()
{
doubleTapped = true;
yield return new WaitForSeconds(delayBetweenDoubleTaps);
doubleTapped = false;
}
//Timers for the left horizontal axis
IEnumerator KeyDownTimer()
{
yield return new WaitForSeconds(maxKeyDownTime);
firstLeftDown = false;
}
IEnumerator KeyUpTimer()
{
yield return new WaitForSeconds(maxKeyUpTime);
firstLeftUp = false;
}
//Timers for the right horizontal axis
IEnumerator KeyRightDownTimer()
{
yield return new WaitForSeconds(maxKeyDownTime);
firstRightDown = false;
}
IEnumerator KeyRightUpTimer()
{
yield return new WaitForSeconds(maxKeyUpTime);
firstRightUp = false;
}
//Store the raw input conditions for the horizontal axis as reference in next frame
IEnumerator KeyInputBuffer()
{
while(true)
{
yield return new WaitForEndOfFrame();
if (Input.GetAxisRaw("Horizontal") > 0)
{
prevLeftDown = false;
prevRightDown = true;
}
else if (Input.GetAxisRaw("Horizontal") < 0)
{
prevLeftDown = true;
prevRightDown = false;
}
else
{
prevLeftDown = false;
prevRightDown = false;
}
}
}}
Ниже приведено улучшение ( и отлаженный код), предложенный derHU GO. Я действительно поражен тем, сколько кода требуется для такой малой функциональности.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Axis
{
X,
Y
}
public enum AxisDirection
{
Right,
Left,
Up,
Down
}
public class DoubleTap : MonoBehaviour //StackOverFlow
{
// With [SerializeField] these are now configured directly via the Inspector
// in unity without having to recompile
// This way you can play with them in Playmode until you have the values the fit your needs
// For restring to the defaults simply hit Reset in the Context menu of the component
[SerializeField] private float translationSpeedX = 20;
[SerializeField] private float translationSpeedY = 20;
[SerializeField] private float maxKeyDownTime = 0.2f;
[SerializeField] private float maxKeyUpTime = 0.2f;
[SerializeField] private float delayBetweenDoubleTaps = 0.4f;
private Dictionary<Axis, string> axisName = new Dictionary<Axis, string>
{
{Axis.X, "Horizontal"},
{Axis.Y, "Vertical"}
};
private Dictionary<Axis, AxisDirection> axisPositive = new Dictionary<Axis, AxisDirection>
{
{Axis.X, AxisDirection.Right},
{Axis.Y, AxisDirection.Up}
};
private Dictionary<Axis, AxisDirection> axisNegative = new Dictionary<Axis, AxisDirection>
{
{Axis.X, AxisDirection.Left},
{Axis.Y, AxisDirection.Down}
};
private Vector3 playerPosition;
private bool doubleTapped = false;
private Dictionary<AxisDirection, bool> axisFirstDown = new Dictionary<AxisDirection, bool>();
private Dictionary<AxisDirection, bool> axisFirstUp = new Dictionary<AxisDirection, bool>();
private Dictionary<AxisDirection, bool> axisPrevDown = new Dictionary<AxisDirection, bool>();
private Dictionary<AxisDirection, Action> doubleTapActions = new Dictionary<AxisDirection, Action>(); //MOD
// Start is called before the first frame update
private void Start()
{
doubleTapActions.Add(AxisDirection.Left, LeftDoubleTapAction); //MOD
doubleTapActions.Add(AxisDirection.Right, RightDoubleTapAction);//MOD
doubleTapActions.Add(AxisDirection.Up, UpDoubleTapAction); //MOD
doubleTapActions.Add(AxisDirection.Down, DownDoubleTapAction); //MOD
foreach (var axis in (AxisDirection[])Enum.GetValues(typeof(AxisDirection)))
{
axisFirstDown.Add(axis, false);
axisFirstUp.Add(axis, false);
axisPrevDown.Add(axis, false);
}
playerPosition = transform.position;
StartCoroutine(KeyInputBuffer());
}
// Update is called once per frame
private void Update()
{
foreach (var axis in (Axis[])Enum.GetValues(typeof(Axis)))
{
// positive
if (axisFirstUp[axisPositive[axis]] && Input.GetAxisRaw(axisName[axis]) > 0) //MOD axisFirstUp || axisFirstDown
{
Debug.Log($"Double Tap {axisPositive[axis]}!");
doubleTapActions[axisPositive[axis]].Invoke(); //MOD
axisFirstDown[axisPositive[axis]] = false;
axisFirstUp[axisPositive[axis]] = false;
StartCoroutine(DoubleTapDelayTimer());
return;
}
else if (!axisFirstUp[axisPositive[axis]] && axisFirstDown[axisPositive[axis]] && Input.GetAxisRaw(axisName[axis]) == 0)
{
Debug.Log($"firstUp {axisPositive[axis]}!");
axisFirstUp[axisPositive[axis]] = true;
StartCoroutine(KeyUpTimer(axisPositive[axis])); //MOD axisPositive[axis]) || axis
}
else if (!doubleTapped && !axisFirstDown[axisPositive[axis]] && !axisPrevDown[axisPositive[axis]] && Input.GetAxisRaw(axisName[axis]) > 0)
{
Debug.Log($"firstDown {axisPositive[axis]}!");
axisFirstDown[axisPositive[axis]] = true;
StartCoroutine(KeyDownTimer(axisPositive[axis])); //MOD axisPositive[axis]) || axis
}
// negative
if (axisFirstUp[axisNegative[axis]] && Input.GetAxisRaw(axisName[axis]) < 0) //MOD axisFirstUp || axisFirstDown //MOD2 if || else if
{
Debug.Log($"Double Tap {axisNegative[axis]}!");
doubleTapActions[axisNegative[axis]].Invoke(); //MOD
axisFirstDown[axisNegative[axis]] = false;
axisFirstUp[axisNegative[axis]] = false;
StartCoroutine(DoubleTapDelayTimer());
return;
}
else if (!axisFirstUp[axisNegative[axis]] && axisFirstDown[axisNegative[axis]] && Input.GetAxisRaw(axisName[axis]) == 0)
{
Debug.Log($"firstUp {axisNegative[axis]}!");
axisFirstUp[axisNegative[axis]] = true;
StartCoroutine(KeyUpTimer(axisNegative[axis])); //MOD axisPositive[axis]) || axis
}
else if (!doubleTapped && !axisFirstDown[axisNegative[axis]] && !axisPrevDown[axisNegative[axis]] && Input.GetAxisRaw(axisName[axis]) < 0)
{
Debug.Log($"firstDown {axisNegative[axis]}!");
axisFirstDown[axisNegative[axis]] = true;
StartCoroutine(KeyDownTimer(axisNegative[axis])); //MOD axisPositive[axis]) || axis
}
}
// Do only process the input as movement if there was no double tap this frame
//Take keyboard input and translate the player in X and Y directions
playerPosition.x += Input.GetAxis("Horizontal") * translationSpeedX * Time.deltaTime; //MOD || UnityEgine.
playerPosition.x = Mathf.Clamp(playerPosition.x, -100, 100);
playerPosition.y += Input.GetAxis("Vertical") * translationSpeedY * Time.deltaTime; //MOD || UnityEgine.
playerPosition.y = Mathf.Clamp(playerPosition.y, -100, 100);
transform.position = playerPosition;
Debug.Log("update");
}
//Timer which controlls the minimun time between double taps
IEnumerator DoubleTapDelayTimer()
{
doubleTapped = true;
yield return new WaitForSeconds(delayBetweenDoubleTaps);
doubleTapped = false;
}
//Timers for the axis
IEnumerator KeyDownTimer(AxisDirection axis)
{
yield return new WaitForSeconds(maxKeyDownTime);
axisFirstDown[axis] = false;
}
IEnumerator KeyUpTimer(AxisDirection axis)
{
yield return new WaitForSeconds(maxKeyUpTime);
axisFirstUp[axis] = false;
}
//Store the raw input conditions for the horizontal axis as reference in next frame
IEnumerator KeyInputBuffer()
{
while (true)
{
Debug.Log("coroutine");
yield return new WaitForEndOfFrame();
foreach (var axis in (Axis[])Enum.GetValues(typeof(Axis)))
{
axisPrevDown[axisPositive[axis]] = false;
axisPrevDown[axisNegative[axis]] = false;
if (Input.GetAxisRaw(axisName[axis]) > 0) //MOD || UnityEgine.
{
axisPrevDown[axisPositive[axis]] = true;
}
else if (Input.GetAxisRaw(axisName[axis]) < 0) //MOD || UnityEgine.
{
axisPrevDown[axisNegative[axis]] = true;
}
}
}
}
//Double tap actions
private void LeftDoubleTapAction()
{
playerPosition.x -= 10f;
}
private void RightDoubleTapAction()
{
playerPosition.x += 10f;
}
private void UpDoubleTapAction()
{
playerPosition.y += 10f;
}
private void DownDoubleTapAction()
{
playerPosition.y -= 10f;
}
}