[英]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.