Carrying object loses its collision

In my game I have a hallway my partner made. Inside of it I have my player (first-person camera) and a box. Collision works great between all of these things. I have this script I made that I use to pick up an object (in this case the box):

using UnityEngine;
using System.Collections;

public class ReticleInteraction : MonoBehaviour {


    Camera camera;
    public GameObject hitGameObject;

    public bool haveItem;


    void Start ()
    {
        camera = GetComponent<Camera>();
        haveItem = false;
    }

    void Update ()
    {
        Vector3 screenCenter = camera.ScreenToWorldPoint(new Vector3(Screen.width/2, Screen.height/2, 2.5f));

        Ray ray = camera.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 4f))
        {
            if (hit.collider.tag == "Interactive")
            {
                hitGameObject = hit.collider.gameObject;
                if (Input.GetMouseButtonDown(0))
                {
                    if (!haveItem)
                    {
                        haveItem = true;
                    }
                    else
                    {
                        haveItem = false;
                    }
                }
            }
        }

        if (haveItem)
        {
            hitGameObject.transform.position = screenCenter;
        }
    }
}

The problem is that while I’m carrying the box it moves through the walls. Why is that? Is it my script?

Additionally, how is my script so far? Is it efficient enough for what I am trying to do? I know it could still use some work. Eventually plan to add the ability to rotate the object left/right while holding it. I know it could use some work as it stands now. I’m still kind of new to C# (used to do Actionscript3) so there is still so much for me to learn about coding efficiently in this language.

Your box is moving through objects because you’re not moving it using physics, you are manipulating its position directly.
There’s an example script in the Standard Assets package called DragRigidbody that has the fundamentals of moving and object around with physics.

1 Like

If you are “picking it up” by re-parenting itself to your player, then I’m guessing you are moving by modifying transform.position directly? That’s probably what’s causing it to move through walls. Unfortunately, I don’t have any ideas on how to stop that :), but at least it’s a starting point for you.

As for your script, some suggestions:

You should cache screenCenter instead of calculating it every frame. (I’m assuming it never changes).

To better scale your “interactivity”, i.e. what if you wanted to press a button instead of picking an object up?

  • Make an Interaction script, which can be a base class for all interactions.
  • Instead of the string conditional you have, you can do a GetComponent(), with an virtual method such as

public virtual void Interact(Player requester){}


- If you had a , PickUpInteraction : Interaction. You could override the virtual function with:
- ```csharp
public override void Interact(Player requester)
[*]{
  if(Input.GetMouseButtonDown(0))
  {
    //Parent the gameobject this is attached to, to the player
    //Let the player know he now has an item
  }
}

You could then rename your current class to , InteractionHandler or something similar, so it would look like this:

using UnityEngine;
using System.Collections;
public class InteractionHandler : MonoBehaviour {
    Camera camera;
    void Start ()
    {
        camera = GetComponent<Camera>();
    }
    void Update ()
    {
        Ray ray = camera.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 4f))
        {

           if(hit.collider != null)
            {
                  Interaction currentInteraction = hit.collider.GetComponent<Interaction>();

               if(currentInteraction != null)
               {
                currentInteraction.Interact(player);//Not sure where you //would get a reference to player :)
                }
         
            }
 
    }
}

Just something to think about!

1 Like

You’re setting the box’s position manually every single frame, to be positioned exactly in the center of your camera- the physics engine isn’t going to be able to fight this. If you want to be able to “hold” something, but you still want it to connect with other objects, then you need to hold it in place with a “force” of some kind, like a strong gravitational pull. Then, as long as the collisions aren’t strong enough to knock it out of range of that “force”, then it’ll just bounce around a little and get pulled back in. This is far more complicated.

As @ThermalFusion mentioned, the DragRigidbody package is an excellent starting point for this.

1 Like

Thank you for the lengthy feedback I now have lots to look into and consider :slight_smile:

One thing I keep hearing on other posts is to cache something. It kind of confuses me. I kind of understand it… Like I’m assuming it means to store it in some kind of variable outside of the Update. But I don’t know how I would then call that single variable within Update as I need that screenCenter input every frame… Could you possibly give me a pseudo code example?

Your camera variable, for instance, is a component that you cache in the Start function so you don’t need to keep retrieving it- all you have to do to cache something is make a new variable at the class scope rather than the function scope and only assign it once (or only when it changes), then you can use it anywhere within the class (and outside of it, if it’s public) without having to recreate it every update. I don’t think caching the Vector3 for “center of the screen” is really going to make any difference though- you can probably create like half a billion Vector3s before it starts slowing anything down. Unnecessarily instantiating dozens of prefabs, doing FindGameObjectByName/Tag, and retrieving components every frame are the big ones to avoid when at all possible.

1 Like

So what I meant was the actual calculating on the center of the screen. Screen.width and screen.height will never change and neither will your z value.
It’s a completely minor change and won’t affect performance, unless you have millions of calculations involving it.

i.e.

private Vector3 actualScreenCenter;

void Start()
{
actualScreenCenter = new Vector3(Screen.width/2, Screen.height/2, 2.5f);
}

Then in your update function:

void Update()
{
  Vector3 screenCenter = camera.ScreenToWorldPoint(actualScreenCenter);
}

So caching is basically: this value never changes, so just calculate it once, and store it in a variable.

1 Like

This is very useful to know. Thank you!

Oh I understand now. Sometimes I’m on the verge of getting things to “click” in my mind on how things work and a piece of pseudo code usually helps fill in the missing gap. Thank you :slight_smile:

Out of pure curiosity for learning purposes which is more intensive: finding a game object by name/tag or retrieving a component?

With something I’m doing right now I will only be calling it once and not every frame so it’s no big deal, but it got me wondering which of the two methods is heavier on the on the system (probably a better way to phrase that but you know what I mean)?

Finding an object by name/tag is pretty heavy- heavy enough in larger projects that I try to avoid doing it at all if at all possible. That said, the actual impact depends on the number of objects currently in the scene. It might not be that much worse than a GetComponent call in a small project, but the impact increases as the size of the project increases. More importantly, there’s almost always a way to avoid doing it, and those ways tend to be just better programming/management in general.

Getting a component should only actually become a problem if you’re doing it every single frame, multiple times a frame, like in an Update. That’s what was so dangerous (and continues to be dangerous) about the shortcut members they made for “.renderer” and “.transform”, etc… People use them assuming they’re just normal members, but they’re actually calling GetComponent internally, so if you put them in Update you’re doing it every frame. Removing those shortcuts, as they’re in the process of doing, will make it so that it’s more obvious what’s going on and make it clear that you need to cache your references to them.

Anyways, you shouldn’t go out of your way to avoid GetComponent calls, you should just avoid using the same GetComponent call repeatedly in the same script. If you need to use it two or more times, then cache it (or, in the case that the component is for a “target” that changes, at least save it to a temporary variable and re-use that reference until the current function is finished).

1 Like

I rewrote my script that had a raycast from the center of the screen to interact with things. I made it so that the raycast only goes out when the mouse button is clicked down rather than continuously. I wanted to use the .tag to check if the raycast hits certain types of objects such as objects you can pick up, doors you can open, buttons you can push, etc. and then handle the objects accordingly depending on what they are. Would using the .tag to check the tag of the object the raycast hit be too much of a problem?

The game is a kind of puzzle game where you solve the puzzle in the room and then move on to the next room. The room will be filled with quite a bit of different types of objects the player can interact with.

Checking the tag directly is fine (not using “FindGameObjectsWithTag” doesn’t mean “don’t use tags” ^_~), but a better way is to put the items on the same layer and then use a LayerMask in the raycast to only detect objects in that layer. That way, you can use the “tags” to describe which specific types of items they are, instead of all of them having the same “item” tag to check the RaycastHit with.

Edit: Here’s an example of creating a layer mask in real time, rather than building one and setting it up beforehand.

if (Physics.Raycast(Camera.main.ScreenPointToRay(location), out hit, Mathf.Infinity, 1 << LayerMask.NameToLayer("Terrain")))

Just for a reference.

1 Like

Oh haha I understand now :stuck_out_tongue: Thanks for the tip. I really appreciate the example code as well. Your suggestions with layers is a much better way to go about it. I’ll give it a go. Thanks again :slight_smile:

I already posted a solution for exactly this though. As long as the object you’re raycasting against as an Interaction component, you can override the functionality that is applied through polymorphism.

Sorry if I’m bumping an old thread with this but it relates to your advice about caching GetComponent calls if I will be calling them multiple times. What about times when you pass an argument to a function and then need to use that new argument to use GetComponent. Probably explained that bad…here is the code related to what I am talking about:

void carry(GameObject pickObj)
    {
        pickObj.transform.position = Vector3.Lerp (pickObj.transform.position, camera.transform.position + camera.transform.forward * distance, Time.deltaTime * smooth);
        if (PlayerController.rightClick)
        {
            pickObj.gameObject.GetComponent<Rigidbody>().freezeRotation = false;
            mY = Input.GetAxis("Mouse Y") * Time.deltaTime * rotateSpeed;
            mX = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;
            pickObj.transform.Rotate (mY, mX, 0);
        }
        else
        {
            pickObj.gameObject.GetComponent<Rigidbody>().freezeRotation = true;
        }
    }

I am passing a GameObject called carriedObject to the carry function and it stores this variable into a new gameObject called pickObj. Since pickObj will change every time the player grabs a new object is it even possible to cache pickObj’s GetComponent?

Sorry if I am not explaining this clearly enough. Let me know if you need me to better explain it. Or if you need me to post more code (the whole script so far is 91 lines so I didn’t want to post the whole thing).

It’s not practical or that useful to cache it at the class level in that case (this is the same as with objects you collide with in the collision event functions), but if you’re going to be calling the same component on the same object multiple times in sequence, you can save it as a temporary local variable and use that to speed up subsequent accesses a bit. In this case, like so:

void carry(GameObject pickObj)
{
   Rigidbody pickObjRigidbody = pickObj.GetComponent<Rigidbody>();
   Transform pickObjTransform = pickObj.transform;
   Transform cameraTransform = camera.transform;

   pickObjTransform.position = Vector3.Lerp (pickObjTransform.position, cameraTransform.position + cameraTransform.forward * distance, Time.deltaTime * smooth);
   if (PlayerController.rightClick)
   {
      pickObjRigidbody.freezeRotation = false;
      mY = Input.GetAxis("Mouse Y") * Time.deltaTime * rotateSpeed;
      mX = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;
      pickObjTransform.Rotate (mY, mX, 0);
   }
   else
   {
      pickObjRigidbody.freezeRotation = true;
   }
}

But keep in mind that for functions that you only call occasionally, it isn’t as important to save a few GetComponent calls like this as it would be if you were doing something every frame, or a dozen times in a frame. Still, efficiency doesn’t hurt.

1 Like

Thanks for the tip I appreciate it :slight_smile: