c# - 为什么可变高度值是 0?
问题描述
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(UnityEngine.LineRenderer))]
public class DrawCircle : MonoBehaviour
{
public enum CircleHeight
{
Center, Bottom, Top
};
public CircleHeight circleheight;
[Range(0, 50)]
public int segments = 50;
[Range(1, 50)]
public float xradius = 1.5f;
[Range(1, 50)]
public float yradius = 1.5f;
[Range(-10, 10)]
public float height = 0;
public bool changeBothRadius = false;
[Range(0.1f, 2)]
public float lineThickness = 0.1f;
public bool minimumRadius = false;
public bool draw = false;
public bool animateCircle = false;
public float animationSpeed = 0.5f;
private LineRenderer line;
private Renderer renderer;
private float Bottom;
private float Top;
private float Center = 0;
private float t = 0f;
void Start()
{
circleheight = CircleHeight.Center;
line = gameObject.GetComponent<UnityEngine.LineRenderer>();
line.positionCount = segments + 1;
line.useWorldSpace = false;
renderer = gameObject.GetComponent<Renderer>();
Bottom = transform.InverseTransformPoint(renderer.bounds.min).y + 0.1f;
Top = transform.InverseTransformPoint(renderer.bounds.max).y + 0.1f;
}
void Update()
{
line.startWidth = lineThickness;
line.endWidth = lineThickness;
if (draw)
{
line.enabled = true;
CreatePoints();
}
else
{
line.enabled = false;
}
}
bool animStart = true;
void CreatePoints()
{
float x;
float z;
float angle = 20;
if (animateCircle == false)
{
switch (circleheight)
{
case CircleHeight.Center:
height = Center;
break;
case CircleHeight.Bottom:
height = Bottom;
break;
case CircleHeight.Top:
height = Top;
break;
}
}
else
{
AnimateCircle(Top, Bottom);
}
for (int i = 0; i < (segments + 1); i++)
{
x = Mathf.Sin(Mathf.Deg2Rad * angle) * xradius;
z = Mathf.Cos(Mathf.Deg2Rad * angle) * yradius;
line.SetPosition(i, new Vector3(x, height, z));
angle += (360f / segments + 1);
}
}
private void AnimateCircle(float From, float To)
{
if (animStart)
{
if (height == Center)
{
height = Mathf.Lerp(Center, From, t);
t += animationSpeed * Time.deltaTime;
if (height == From)
{
animStart = false;
}
}
}
}
}
我正在使用 animateCircle 标志来防止枚举始终将高度重置为 Center:
if (animateCircle == false)
然后我添加了一个断点,它没有再次传入它一直在做其他部分:
else
{
AnimateCircle(Top, Bottom);
}
在 AnimateCircle 方法中执行该过程后,我看到高度值为 0.6。
但后来我也在行上添加了一个断点:
line.SetPosition(i, new Vector3(x, height, z));
第一个循环高度为 0.6,但在 i = 50 时循环结束并且循环重新开始后,我看到高度为 0。但我没有在其他任何地方重置高度。
这是 AnimateCircle 方法未使用的代码,只是为了展示我尝试过的和打算做的事情:
private void AnimateCircle(float From, float To)
{
// From = Top To = Bottom
// height = Center
if (animStart)
{
if (height != From)
{
height = Mathf.Lerp(height, From, t);
}
else
{
height = Mathf.Lerp(From, To, t);
}
t += animationSpeed * Time.deltaTime;
if (height == From || height == To)
animStart = false;
}
else
{
height = Mathf.Lerp(From, To, t);
t += animationSpeed * Time.deltaTime;
if (t > 1.0f)
{
if (To == Top)
{
float temp = To;
To = From;
From = temp;
t = 0.0f;
}
if(To == Bottom)
{
float temp = From;
From = To;
To = temp;
t = 0.0f;
}
}
if (To == Top)
{
height = Mathf.Lerp(Bottom, Top, t);
t += animationSpeed * Time.deltaTime;
if (t > 1.0f)
{
float temp = Top;
Top = Bottom;
Bottom = temp;
t = 0.0f;
}
}
if(To == Bottom)
{
height = Mathf.Lerp(Top, Bottom, t);
t += animationSpeed * Time.deltaTime;
if (t > 1.0f)
{
float temp = Bottom;
Bottom = Top;
Top = temp;
t = 0.0f;
}
}
}
}*/
例如,当枚举默认状态为 Start 中的 Center 时游戏开始。如果我打电话AnimateStart(Top, Bottom);
或AnimateStart(Bottom, Top);
然后在 AnimateCircle 内部,我想将圆从中心移动到顶部或底部,具体取决于我如何称呼它。所以从可以是顶部或底部。
在圆圈从中心移动一次到顶部或底部之后,然后在顶部和底部(或底部顶部)之间开始一个不间断的乒乓球。
如果游戏以枚举默认状态为底部或顶部开始,那么只需在顶部和底部之间开始一个乒乓球,而无需中心。
编辑:
这是我现在使用的 AnimateCircle 的代码:
private void AnimateCircle(float From, float To)
{
if (animStart)
{
// prevent t from exceeding tGoal
if (t > tGoal)
{
t = tGoal;
}
// end animation when t reaches goal
if (t == tGoal)
{
animStart = false;
}
// advance height according to t
height = Mathf.Lerp(Bottom, Top, Mathf.PingPong(t, 1f));
// advance height according to time & speed
t += animationSpeed * Time.deltaTime;
}
}
CreatePoints 没有改变:
bool animStart = true;
void CreatePoints()
{
float x;
float z;
float angle = 20;
if (animateCircle == false)
{
switch (circleheight)
{
case CircleHeight.Center:
// t=0.5f, tGoal=1f to go to top first then stop at top
// t=0.5f, tGoal=2f to go to top first then stop at bottom
// t=1.5f, tGoal=2f to go to bottom first then stop at bottom
// t=1.5f, tGoal=3f to go to bottom first then stop at top
t = 0.5f;
tGoal = 2f;
height = Center;
break;
case CircleHeight.Bottom:
t = 0f;
tGoal = 1f;
height = Bottom;
break;
case CircleHeight.Top:
t = 1f;
tGoal = 2f;
height = Top;
break;
}
}
else
{
AnimateCircle(Bottom, Top);
}
for (int i = 0; i < (segments + 1); i++)
{
x = Mathf.Sin(Mathf.Deg2Rad * angle) * xradius;
z = Mathf.Cos(Mathf.Deg2Rad * angle) * yradius;
line.SetPosition(i, new Vector3(x, height, z));
angle += (360f / segments + 1);
}
}
为了首先移动到顶部,我这样调用 AnimateCircle:
AnimateCircle(Top, Bottom);
在 AnimateCircle 内部也是这样的 Top、Bottom:
height = Mathf.Lerp(Top, Bottom, Mathf.PingPong(t, 1f));
在开关盒部分t = 0.5f
和tGoal = 2f
但相反,它首先移动到顶部,然后快速移动到底部,然后从底部移动到顶部。
但是,如果我更改t = 1.5f
,tGoal = 3f;
然后它将首先移动到顶部,然后从顶部移动到底部,这很好。但是 0.5 和 2 并没有先向上移动它。
如果 t = 1.5f 且 tGoal = 2f; 它将向上移动到顶部并停在那里。
但是我找不到如何制作底部部分,所以它会首先移动到底部并停止或首先移动到底部并移动到顶部。
解决方案
添加一个名为 tGoal 的浮点字段:
private float tGoal;
根据您希望它开始的位置设置 t,并在您希望它停止动画的位置设置 tGoal。如果您希望它从 开始Center
,则必须确定适当的 lerp 值以开始:
switch (circleheight)
{
case CircleHeight.Center:
float centerT = Mathf.InverseLerp(Bottom, Top, Center);
// t=0f+centerT, tGoal=1f to go to top first then stop at top
// t=0f+centerT, tGoal=2f to go to top first then stop at bottom
// t=2f-centerT, tGoal=2f to go to bottom first then stop at bottom
// t=2f-centerT, tGoal=3f to go to bottom first then stop at top
t = 2f - centerT;
tGoal = 3f;
height = Center;
break;
case CircleHeight.Bottom:
t= 0f;
tGoal = 1f;
height = Bottom;
break;
case CircleHeight.Top:
t = 1f;
tGoal = 2f;
height = Top;
break;
}
然后使用Mathf.PingPong
变成t
一个 lerp 值,乒乓球。当 t 等于 tGoal 时停止,确保 tGoal 永远不会超过它:
private void AnimateCircle()
{
if (animStart)
{
// prevent t from exceeding tGoal
if (t > tGoal) {
t = tGoal;
}
// end animation when t reaches goal
if (t == tGoal) {
animStart = false;
}
// advance height according to t
height = Mathf.Lerp(Bottom, Top, Mathf.PingPong(t,1f));
// advance height according to time & speed
t += animationSpeed * Time.deltaTime;
}
}
推荐阅读
- regex - 正则表达式查找紧接在日期之前的字符串
- mongodb - 我想在mongodb中使用左外连接,如何使用?我只使用 mongodb 指南针
- unit-testing - 任何支持多种 RPC 协议以测试不同组件的测试工具或框架
- python - python 3.7中的无序字典
- javascript - 为什么删除运算符不适用于使用 Object.create() 方法创建的对象
- python - VSCode:运行代码不考虑 virtualenv
- python - 在python中使用for循环从两个列表创建字典列表
- c - c 中 fork() 的输出
- logic - 如何在 Coq 中证明以下内容?
- html - 在问题和答案周围创建边框