Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to pick up an Item and place at correct position in hand?

Discussion in 'Scripting' started by brashadam85, Apr 13, 2021.

  1. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    Hey folks,

    Been trying to figure out this silly little thing for days now, found many a resource on Youtube and on here on picking up and dropping items, creating an inventory system etc. Just not experienced enough yet to fully apply it to my little character. I'm using Synty Basic People and Basic Props, its a little 3d top down game, the character can pickup a crowbar onCollisionStay and a Key Press (parenting the object to an empty Game Object at the characters right hand), and drop it on another key press(parenting it to the original Game Object), and he can only pick up 1 item at a time. This is all working fine.

    The problem I'm having is I have no idea how to make the crowbar attach to the hand at a custom position and rotation, as it is just now the weapon centres on the hand, so he is holding it by the middle.

    How would I make it attach to his hand so he's holding it like he's about to swing it, or if its a gun so he's holding it properly? My weapons are all under the tag "Weapon" just now, but will split them into Melee and Guns at some point. I'll attach my pick up script which is attached to my player.

    Code (CSharp):
    1. public class PickUp : MonoBehaviour
    2. {
    3.     public bool isEquipped;
    4.     private Rigidbody itemRb;
    5.     public Transform rightHand;
    6.  
    7.  
    8.     // Start is called before the first frame update
    9.     void Start()
    10.     {
    11.         isEquipped = false;
    12.        
    13.  
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.         //Drop item on keypress and enable rigidbody
    20.             if (Input.GetKey(KeyCode.F) && isEquipped)
    21.         {
    22.             itemRb.transform.parent = GameObject.Find("PickUps").transform;
    23.             isEquipped = false;
    24.             itemRb.isKinematic = false;
    25.             itemRb.detectCollisions = true;
    26.  
    27.         }
    28.     }
    29.  
    30.     public void OnCollisionStay(Collision collision)
    31.     {
    32.         //Pick up item on key press, parent to hand and disable rigidbody
    33.        if (collision.gameObject.CompareTag("Weapon")  && Input.GetKey(KeyCode.E) && !isEquipped)
    34.        {
    35.             collision.transform.position =  rightHand.position;
    36.             collision.transform.rotation = rightHand.rotation;
    37.             isEquipped = true;
    38.  
    39.            
    40.             itemRb = collision.gameObject.GetComponent<Rigidbody>();
    41.             itemRb.transform.parent = rightHand.transform;
    42.             itemRb.isKinematic = true;
    43.             itemRb.detectCollisions = false;
    44.  
    45.  
    46.         }
    47.  
    48.      
    49.     }
    50. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Your parenting of the object is fine.

    The part you are missing is settings its .localRotation and .localPosition

    In order to not go completely insane managing different offsets and rotations on all your items, be kind to yourself and set your weapon and tool prefabs up so that they can attach "correctly" to your player's hand when their .localRotation is Quaternion.identity, and their .localPosition is Vector3.zero

    Then just set those two local values in the item's transform AFTER parenting it to the attach point.
     
    eses likes this.
  3. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    Thanks for reply

    I watched a video where the guy copied the object and placed it where he wanted in the players hand, he copied the position and rotation, then deleted the object and used those numbers in the script. Is that what you mean by this or am I over complicating things? Sorry if its a silly question, I've only been learning game dev since January and I'm probably getting a bit ahead of my actual ability lol
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    That's exactly what I mean, but I think there is value in creating your props so that there is a magical "zero point" that matches up perfectly with your character's hand zero point.

    That way you don't need special numbers. Generally special numbers are bad bad bad because if the art changes, you have to go change code. And any number at all besides Quaternion.Identity and Vector3.zero is a "magic number," and six months from now you won't remember how you got it or how to change it.

    But if every gun has its zero point at the back of the grip, and every player hand has his zero point at the base of his palm, you're golden, no magic numbers.

    Remember, Magic Numbers Bad!(tm)
     
  5. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    Thanks for the help, I'm pretty sure I understand roughly how to call for this in script. One more question, the Zero Point. How do I create this? Is it just a matter of placing the object where I want it, like in position in the players hand and then creating a PreFab of that object?
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    It may just require an extra GameObject "below" the level of the player's hand, and an extra GameObject "above" the level of the Gun. That means:

    PlayerHierarchy
    Leg
    Body
    Arm
    Hand
    GunZero


    Then the gun prefabs would be

    GunZeroPoint
    GunGeometryOffsetSoItLooksCorrect
     
  7. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    Sorry I'm still struggling with this, I've made an empty game object that I've set at the handle of the crowbar, and parented the crowbar to it, the crowbar moves close to the hand but the game object with the new pivot does not.

    I've also tried adding a script to the crowbar with 2 public Vector 3 variables, I've entered the position and rotation in the editor, but when I try to apply it to my pickup script on the player, and reference the other script the weapon starts flying around in front of the player.
     
    Last edited: Apr 14, 2021
  8. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    Would it be easier to attach the weapons in position as a child of the players hand and then hide it through script until one of the ground is picked up? Using instantiate and destroy object for the one on the ground and then use something like this.gameObject.transform.Find("Weapon").gameObject.SetActive(false); to hide it and the opposite to show it?
     
    Last edited: Apr 14, 2021
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Totally viable approach. However,

    Never ever ever ever write code like the above.

    When you do, the next thing you will do is get a null reference and have no idea why.

    Write it one line at a time.

    How to break down hairy lines of code:

    http://plbm.com/?p=248
     
    brashadam85 likes this.
  10. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    Thanks again for the help, so far I'm kinda getting there, the object on the ground destroys when the player enter the trigger and the child object in hand is set active, works for an axe and a crowbar. When i press F it drops the weapon and weaponEquipped is false, the problem I'm having is that it only drops the crowbar, if your holding a crowbar it hides the one in your hand, and spawns one that falls in front of you that you can pickup again and again. When I pickup the axe it places the axe in my hand, but when I press F it spawns a crowbar, weaponEquipped is set to false and the axe model remains in my hand. I know I'm probably just missing something really obvious but any help would be appreciated.

    Here's my new pickup code
    Code (CSharp):
    1. public class PickUp : MonoBehaviour
    2. {
    3.     public Transform weaponSlot;
    4.  
    5.     private GameObject crowbar;
    6.     public GameObject crowbarDrop;
    7.     private GameObject axe;
    8.     public GameObject axeDrop;
    9.     public bool weaponEquipped;
    10.  
    11.     // Start is called before the first frame update
    12.     public void Start()
    13.     {
    14.         weaponEquipped = false;
    15.  
    16.         crowbar = GameObject.Find("CrowBar_Hand");
    17.         crowbar.SetActive(false);
    18.         axe = GameObject.Find("Axe_Hand");
    19.         axe.SetActive(false);
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     public void Update()
    24.     {   //Hide crowbar child object and spawn another on drop
    25.      
    26.         if (Input.GetKey(KeyCode.F) && weaponEquipped && crowbar)
    27.         {
    28.             crowbar.SetActive(false);
    29.             weaponEquipped = false;
    30.             Instantiate(crowbarDrop, weaponSlot.position, Quaternion.identity);
    31.         }
    32.  
    33.  
    34.         else if (Input.GetKey(KeyCode.F) && weaponEquipped && axe)
    35.         {
    36.            
    37.             axe.SetActive(false);
    38.             weaponEquipped = false;
    39.             Instantiate(axeDrop, weaponSlot.position, Quaternion.identity);
    40.         }  
    41.  
    42.     }  
    43.    
    44.  
    45.  
    46.     public void OnTriggerStay(Collider other)
    47.     {
    48.         if (other.CompareTag("Crowbar") && Input.GetKey(KeyCode.E) && !weaponEquipped)
    49.         {
    50.             crowbar.SetActive(true);
    51.             Destroy(other.gameObject);
    52.             weaponEquipped = true;
    53.         }
    54.  
    55.         if (other.CompareTag("Axe") && Input.GetKey(KeyCode.E) && !weaponEquipped)
    56.         {
    57.             axe.SetActive(true);
    58.             Destroy(other.gameObject);
    59.             weaponEquipped = true;
    60.         }
    61.        
    62.     }
    63. }  

    I know its probably a really backward way of doing it, but for the most part seems to work so far and I'm only gonna be using a few weapons in this as its just for learning purposes.
     
  11. brashadam85

    brashadam85

    Joined:
    Jan 27, 2021
    Posts:
    14
    I got it, I just needed a bool to determine what weapon the player was holding.
     
    Kurt-Dekker likes this.