Home > Mobile >  How to grab the nearest object from a spherecast?
How to grab the nearest object from a spherecast?

Time:01-28

Im using a Grab Object script that grabs a object that is inside the trigger collider. But when i try to grab a object with more than 1 object inside the collider it grabs all the objects at the same time (example image with two bricks grabbed at the same time).

I need a rule to grab only the nearest object.

two brick grabbed

im using this script to grab the objects. Found it on a YT tutorial and tweaked it

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;
        }
 }

}

CodePudding user response:

There is a sphere cast implemented in Unity's physics system, however it exists for a different purpose. Instead you're looking for Physics.OverlapSphere

Assuming that your guide object should be the center of the sphere you can determine the closest object (closestSelectedObject) in a specified selection radius.

float radiusOfSphere;
float smallesDistance;
Transform closestSelectedObject;
/***/

void Update(){
  if(Input.GetKeyDown("space")){
    Collider[] hitColliders = Physics.OverlapSphere(guide.transform.position, radiusOfSphere);
    if(hitColliders.length > 0){
      smallesDistance = radiusOfSphere;
      foreach(Collider obj in hitColliders){
        float tempDistance = Vector3.Distance(obj.transform.position, guide.transform.position);
        if(tempDistance <= smallesDistance){
          smallesDistance = tempDistance;
          closestSelectedObject = obj;
        }
      }
      /*other stuff that your code does*/
    }
  }
}

CodePudding user response:

my final functional (Update) code here Cant make it without your help @derHugo, thank you!

void Update () {

    Collider[] hitColliders = Physics.OverlapSphere(guide.transform.position, radiusOfSphere);
    var closestSelectedObject = hitColliders.OrderBy(obj => (obj.transform.position - guide.transform.position). sqrMagnitude).FirstOrDefault();
    
    GameObject grabbed = GameObject.Find("grabbedObject");

    if (grabbed != null)
    {
    Debug.Log("existe");
    if (Input.GetKeyDown(KeyCode.Space) && !spaceDisabled) {
    spaceDisabled = true;
    }
    }

    else
    {

        if (Input.GetKeyDown("space"))
        {

            // targetObject does not exist in the scene
            Debug.Log("NAOexiste");

                if (closestSelectedObject.tag.Contains("CanPickup"))
                {

                closestSelectedObject.transform.position = tempParent.transform.position;
                closestSelectedObject.transform.parent = tempParent.transform;
                closestSelectedObject.GetComponent<Rigidbody>().detectCollisions = false;
                closestSelectedObject.GetComponent<Rigidbody>().isKinematic = true;
                closestSelectedObject.GetComponent<Rigidbody>().useGravity = true;

                originalName = closestSelectedObject.name;
                closestSelectedObject.name = "grabbedObject";
                
                //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 (Input.GetKeyDown(KeyCode.Q))
                {
                Debug.Log("Q key was pressed.");
                
                grabbed.transform.parent = null;
                grabbed.GetComponent<Rigidbody>().detectCollisions = true;
                grabbed.GetComponent<Rigidbody>().isKinematic = false;
                grabbed.GetComponent<Rigidbody>().useGravity = true;
                grabbed.GetComponent<Rigidbody>().AddForce(guide.transform.forward * throwForce);          
                
                Input.ResetInputAxes();

                grabbed.name = originalName;
                
            }

    }   
  • Related