Unity 中的光线投射和计时器存在问题
本文关键字:计时器 存在 问题 光线投射 Unity | 更新日期: 2023-09-27 18:36:12
这是我
最后一个问题的后续,现在我希望扩展它的功能,但我遇到了一些主要障碍。
我的目标如下:
我有一个相机,它投射光线以击中具有特定标签的物体。当光线在设定的时间段内击中标签时,我正在寻找要发生的事情,现在我正在寻找的只是调试消息或简单的东西。当光线没有击中任何带有标签的物体时,我希望我的计时器不会更新。如果用户将视线从对象上移开并返回,我希望计时器从 0 再次启动,并且如果用户查看另一个标签,即计时器再次启动,我想要类似的功能。
无论如何,我的计时器没有按预期工作,无论我在看什么,它都会继续计数。我花了 3 个小时在这上面,我得到了隧道视野,我一遍又一遍地尝试相同的代码行。
有一双新鲜眼睛的人可以看看我到目前为止所做的事情,并向我指出我错过/做错了什么吗?
public float end_time;
public float start_time;
private float running_time;
public Texture2D progress_bar_empty;
public Texture2D progress_bar_full;
public Material highlight_material;
public float progress = 0;
public bool hited = false;
public List<string> _tags = new List<string>();
private GameObject hit_object;
private Material oldMat;
RaycastHit hit;
// Use this for initialization
void Start ()
{
start_time = Time.deltaTime;
running_time = 0;
}
// Update is called once per frame
void Update ()
{
EyeTarget();
Check(hited);
}
void EyeTarget()
{
try
{
Vector3 fwd = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, fwd, out hit))
{
foreach(string t in _tags)
{
if(hit.collider.gameObject.tag == t)
{
HighLight();
}
}
}
Debug.DrawRay(transform.position, fwd, Color.red);
}
catch(Exception e)
{
Debug.Log(e.Message);
}
}
void ResetTimer()
{
start_time = Time.time;
running_time = 0f;
//Debug.Log("resetting timer");
}
void HighLight()
{
if(hit_object == null)
{
ResetTime();
oldMat = hit.transform.renderer.material;
hit.collider.gameObject.renderer.material = highlight_material;
hit_object = hit.collider.gameObject;
hited = true;
}
else if( hit.transform.tag != hit_object.tag)
{
//hit.collider.gameObject.renderer.material = oldMat;
hit_object = null;
hit_object.renderer.material = oldMat;
progress = 0;
Debug.Log("hi");
hited = false;
}
}
// see if ray has hit object
void Check(bool hit)
{
if(hit)
{
start_time = Time.time - end_time;
running_time += Time.deltaTime;
if ( running_time >= end_time )
{
hited = false;
}
}
else if( hited == false)
ResetTime();
}
void ResetTime()
{
start_time = Time.time;
running_time = 0f;
Debug.Log("restting timer");
}
我试图尽可能地不理会你的版本。 当光标移离标记对象时,此版本将停止计时器,当另一个标记对象位于raycast
下方时,将从 0 重新开始。
我的代码有点冗长,但它可以更容易地看到发生了什么。
public float end_time;
public float start_time;
public float running_time;
public Texture2D progress_bar_empty;
public Texture2D progress_bar_full;
public Material highlight_material;
public float progress = 0;
public bool trackTimer = false;
public List<string> _tags = new List<string>();
public GameObject lastHitObject = null;
private Material oldMat;
// Use this for initialization
void Start ()
{
ResetTimer();
}
// Update is called once per frame
void Update ()
{
EyeTarget();
// Update the timer if and only if we are tracking time AND
// the last ray cast hit something.
bool updateTimer = (trackTimer && lastHitObject != null);
Check(updateTimer);
}
void EyeTarget()
{
RaycastHit hit;
bool hitTaggedObject = false;
Vector3 fwd = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, fwd, out hit))
{
foreach(string t in _tags)
{
if(hit.collider.gameObject.tag == t)
{
HighLight(hit.collider.gameObject);
hitTaggedObject = true;
}
}
}
// ** Make sure to clean up highlighting if nothing new was hit
if (!hitTaggedObject){
HighLight(null);
}
}
void ResetTimer()
{
start_time = Time.time;
running_time = 0f;
}
void HighLight(GameObject nextHitObject)
{
// Case1: Last ray and new ray both hit objects
if(lastHitObject != null && nextHitObject != null){
//1a: same objects, do nothing
if(lastHitObject.tag == nextHitObject.tag)return;
{ //1b: different objects, swap highlight texture
lastHitObject.renderer.material = oldMat;
lastHitObject = nextHitObject;
oldMat = lastHitObject.renderer.material;
lastHitObject.renderer.material = highlight_material;
trackTimer = true;
return;
}
}
// Case2: Last ray hit nothing, new ray hit object.
if(lastHitObject == null && nextHitObject != null){
ResetTimer();
lastHitObject = nextHitObject;
oldMat = lastHitObject.renderer.material;
lastHitObject.renderer.material = highlight_material;
trackTimer = true;
return;
}
// Case3: Last ray hit something, new ray hit nothing
if(lastHitObject != null && nextHitObject == null){
lastHitObject.renderer.material = oldMat;
lastHitObject = null;
trackTimer = false;
return;
}
}
// see if ray has hit object
void Check(bool updateTimer)
{
if(updateTimer)
{
start_time = Time.time - end_time;
running_time += Time.deltaTime;
if ( running_time >= end_time )
{
trackTimer = false;
}
}
}
trackTimer
是一个状态标志,与所选对象的状态分开,用于跟踪running_time
到达end_time
的时间。 一旦这 2 个相等,trackTimer
就会翻转为 false,您需要突出显示一个新对象或重新突出显示当前对象,然后计时器才会再次启动。