c# - 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");
}
}
}
}
解决方案
Input.GetKey
在按键保持按下状态时每帧触发。
您宁愿使用的Input.GetKeyDown
是true
仅在实际按下按钮时的一帧中。
进一步注意,我总是选择使用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");
}
}
}
推荐阅读
- iis - IIS - 发布 - 错误 405 方法不允许
- node.js - 在 Jenkins 管道中合并多个笑话覆盖率报告
- python - 403 客户端错误:禁止访问 url:https://api.twitter.com/oauth/request_token - 无法使用 Twitter 登录
- c++ - 如何将对象函数的实例传递给另一个函数?
- batch-file - 有没有办法编写批处理文件以使用设置变量重命名文件?
- swift - 选择可重复使用的表格视图单元格时索引超出范围
- c# - 实体框架数据库优先方法 - 如何制作异步方法?
- sql - 如何删除sqlite中的第n行表?
- c++ - 为什么我对“鱼”挑战的 C++ 解决方案失败了?
- java - 在哪里增加堆大小 - jboss 或 java?