C# 在Unity中与游戏对象交互

C# 在Unity中与游戏对象交互,c#,unity3d,C#,Unity3d,我想在Unity中与游戏对象交互。这些对象可能是钥匙、门、箱子 假设桌子上有一把钥匙。当玩家靠近它时,它应该被一个着色器勾勒出来,一个文本显示为“拾取键” 我为可交互的游戏对象创建了一个界面 public interface IInteractable { string InteractabilityInfo { get; } void ShowInteractability(); void Interact(); } 通过这样做,我可以将接口组件添加到我的Key脚

我想在Unity中与游戏对象交互。这些对象可能是钥匙、门、箱子

假设桌子上有一把钥匙。当玩家靠近它时,它应该被一个着色器勾勒出来,一个文本显示为“拾取键”

我为可交互的游戏对象创建了一个界面

public interface IInteractable
{
    string InteractabilityInfo { get; }

    void ShowInteractability();

    void Interact();
}
通过这样做,我可以将接口组件添加到我的
Key
脚本中

public class Key : MonoBehaviour, IInteractable
{
    public string InteractabilityInfo { get { return "some text here"; } }

    public void ShowInteractability()
    {
        // Outline Shader maybe?
    }

    public void Interact()
    {
        // Do something with the key
    }
}
当涉及到一个脚本来检查某些东西是否可交互时,我创建了一个脚本来创建一个光线投射来检查可交互。(我将此脚本附加到我的FPS相机)

公共类可交互性检查:单行为
{
私有常量int范围=3;
私有void更新()
{
雷卡斯特击中;
if(物理光线投射(变换.位置,变换.向前,命中率,射程))
{
IIINTERACTABLE interactable=hit.collider.GetComponent();
if(可交互!=null)
{
可交互。显示可交互();
if(Input.GetKeyDown(KeyCode.E))
{
可交互的;
}
}
}
}
}
此脚本尝试获取接口组件,如果该组件不为null,则从中调用方法

这段代码工作得很好,但我不喜欢的是光线投射每帧触发一次。有没有其他方法实现可交互性?

是的,光线投射是“昂贵的”,称它为每一帧都不酷,有很多方法可以避免这种情况。在您的情况下,您可以这样简单地重新构造代码:

private void Update()
{

    if (Input.GetKeyDown(KeyCode.E))
    {
      RaycastHit hit;
      if (Physics.Raycast(transform.position, transform.forward, out hit, RANGE))
      {
          IInteractable interactable = hit.collider.GetComponent<IInteractable>();

          if (interactable != null)
          {
              interactable.ShowInteractability();
              interactable.Interact();      
          }
      }
  }
}

另一种方法是在可交互对象上放置球形触发器,然后可以通过球形触发器的
半径
控制范围。 这类似于我刚才回答的另一个问题,所以我刚刚修改了代码

using UnityEngine;

[RequireComponent(typeof(SphereCollider))]
internal abstract class CollisionTrigger : MonoBehaviour
{
    private bool _isPlayerInsideTrigger = false;

    private void Awake()
    {
        if(!GetComponent<SphereCollider>().isTrigger)
        {
            Debug.LogError("Please set the sphere collider to a trigger.");
            enabled = false;
            return;
        }
    }

    private void Update()
    {
        if(_isPlayerInsideTrigger)
        {
            FakeOnTriggerStay();
        }
    }

    private void OnTriggerEnter(Collider collider)
    {
        if(!collider.CompareTag("Player")) return;
        _isPlayerInsideTrigger = true;
    }

    public abstract void FakeOnTriggerStay();

    private void OnTriggerExit(Collider collider)
    {
        if(!collider.CompareTag("Player")) return;
        _isPlayerInsideTrigger = false;
    }
}

很抱歉,我必须撤消接受,因为此解决方案无效。我必须调用
interactiable.showInteractibility()当某些东西被光线投射击中时,而不仅仅是按键
public void interactWithYourObject()
{
    RaycastHit hit;
    if (Physics.Raycast(transform.position, transform.forward, out hit, RANGE))
      {
          IInteractable interactable = hit.collider.GetComponent<IInteractable>();

          if (interactable != null)
          {
              interactable.ShowInteractability();
              interactable.Interact();      
          }
      }
}
private void Update()
{
   RaycastHit hit;
   if (Physics.Raycast(transform.position, transform.forward, out hit, RANGE))
   {
      interactWithYourObject()
   }
}
using UnityEngine;

[RequireComponent(typeof(SphereCollider))]
internal abstract class CollisionTrigger : MonoBehaviour
{
    private bool _isPlayerInsideTrigger = false;

    private void Awake()
    {
        if(!GetComponent<SphereCollider>().isTrigger)
        {
            Debug.LogError("Please set the sphere collider to a trigger.");
            enabled = false;
            return;
        }
    }

    private void Update()
    {
        if(_isPlayerInsideTrigger)
        {
            FakeOnTriggerStay();
        }
    }

    private void OnTriggerEnter(Collider collider)
    {
        if(!collider.CompareTag("Player")) return;
        _isPlayerInsideTrigger = true;
    }

    public abstract void FakeOnTriggerStay();

    private void OnTriggerExit(Collider collider)
    {
        if(!collider.CompareTag("Player")) return;
        _isPlayerInsideTrigger = false;
    }
}
internal class Key : CollisionTrigger
{
    public override void FakeOnTriggerStay()
    {
        // Show the user they can now interact with it.
        // Outline Shader maybe?

        if(Input.GetKeyDown(KeyCode.E))
        {
            // Do something with the key.
        }
    }
}