- Home /
Holding object not working. Raycast, and first person.
You probably heard this before cause I read a number of similar Qs, none providing an answer though, but I'm trying to achieve an exact effect of holding and object as in the Amnesia game. xD
I suck at raycasting bad I've read dozens of questions and watched dozens of videos, including the official one but I just don't understand it quite yet. I need a for dummies guide on raycasting. x'D
Anyway here's the code I have now which isn't working. I'm trying to parent it to hold it and unparent to let go, which works only when its not being affected by outside force. And I want it non-kinematic so it doesn't pass through objects but if I make it like that once its pushed out of the raycast I can't seem to unparent it anymore. There's tons of stuff wrong with my code I bet so if anyone has a better way of doing it or a tutorial for exactly that I'll gladly read or watch that, I couldn't find any tutorial for that.
var pickupDistance : int = 10;
var holding : boolean = false;
function Update()
{
//RAYCASTING
var hit : RaycastHit;
var ray : Ray = Camera.main.ScreenPointToRay(Vector3(Screen.width / 2, Screen.height / 2, 0));
if(Physics.Raycast (ray, hit, pickupDistance))
{
//Check if the object is tagged Pickupable and click with mouse
if(Input.GetMouseButtonDown(0) && hit.collider.tag == "Pickupable")
{
Debug.Log("Clicked on " + hit.transform.name);
//Make the tagged object child of the camera and follow it, without being kinematic
hit.transform.parent = gameObject.transform;
hit.rigidbody.useGravity = false;
holding = true;
}
//If mouse button up, make the child object have gravity, unparent and let go
else if(Input.GetMouseButtonUp(0) && holding)
{
hit.rigidbody.useGravity = true;
Drop();
}
//Do the same thing cause the child was affected by outside force and moved from local X 0 and Y 0 coordinates, but in a different way because the child is no longer hit by raycast
else if(hit.transform.localPosition.x > 0 || hit.transform.localPosition.y > 0 && holding)
{
var rigidbodyGravity : Rigidbody;
rigidbodyGravity = gameObject.GetComponentInChildren(Rigidbody);
rigidbodyGravity.useGravity = true;
Drop();
}
}
//if holding is true snap the object to camera local X and Y and the transforms Z
if(holding)
{
hit.transform.localPosition = Vector3(0, 0,hit.transform.position.z);
}
}
//Drop all children
function Drop()
{
transform.DetachChildren();
holding = false;
}
Firstly, I don't know Java I'm a C# guy so the exact coding's going to be difficult. But I don't have an issue with raycasting, so what is it exactly in simpleton terms for me are you trying to do?
If it's what I think, your just trying to pick up an item e.g. $$anonymous$$inecraft, first thing is switch on tracing on your raycast. There's a Unity Video tutorial showing how to colour your raycast lines. That will solve one issue, is my raycasting working correctly? If yes then move onto the second part, picking up the block.
Segment it and take it one step at a time or you'll spend ages trying to figure it out as a whole.
Not really like $$anonymous$$ecraft, I'd manage doing something like that and storing in an inventory and then just holding it, but I just want something like Amnesia where the object is a rigidbody and can knock down other objects and get knocked out of "grasp". I'm trying another way with having a script on the object that can be picked up, but I wanted every rigidbody object with a tag to be picked up and held regardless of whether it has a script on it to act that way.
Answer by RyanZimmerman87 · Sep 20, 2013 at 09:55 PM
I would do this without making the object a child of the player. I don't think that's necessary and it could over complicate things potentially with no real benefits that I can think of.
I think what you need to do in short is cast a Raycast, if it hits the right kind of object you store that object in the Transform position of one of the player's child objects (this object simulates their hand). So you could use any empty gameObject as the child object (or a bone for their hand if you already have the rig) and put the picked up object at that transform position rather than setting the object to be part of the player.
Then you could update the position of the object relative to the transform in FixedUpdate() to allow it to move around with physics. Getting all that set up realistically would require a bit of nice code but shouldn't be to overwhelming since Unity has all the physics stuff set up in PhysX I beleive?
So you could allow Unity's normal rigid body physics to affect the object and just make sure it's always a certain distance from the child transform position. so it doesn't just drop on the floor unless you throw it or whatever.
This would probably be easier to do if the player was kinematic and the objects were not, that way it's just the object flailing around and the player movement is mainly controlled by code perhaps gravity. That's just my guess though!
Then when you throw the object you could apply force to it and remove the condition that makes it be a max distance from the hand child object.
That's the basics of how I would try to set it up not sure how much it will help you specifically since I never actually tried this is in any of my games.
So your problem isn't how to pick up items right it's how to make you hold them realistically? Hopefully my answer isn't way off topic haha.
What I'm trying to do is exactly like in Amnesia. No hand and the object floating in front of you while holding it.
And yes thank you after posting this question I tried a similar way as you said and having a pickup script on every pickupable object and its working so far but I'm also parenting the object just for testing purposes cause everyone keeps saying how its bad but I'm not noticing anything. And I used the $$anonymous$$oveTowards to move the picked up object to the transform and from then on moving the transform closer and farther with the scroll wheel to control the held object, and added force to it to throw it with right click.
I had a problem with jumping with physics cause it reaches the peak too slow and falls too slow but i solved it with high jump force and slightly lesser fall force in the opposite direction.
Now only thing remaining is that I can't throw the object by just swinging and then releasing, it falls straight down. :S
Sounds like a really cool game! You might have to artificially add force to the object to throw it. Or maybe you could add some acceleration to the child object it is attached to and then transfer that momentum into the picked up object rigid body immediately after you drop it. So if you could somehow make the child object move realistically like a hand that was throwing and transfer that force or momentum to the picked up object might get most realistic result. And then you can set the child hand object back to the original position after every throw.
Never tried it so not sure if that would work but makes sense in theory.
Yeah that's what I'm thinking of doing but don't posses the knowledge to do it yet. xD
Anyway thanks, I just made this basic rigidbody character controller to glimpse into a future game we'll be making, and see if I can do it. Right now we're finishing up our first game, a lunar lander style game. xD
Its not much, and based on the $$anonymous$$ine Lander unity tutorial, but added a lot more stuff and over 60 levels so all that's left is polishing and getting the 100$ needed to submit to Greenlight. Cause we're working on a 0$ budget. xD
Can't wait to get my hands on Unity Pro one day. xD
Your answer
Follow this Question
Related Questions
Distance From & CrossHair 0 Answers
Ragdoll only physics grab object 0 Answers
Method for grabbing rigidbody 2 Answers
Adding Rigidbody to an Object on Collision by Raycast? 1 Answer
0 Understanding of raycast2D commands 2 Answers