[英]How to accurately get the objects that the camera is directly pointed to?
我正在尝试在我的游戏中拾取对象。 因此,用户直接查看的 object 可以通过单击按钮来获取。 我有LookObject
,它是一个gameObejct
,用于存储我当前正在查看的对象。 我在这里面临的问题是LookObject
没有准确地显示我正在查看的对象。 请看这张图片。
如图所示,标线并不完全位于立方体上,但外观 object 显示的是立方体。 我怎样才能使它准确?
[Header("InteractableInfo")]
public float sphereCastRadius = 0.5f;
public int interactableLayerIndex;
private Vector3 raycastPos;
public GameObject lookObject;
private PhysicsObjects physicsObject;
private Camera mainCamera;
public GameObject winUI;
private InteractiveObjects interactiveObjects;
void Update()
{
//Here we check if we're currently looking at an interactable object
raycastPos = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
{
lookObject = hit.collider.transform.gameObject;
}
Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hit, maxDistance);
if (hit.transform)
{
interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
}
else
{
lookObject = null;
interactiveObjects = null;
}
//if we press the button of choice
if (Input.GetKeyDown(KeyCode.Space))
{
//and we're not holding anything
if (currentlyPickedUpObject == null)
{
//and we are looking an interactable object
if (lookObject != null )
{
PickUpObject(); }
}
}
}
立方体和所有其他可交互对象都有这个脚本:
public class PhysicsObjects : MonoBehaviour
{
public float waitOnPickup = 0.2f;
public float breakForce = 35f;
[HideInInspector] public bool pickedUp = false;
[HideInInspector] public PlayerInteractions playerInteractions;
private void OnCollisionEnter(Collision collision)
{
if (pickedUp)
{
if (collision.relativeVelocity.magnitude > breakForce)
{
playerInteractions.BreakConnection();
}
}
}
//this is used to prevent the connection from breaking when you just picked up the object as it sometimes fires a collision with the ground or whatever it is touching
public IEnumerator PickUp()
{
yield return new WaitForSecondsRealtime(waitOnPickup);
pickedUp = true;
}
}
你在做
if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
{
lookObject = hit.collider.transform.gameObject;
}
半径0.5
米!
然后接下来你做
Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hit, maxDistance);
没有任何图层过滤器,因此您会碰到地板。
所以检查
if (hit.transform)
{
interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
}
else
{
lookObject = null;
interactiveObjects = null;
}
进入if
情况,即使第二个演员的hit.transform
与第一个演员不同。
我真的不明白您为什么首先要进行两次演员表。 您可能更愿意简单地坚持
if (Physics.SphereCast(mainCamera.ViewportPointToRay(Vector2.one * 0.5f), sphereCastRadius, mainCamera.transform.forward, out var hit, maxDistance, 1 << interactableLayerIndex))
// or if you don't want to use a sphere cast anyway
//if(Physics.Raycast(mainCamera.ViewportPointToRay(Vector2.one * 0.5f), maxDistance, 1 << interactableLayerIndex))
{
var lookObject = hit.collider.gameObject;
if(lookObject.TryGetComponent<InteractiveObjects>(out var interactiveObject))
{
if (Input.GetKeyDown(KeyCode.Space))
{
//and we're not holding anything
if (!currentlyPickedUpObject)
{
// whatever happens in here
PickUpObject(interactiveObject);
}
}
}
}
并且只需使用较小的半径进行球体投射,或者如果您不想使用半径,则直接使用简单的 RayCast。
一般来说,我还建议宁愿使用
public LayerMask interactableLayers;
然后直接使用interactableLayers
而不是1 << interactableLayerIndex
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.