首页 > 解决方案 > Unity如何检查一个键是否被点击

问题描述

我的游戏中有一个传送球,您可以将鼠标悬停在上面并单击 e 以用于传送到,但是当我按住 e 按钮并将鼠标悬停在球上时,它无论如何都会传送我,我想做它所以你必须悬停在球体上方并单击 e 不传送,这样您就可以按住 e 然后将鼠标悬停在它上面。关于如何做到这一点的任何想法?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IsLookingAtTeleport : MonoBehaviour
{
    public AudioSource teleportsound;
    public Rigidbody rb;
    void Start()
    {
       
    }

    void FixedUpdate()
    {
        // Bit shift the index of the layer (8) to get a bit mask
        int layerMask = 1 << 8;

        // This would cast rays only against colliders in layer 8.
        // But instead we want to collide against everything except layer 8. The ~ operator does this, it 
        //inverts a bitmask.
        layerMask = ~layerMask;

        RaycastHit hit;
        // Does the ray intersect any objects excluding the player layer
        if (Input.GetKey("e"))
        {
            if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layerMask))
            {
                Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
                Debug.Log("Did Hit");
                if (hit.transform.tag == "TeleportOrb")
                {
                    Debug.Log("Hit Teleportable Orb");
                    teleportsound.Play();
                    rb.transform.position = hit.transform.position;
                    Destroy(hit.transform.gameObject); // destroy the object hit
                }
            }
            else
            {
                Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 1000, Color.white);

                Debug.Log("Did not Hit");

            }   
        }
    }
}

标签: c#unity3d

解决方案


Input.GetKey在按键保持按下状态时每帧触发。

您宁愿使用的Input.GetKeyDowntrue仅在实际按下按钮时的一帧中。

进一步注意,我总是选择使用KeyCode作为参数的版本,而不是字符串版本。

然后确保您在Update not in 中输入您的用户FixedUpdate。虽然后者在某些情况下可能适用于获取连续输入,例如GetKey您可能会错过单个事件输入。

最后,每当涉及 a 时Rigibody,您都不想通过Transform组件设置任何内容。

// Rather configure the desired layers you want to hit here
// via the Inspector in Unity!
// actually way better than just including everything rather only 
// select these layers that actually should be considered as teleport targets
// This way you wouldn't even need to check for Tags!
// just rather place all your teleport objects on a Teleport layer
// and only use a raycast on that layer
// see https://docs.unity3d.com/Manual/Layers.html
[serializeField] private LayerMask hitLayers;

private void Update()
{
    if (Input.GetKeyDown(KeyCode.E))
    { 
        // store the ray once
        var ray = new Ray(rigibody.position, rigidbody.rotation * Vector3.forward);
        if (Physics.Raycast(ray , out var hit, Mathf.Infinity, hitLayers))
        {
            Debug.DrawRay(ray.origin, ray.direction * hit.distance, Color.yellow);
            Debug.Log("Did Hit");

            // Rather use CompareTag instead of string based ==
            if (hit.gameObject.CompareTag("TeleportOrb"))
            {
                Debug.Log("Hit Teleportable Orb");
                teleportsound.Play();
                rb.position = hit.transform.position;
                // destroy the object hit
                Destroy(hit.gameObject);
            }
        }
        else
        {
            Debug.DrawRay(ray.origin, ray.direction * 1000, Color.white);
            Debug.Log("Did not Hit");
        }  
    }
}

推荐阅读