【问题标题】:Unity - Laser activated objects using raycastUnity - 使用光线投射的激光激活对象
【发布时间】:2018-06-29 07:16:08
【问题描述】:

我正在尝试重新创建一个简单的激光拼图机制,就像在 Talos 原理中看到的那样 - 我有一个可以移动和旋转的激光发射器,当光束(射线投射和 LineRenderer)击中特定对象时,对象将变得“活跃”。然而,当物体不再被激光击中时,它应该“停用”。

我在停用部分遇到问题。有没有办法告诉对象它不再被光线投射击中,或者向LineRenderer 添加一个对撞机?或者通过第三种方式告诉对象它不再被任何激光击中。

【问题讨论】:

  • 你尝试了什么?发布一些代码来显示您的问题
  • 你能每 x 帧运行一次检查,看看它是否被击中吗?然后激活/停用?
  • 我觉得你的方法有点不对;我会这样做:所有可激活的对象都应该尝试一直停用(可能是协同程序),但是当它被射线击中时你会取消它
  • @JamesLingham - 那太好了,但我怎么能从光线投射接收器中检查呢? -zedling - 嗯..好主意,我会尝试看看我是否可以按照这些思路为我解决问题
  • @darknath 可能是一个倒计时变量,它会减少每一帧,并在光线投射时重置,类似于 Doh09 建议的内容

标签: c# unity3d


【解决方案1】:

当您的目标被射线投射命中时,您可以使用 RaycastHit 引用来获取脚本并更新冷却时间。

假设我们有 RaySender 和 RayReceiver。

RaySenderScript

public class RaySenderScript{
    RaycastHit Hit;
    void FixedUpdate(){
        //SendRaycast and store in 'Hit'.
        if (Hit.collider != null)
           { //If raycast hit a collider, attempt to acquire its receiver script.
               RayReceiverScript = Hit.collider.gameObject.GetComponent<RayReceiverScript>();
               if (RayReceiverScript != null)
                  { //if receiver script acquired, hit it.
                      RayReceiverScript.HitWithRay();
                  }
           }
    }  
}

RayReceiverScript

public class RayReceiverScript{
    public float HitByRayRefreshTime = 1f;
    float RayRunsOutTime;
    public bool IsHitByRay = false;
    void Start()
    {   //Initialize run out time.
        RayRunsOut = Time.time;
    }

    void Update()
    {
        if (Time.time > RayRunsOutTime)
        { //check if time run out, if it has, no longer being hit by ray.
            IsHitByRay = false;
        }
    }

    public void HitWithRay(){ //method activated by ray sender when hitting this target.
         IsHitByRay = true;
         RayRunsOutTime = Time.time + HitByRayRefreshTime;
    }  
}
  1. 发送者用射线击中接收者。
  2. Sender 有一个对 Receiver 的引用,它使用 GetComponent() 来访问它。然后可以说receiverScript.HitWithRay();
  3. 接收器不断检查它是否不再接收,如果不是,则停止被射线击中。

【讨论】:

  • 请注意,我实际上并没有发送光线投射,我假装你在“//SendRaycast 并存储在'Hit'”评论中首先在发送者脚本中处理。
  • 非常酷的解决方案,谢谢。这非常适合我想要的。
  • 太棒了:-)。记住你可以调整冷却时间,它不一定是 1f。
【解决方案2】:

将所有被激光击中的物体添加到集合中,并检查当前目标是否在此集合中。如果它不存在,则它被“停用”。

【讨论】:

  • 这依赖于发件人停用它。如果发件人被销毁怎么办?我想你可以有一个 OnDestroy() 设置它也不会被击中。但总而言之,让目标命中负责检查它是否被命中会更好,因为它在代码方面和对象方面更加孤立。对于未来的操作,哪个更好、更安全。