Unity中如何从触发范围内抓取最近的物体?
解决抓取多个物体问题:仅抓取距离最近的物体
问题说明
当前使用的抓取脚本会同时抓取碰撞器范围内的所有物体,需要添加逻辑,只抓取距离玩家(抓取引导点)最近的物体。原脚本代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PickUp : MonoBehaviour { public float throwForce = 100; public bool canHold = true; public GameObject item; public GameObject tempParent; public GameObject poof; public GameObject vanish; public GameObject poofParent; public Transform guide; public bool isHolding = false; float distance; // Use this for initialization void Start () { } // Update is called once per frame void Update () { distance = Vector3.Distance(item.transform.position, guide.transform.position); if (Input.GetKeyDown("space")) if (distance <= 6f) { isHolding = true; item.transform.position = tempParent.transform.position; //Poof GameObject myPoof = Instantiate(poof, Vector3.zero, Quaternion.identity) as GameObject; myPoof.transform.parent = poofParent.transform; myPoof.transform.position = poofParent.transform.position; Destroy (myPoof, 2); //Particles GameObject myVanish = Instantiate(vanish, Vector3.zero, Quaternion.identity) as GameObject; myVanish.transform.parent = tempParent.transform; myVanish.transform.position = tempParent.transform.position; Destroy (myVanish, 4); } if (isHolding==true) { item.GetComponent<Rigidbody>().useGravity = false; item.GetComponent<Rigidbody>().detectCollisions = true; item.GetComponent<Rigidbody>().isKinematic = false; item.transform.parent = tempParent.transform; item.transform.position = tempParent.transform.position; if (Input.GetKeyUp("space")) { Debug.Log("Trying to throw"); item.GetComponent<Rigidbody>().AddForce(guide.transform.forward * throwForce); isHolding = false; } } else { item.GetComponent<Rigidbody>().useGravity = true; item.GetComponent<Rigidbody>().isKinematic = false; item.transform.parent = null; } } }
修改后的代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PickUp : MonoBehaviour { public float throwForce = 100; public bool canHold = true; public GameObject tempParent; public GameObject poof; public GameObject vanish; public GameObject poofParent; public Transform guide; public bool isHolding = false; public float grabRange = 6f; // 给可抓取物体统一添加该标签 public string grabbableTag = "Grabbable"; private GameObject currentHeldItem; void Update () { if (Input.GetKeyDown("space")) { if (!isHolding) { // 查找范围内最近的可抓取物体 GameObject closestItem = FindClosestGrabbableItem(); if (closestItem != null) { currentHeldItem = closestItem; isHolding = true; currentHeldItem.transform.position = tempParent.transform.position; // 生成特效 GameObject myPoof = Instantiate(poof, poofParent.transform.position, Quaternion.identity); myPoof.transform.parent = poofParent.transform; Destroy(myPoof, 2); GameObject myVanish = Instantiate(vanish, tempParent.transform.position, Quaternion.identity); myVanish.transform.parent = tempParent.transform; Destroy(myVanish, 4); } } } if (isHolding && currentHeldItem != null) { Rigidbody rb = currentHeldItem.GetComponent<Rigidbody>(); rb.useGravity = false; rb.detectCollisions = true; rb.isKinematic = false; currentHeldItem.transform.parent = tempParent.transform; currentHeldItem.transform.position = tempParent.transform.position; if (Input.GetKeyUp("space")) { Debug.Log("Trying to throw"); rb.AddForce(guide.transform.forward * throwForce); isHolding = false; currentHeldItem.transform.parent = null; currentHeldItem = null; } } } // 查找范围内最近的可抓取物体 private GameObject FindClosestGrabbableItem() { GameObject[] grabbableItems = GameObject.FindGameObjectsWithTag(grabbableTag); GameObject closest = null; float minDistance = Mathf.Infinity; foreach (GameObject item in grabbableItems) { float distance = Vector3.Distance(item.transform.position, guide.transform.position); if (distance <= grabRange && distance < minDistance) { minDistance = distance; closest = item; } } return closest; } }
关键改动说明
- 新增
grabbableTag变量,用于标记可抓取物体(需要给所有可抓取物体添加对应标签,比如"Grabbable") - 移除原有的单个
item变量,改用currentHeldItem存储当前抓取的物体 - 添加
FindClosestGrabbableItem()方法,遍历所有带指定标签的物体,计算与引导点的距离,筛选出范围内最近的物体 - 修改抓取逻辑,按空格时先查找最近物体,再执行抓取操作
- 优化抛出后的物体状态重置逻辑
内容的提问来源于stack exchange,提问作者diegojms
相关产品推荐
相关产品推荐

