What is the best way to Push or Pull an Object?

Hello,

I am currently trying to get a working script for pulling and pushing objects in a 2D game.I have heard there are several ways to do this. At first I was using the script found in the documentation, but I realized it only works for pushing objects and not pulling towards you. Then I came across making your character the parent of your game object. The following is my script atm.

function OnControllerColliderHit (hit : ControllerColliderHit) {

var body : Transform = hit.transform;

if(body.gameObject.name == "Crate"){
      if (Input.GetButton("Action")){
      body.transform.parent = transform;
      body.rigidbody.isKinematic = true;
       }
      else {
      body.transform.parent = null;
      body.rigidbody.isKinematic = false;
      }
}
}

I am having problems using this though. First of all, If I collide with the gameobject and then press the action button, (Hence my velocity is zero), my character will not be able to move at all. On the other hand if I hold the action button and collide with the gameobject at a velocity it will start moving with my character. Second, If I jump on my gameobject and click the action button, it will become the child of my character following his movements. How can I avoid this from happening since the character should only be pulling/pushing if he is on the left or right of the gameobject and not on top of it.

I have also read that you can do this by creating a joint that will attach the game object and the character together. I am wondering though if the joint method could be used if I am not using rigidbody as my controller. Currently I am using The platform input controller script along with the character motor.

Any Help is appreciated.
Thank you very much.

Two parts: how to know what to pull, and then pulling it. There might be a few ways to say “I want to pull this.” For example, clicking on a crate. But, to go with what you have, bumping a crate selects it. The standard trick is to have a variable, maybe thingToPull which will be set on a bump, and will be nothing (null) if we aren’t pulling anything.

Then, once we have thingToPull (no matter how we got it,) we can have Update move it around.

I’m using C#. Finding out what they want to pull, using your first script modified:

Transform thingToPull; // null if nothing, else a link to some pullable crate

void OnControllerColliderHit(ControllerColliderHit hit) {
  if(hit.transform.name=="Crate") // NOTE: tags checking may be better
    thingToPull = hit.transform;
}

Then the player’s Update can drag it towards you. Notice I’m being cute here in a few ways. You lose it if it gets beyond 50 meters; it stops when it gets within 3 meters, and it gets pulled harder as you get further away.

if(thingToPull!=null) {
  Vector3 D = transform.position - thingToPull; // line from crate to player
  float dist = D.magnitude;
  Vector3 pullDir = D.normalized; // short blue arrow from crate to player

  if(dist>50) thingToPull=null; // lose tracking if too far
  else if(dist>3) { // don't pull if too close

    // this is the same math to apply fake gravity. 10 = normal gravity
    float pullF = 10;

    // for fun, pull a little bit more if further away:
    // (so, random, optional junk):
    float pullForDist = (dist-3)/2.0f;
    if(pullForDist>20) pullForDist=20;
    pullF += pullForDist;

    // Now apply to pull force, using standard meters/sec converted
    //    into meters/frame:
    thingToPull.rigidbody.velocity += pullDir*(pullF * Time.deltaTime);
  }
}

At the end, it just adds to velocity. Lots of guys prefer an AddForce. 10 might be a little high for the pull, but it helps to use numbers that are too big when testing, so you can see it’s working.