I am working on a pickup and droping system but am having some problem with the dropping part. The pickup part works bug free and good, I am setting the grab object as a child to my hold position and that works just fine but i cant figure out how to unset the parent.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class PickupScript : MonoBehaviour
{
public float pickRange = 4f;
private bool slotFull;
public Transform player;
public Transform holdpos;
private Transform currentObject;
void Update()
{
if(Input.GetKeyDown(KeyCode.E) != slotFull)
{
RaycastHit hit;
if(Physics.Raycast(player.position, transform.forward, out hit, pickRange))
{
if(hit.collider.gameObject.tag == "CanGrab")
{
Debug.Log("Nice");
currentObject = hit.transform;
currentObject.transform.position = holdpos.position;
currentObject.parent = holdpos;
slotFull = true;
}
Debug.DrawRay(player.position, transform.forward, Color.green);
}
else
{
}
}
}
}
On the child: you can either assign null to the transform.parent or better yet, call transform.SetParent(null)
I dont understand how i would set the parent to null? or should i set the parent to a folder called drop items in the unity project?
if(Input.GetKeyDown(KeyCode.E) != slotFull)
{
RaycastHit hit;
if(Physics.Raycast(player.position, transform.forward, out hit, pickRange))
{
if(hit.collider.gameObject.tag == “CanGrab”)
{
currentObject = hit.transform;
currentObject.transform.position = holdpos.position;
currentObject.parent = holdpos;
slotFull = true;
}
}
else if(Input.GetKeyDown(KeyCode.E) == slotFull)
{
currentObject.SetParent(null);
}
}
You need to retain a reference to what you originally parented when you had the raycast, then use that reference to call transform.SetParent(null)
Uhm, you set it to “holdpos”, so why don’t you just set it to null?
currentObject.parent = null;
I just had another look at the code you posted that you forget to format properly:
if (Input.GetKeyDown(KeyCode.E) != slotFull)
{
RaycastHit hit;
if (Physics.Raycast(player.position, transform.forward, out hit, pickRange))
{
if (hit.collider.gameObject.tag == "CanGrab")
{
currentObject = hit.transform;
currentObject.transform.position = holdpos.position;
currentObject.parent = holdpos;
slotFull = true;
}
}
else if (Input.GetKeyDown(KeyCode.E) == slotFull)
{
currentObject.SetParent(null);
}
}
This would not really work. Your use of slotFull and the nested if statements just can’t work. When slotFull is false, you would enter the outer if statement when you press the E button. You do the raycast and if you hit something you do the parenting and set slotFull to true. That means from now on, the next frame when GetKeyDown returns false again (it only returns true for one frame) you would enter the outer if statement every frame and do the raycast every frame, again and again. Since your unparenting code is in the else statement of the raycast, it could only be reached when the raycast does not hit anything. However even that would not really help. Because you can only run the unparenting code when you press E down this frame. However if GetKeyDown returns true, you would not enter the outer if statement and no code is executed at all. So you have a complete mess regarding your conditions and structure of your code. You should really rethink your approach. Also currently you never set slotFull back to false, so it stays true forever (unless there is some additional code you haven’t shown).
I found the problem its not the script its the drop function not triggering on time, Its triggerd every frame which i will look in to tomorrow. This is how far i came today
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class PickupScript : MonoBehaviour
{
public float pickRange = 4f;
private bool slotFull;
public Transform player;
public Transform holdpos;
private Transform currentObject;
private void Start()
{
slotFull = false;
}
void Update()
{
if(Input.GetKeyDown(KeyCode.E) != slotFull)
{
RaycastHit hit;
if(Physics.Raycast(player.position, transform.forward, out hit, pickRange))
{
if(hit.collider.gameObject.tag == "CanGrab")
{
currentObject = hit.transform;
currentObject.transform.position = holdpos.position;
currentObject.parent = holdpos;
slotFull = true;
}
}
}
if(Input.GetKeyDown(KeyCode.Q) == slotFull)
{
Debug.Log("Hello");
}
}
}
I guess this line should be
if(!slotFull && Input.GetKeyDown(KeyCode.E))
GetKeyDown always returns false unless the key was pressed down this frame. In your code when slotFull is true, your if condition would be true all the time since GetKeyDown returns false which is not equal to true so the result is true since false != true is a true statement. It only stops executing for one frame when you actually press the key down.
In my code I need two conditions and both need to be true in order to execute the if body. slotFull must be false and GetKeyDown must be true. The same logic should be used by your other if statement. Though you could simplify your code and it would be easier to read when you simply use a nested if statement
if(Input.GetKeyDown(KeyCode.E))
{
if (!slotFull)
{
// do your raycast stuff here
}
else
{
// do your unparenting here
}
}
With this structure its way easier to read and reason about the code. Anything inside the outermost if statement is only executed when we press the button down. When we do that, depending on the slotFull state we either do the raycast and parent the found object, or we unparent the object. Though, keep in mind to change the “slotFull” variable back to false when you unparent the object.
Okay so i re wrote the whole script and got everything working correctly here is the finished code. Thanks for all the help!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickUpScript : MonoBehaviour
{
public float pickRange = 4f;
private bool slotFull;
public Transform player;
public Transform holdPos;
private Transform pickedItem;
void Start()
{
}
void Update()
{
if(Input.GetKey(KeyCode.E))
{
if(!slotFull)
{
PickUp();
}
}
if(Input.GetKey(KeyCode.Q))
{
if(slotFull)
{
Drop();
}
}
}
void PickUp()
{
RaycastHit hit;
if (Physics.Raycast(player.position, transform.forward, out hit, pickRange))
{
if (hit.collider.gameObject.tag == ("CanGrab"))
{
pickedItem = hit.transform;
pickedItem.transform.position = holdPos.position;
pickedItem.parent = holdPos;
slotFull = true;
}
}
}
void Drop()
{
pickedItem.parent = null;
slotFull = false;
}
}