Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Raycast 'picking up' items issue

Discussion in 'Scripting' started by djfunkey, May 19, 2016.

  1. djfunkey

    djfunkey

    Joined:
    Jul 16, 2012
    Posts:
    201
    The problem I'm facing is...
    Periodically when I 'pick up' a gameobject, and other objects i can also 'pick up' are quite close to each other, it will pick up both items up, even though the raycast is only hitting one at a time.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PickUp : MonoBehaviour {
    5.  
    6.     public LayerMask interaction;
    7.     public bool canPickup; // keep public for testing
    8.     public Inventory inv; // keep public for testing
    9.  
    10.     private Item item;
    11.  
    12.     /// Need to fix up picking up objects (believe raycast isnt working properly)
    13.     /// Within this block of code
    14.     private void Update () {
    15.         if (canPickup && inv != null) {
    16.             Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
    17.             RaycastHit h; // Using for testing purposes
    18.             if (Physics.Raycast(r, out h, 100f, interaction, QueryTriggerInteraction.Ignore)) {
    19.                 Debug.DrawLine(r.origin, r.GetPoint(100), Color.blue);
    20.                 Debug.Log(h.transform.name);
    21.                 if (Input.GetKeyDown(KeyCode.E)) {
    22.                     inv.pickUpObject(SwitchState());
    23.                 }
    24.             }
    25.         }
    26.     }
    27.  
    28.     // Add a type for each class inherited from Item
    29.     private Item SwitchState () {
    30.         System.Type t = GetComponent(gameObject.tag).GetType();
    31.         Item i = null;
    32.         // Type Checking
    33.         // Type Gun
    34.         if (t == typeof(Gun)) {
    35.             i = gameObject.GetComponent<Gun>();
    36.         }
    37.         // Type Sword
    38.         else if (t == typeof(Sword)){
    39.             i = gameObject.GetComponent<Sword>();
    40.         }
    41.         return i;
    42.     }
    43.  
    44.     private void OnTriggerEnter (Collider other) {
    45.         if (other.CompareTag("Player")) {
    46.             canPickup = true;
    47.             inv = other.GetComponent<Inventory>();
    48.         }
    49.     }
    50.  
    51.     private void OnTriggerExit (Collider other) {
    52.         if (other.CompareTag("Player")) {
    53.             canPickup = false;
    54.             inv = null;
    55.         }
    56.     }
    57. }
    An image of the object setup...
     
  2. Zaladur

    Zaladur

    Joined:
    Oct 20, 2012
    Posts:
    392
    Your problem is that every item is ray casting and picking up - that logic should be owned by the player and only run once. Right now, as long as the ray cast hits any item, every item within range will be picked up.

    Additionally, you don't need the switchstate method. Just getcomponent on the base class, item, and it will grab the proper inherited class of gun or sword.
     
    Last edited: May 21, 2016
    djfunkey likes this.
  3. djfunkey

    djfunkey

    Joined:
    Jul 16, 2012
    Posts:
    201
    @Zaladur thanks for replying,

    I see what you mean, I'm rewriting my code to a similar idea of what you mentioned, thanks!
    Also the code above didn't 'pick up' both times 90% of the time, even though they were both in range of the player.
    I worked around it by comparing if the transform of the hit was equal to the transform of that specific object (which probably isnt the best way), but I'm rewriting the code anyway.

    Thanks for the help again!
    Especially with the getcomponent functionality, that helped heaps!
    (Maybe, that it grabs the inherited class if the bass class is passed to it, should be included in the documentation?)
     
  4. Zaladur

    Zaladur

    Joined:
    Oct 20, 2012
    Posts:
    392
    One way to look at it is that every Gun and Sword is an Item, so if you ask for an Item, they are legitimate targets for the request. If I asked you for a piece of fruit and you had an apple, you would give it to me, even though I didn't specifically ask for an apple. This is the entire reason behind using polymorphism - you can treat everything like the base class and everything will work out fine. Its only when you are using specific methods found in children that you have to be more specific.