我是一个统一的初学者,虽然我没有太多的编码经验,但我知道我的代码一团糟。
所以,事情是这样的:当我点击鼠标(0)时,我插入了一个特定的功能,允许播放器从它的位置到"Object1“。在单击时,一个时间计数器启动,在2秒内,如果我再次单击de鼠标(0),它将将播放机升级到第二次,现在是"Object2“。我应用这个逻辑的一种方式,允许用户4次4次在4个不同的位置,如果每个输入是在5秒以下的球员。
经过大量的努力,我找到了一种让它工作的方法,它是功能性的,但代价是许多布尔人和ifs语句,一个完整而可怕的Spaguetti。所以我的问题是,我怎样才能把这整件事弄得更干净、更有效率?在这种情况下,我可以使用什么代码结构来提高整个程序的可读性,并切断大量的布尔和条件词?提前谢谢大家!
下面是代码:
[SerializeField] private Transform cube1;
[SerializeField] private Transform cube2;
[SerializeField] private Transform cube3;
[SerializeField] private Transform cube4;
private float timer;
private bool canCount;
private bool click1;
private bool click2;
private bool click3;
private bool click4;
private bool lerp1;
private bool lerp2;
private bool lerp3;
private bool lerp4;
private void CountDown()
{
if (canCount)
{
timer += Time.deltaTime;
if (timer >= 2)
{
canCount = false;
Debug.Log("Timer End");
}
}
}
private void Lerp()
{
if (lerp1)
{
transform.position = Vector3.Lerp(transform.position, cube1.position, Time.deltaTime * 10);
}
if (lerp2)
{
transform.position = Vector3.Lerp(transform.position, cube2.position, Time.deltaTime * 10);
}
if (lerp3)
{
transform.position = Vector3.Lerp(transform.position, cube3.position, Time.deltaTime * 10);
}
if (lerp4)
{
transform.position = Vector3.Lerp(transform.position, cube4.position, Time.deltaTime * 10);
}
}
private void Update()
{
CountDown();
Lerp();
if (Input.GetMouseButtonDown(0))
{
if (!canCount)
{
click1 = true;
click2 = false;
click3 = false;
click4 = false;
lerp2 = false;
lerp3 = false;
lerp4 = false;
if (click1)
{
click1 = false;
click2 = true;
lerp4 = false;
lerp1 = true;
timer = 0;
canCount = true;
}
else if (click2 && canCount)
{
click2 = false;
click3 = true;
lerp1 = false;
lerp2 = true;
timer = 0;
}
else if (click3 && canCount)
{
click3 = false;
click4 = true;
lerp2 = false;
lerp3 = true;
timer = 0;
}
else if (click4 && canCount)
{
click4 = false;
click1 = true;
lerp3 = false;
lerp4 = true;
timer = 0;
}
}
else
{
if (click1)
{
click1 = false;
click2 = true;
lerp4 = false;
lerp1 = true;
timer = 0;
canCount = true;
}
else if (click2)
{
click2 = false;
click3 = true;
lerp1 = false;
lerp2 = true;
timer = 0;
}
else if (click3)
{
click3 = false;
click4 = true;
lerp2 = false;
lerp3 = true;
timer = 0;
}
else if (click4)
{
click4 = false;
click1 = true;
lerp3 = false;
lerp4 = true;
timer = 0;
}
}
}
发布于 2021-06-03 16:29:20
下面的代码应该允许您设置无限多个要移动的对象,以便为每个对象设置唯一的等待时间,直到播放机再次单击移动到下一个对象。如果用户未能在给定的时间内单击,则下一次单击将再次移动到第一个对象。
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
/// <summary>
/// Holds data to a goal target and how long the player has to click to move towards it
/// </summary>
[System.Serializable]
public class CountdownLerpData
{
public float timeToWaitForClick = 0.0f;
public Transform destination = null;
}
public class YourScript : MonoBehaviour
{
[SerializeField] private List<CountdownLerpData> LerpDestinations = new List<CountdownLerpData>();
private Coroutine ExtraMouseClicks = null;
private Coroutine MoveToDestination = null;
// distance until our object has reached our goal point
private const float DISTANCE_EPSILON = 0.001f;
// the speed at which our object moves to a goal position
private float moveSpeed = 10f;
private void Update()
{
// just use update for your first click input, any successive clicks are handled by the Coroutine
if (Input.GetMouseButtonDown(0) && ExtraMouseClicks == null)
ExtraMouseClicks = StartCoroutine(MoveAndDetectMouseClicks(0));
}
/// <summary>
/// Will start a movement coroutine and wait until the time to click is exceeded or
/// when the player clicks, it will start a new coroutine
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
private IEnumerator MoveAndDetectMouseClicks(int idx)
{
// we wait for the next frame to assure we do NOT use the same mouse click event
yield return null;
// we exceeded our container, so exit the coroutine and set it to null
if (idx >= LerpDestinations.Count)
{
ExtraMouseClicks = null;
yield break;
}
float currentTimer = 0.0f; // the time to wait for our next click
bool hasMouseClick = false; // flag to determine if the user clicked
// start a new Coroutine for the motion - stop it if it is ongoing
if (MoveToDestination != null)
StopCoroutine(MoveToDestination);
// start it with our current index
MoveToDestination = StartCoroutine(MoveTowardsDestination(LerpDestinations[idx].destination.position));
// now wait our time to determine if another mouse click occurs, if it does, then increment our counter
while (currentTimer <= LerpDestinations[idx].timeToWaitForClick && !hasMouseClick)
{
// if we have a mouse click, then
if (Input.GetMouseButtonDown(0) && !hasMouseClick)
{
// the user clicked, so set our flag to true
hasMouseClick = true;
// assign the coroutine
ExtraMouseClicks = StartCoroutine(MoveAndDetectMouseClicks(idx + 1));
}
// increase our time since the last frame
currentTimer += Time.deltaTime;
yield return null;
}
// the user missed the window to click again, so set the reference back to null
if (!hasMouseClick)
ExtraMouseClicks = null;
}
/// <summary>
/// Moves your object to a goal location by moveSpeed speed
/// </summary>
/// <param name="goalPosition"></param>
/// <returns></returns>
private IEnumerator MoveTowardsDestination(Vector3 goalPosition)
{
// now lerp until we reach our destination
while (Vector3.Distance(transform.position, goalPosition) > DISTANCE_EPSILON)
{
transform.position = Vector3.MoveTowards(transform.position, goalPosition, moveSpeed * Time.deltaTime);
yield return null;
}
}
}
我的方法将不再存储多次点击和延迟,这是非常令人头痛的,我的方法将删除单独跟踪这些数据。相反,您将有一个名为List
的对象的CountdownLerpData
,它包含两个字段。第一个字段是timeToWaitForClick
,它是程序在单击发生后等待的时间,以决定单击是移动到列表中的下一个对象,还是移回第一个对象。第二个字段是destination
,它是此时要移动到的对象的Transform
。
当用户首先单击时,它将通过对象数据的List
启动一个看似合理的反应链。最初的单击将启动所谓的Coroutine
,它可以简单地定义为一个特殊的函数,允许在多个帧上完成一个较大任务的小部分。
一旦您启动倒计时Coroutine
,它将启动MoveTowardsDestination
Coroutine
,它只会将对象移动到倒计时Coroutine
所在的索引的目标对象。如果用户碰巧在所需的时间间隔内单击,它将再次调用相同的Coroutine
,但是现在索引增加了1,以移动到列表中的下一个对象。如果它碰巧达到或超过了List
,它将退出Coroutine
。
让我知道这对你有什么好处,或者这不是你想要的。如果我的实现不是您想要的,我可以调整答案。如果你对它的工作方式或原因有任何疑问的话,也可以评论一下。
https://stackoverflow.com/questions/67829446
复制