【发布时间】:2020-04-19 05:06:41
【问题描述】:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateAndScale : MonoBehaviour
{
public Transform target; // Target to scale
public Vector3 minScale; // Minimum scale value
public Vector3 maxScale; // Maximum scale value
public Vector3 maxRotate;
public Vector3 minRotate;
public float speed;
private float t = 0.0f;
void Update()
{
//if (Input.GetKey(KeyCode.C))
//{
t += speed * Time.deltaTime;
target.localScale = Vector3.Lerp(target.localScale, maxScale, t);
target.localRotation = Quaternion.Lerp(target.localRotation,
Quaternion.Euler(maxRotate.x, maxRotate.y, maxRotate.z), t);
// }
}
}
这会将对象缩放并旋转到最大一次。但我希望它达到最大值,然后回到最小值,然后不间断地达到最大值和最小值。
然后我想使用一个键,例如 C,当按一次 C 时,它会达到最大,再按一次 C,它会回到最小值。
但首先我不知道如何用不间断的乒乓球来做,然后如何用钥匙做?
我添加了一个新的全局标志来中断协程,所以如果在中间按 C 时为真,它将实时直接更改为另一个方向 min 或 max,如果中断标志为假,它将使用 C 键和以前一样。但它不起作用,它仍然什么都不做,即使中断标志为真,我也需要等待它完成更改为最小值/最大值。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateAndScale : MonoBehaviour
{
public Transform target; // Target to scale
public Vector3 minScale; // Minimum scale value
public Vector3 maxScale; // Maximum scale value
public Vector3 maxRotate;
public Vector3 minRotate;
public float speed;
public bool interruptCoroutine = false;
// Flag for blocking input until one routine is done
private bool isMoving;
// Flag for deciding in which direction to go next
// Via the Inspector set this to the direction it shall initially go towards
[SerializeField] bool towardsMin;
private float t = 0.0f;
void Update()
{
if(interruptCoroutine == true)
{
if (Input.GetKeyDown(KeyCode.C))
{
StopAllCoroutines();
StartCoroutine(DoMove());
}
}
else
{
if (!isMoving && Input.GetKeyDown(KeyCode.C))
{
StartCoroutine(DoMove());
}
}
}
// Once started via a StartCoroutine call this will be executed
// every frame until the next yield command
IEnumerator DoMove()
{
if (interruptCoroutine == false)
{
// Just in case block concurrent routines
if (isMoving) yield break;
// Block input
isMoving = true;
}
// Decide if going to Max or min
var targetRot = Quaternion.Euler(towardsMin ? minRotate : maxRotate);
var targetScale = towardsMin ? minScale : maxScale;
// Store Start values
var startRot = target.localRotation;
var startScale = target.localScale;
var duration = 1 / speed;
var timePassed = 0f;
while (timePassed < duration)
{
t = timePassed / duration;
// Optional: add ease-in and ease-out
//t = Mathf.SmoothStep(0, 1, t);
target.localScale = Vector3.Lerp(startScale, targetScale, t);
target.localRotation = Quaternion.Lerp(startRot, targetRot, t);
// Increase the time passed since last frame
timePassed += Time.deltaTime;
// This tells Unity to "pause" the routine here,
// render this frame and continue from here
// in the next frame
yield return null;
}
// Just to be sure to end with exact values apply them hard once
target.localScale = targetScale;
target.localRotation = targetRot;
// Invert direction
towardsMin = !towardsMin;
if (interruptCoroutine == false)
{
// Done -> unlock input
isMoving = false;
}
}
}
【问题讨论】: