Search Unity

Gravity gun!

Discussion in 'Scripting' started by Theformand, Jan 3, 2010.

  1. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Hey folks!

    Im trying to figure out a way to make a quick little game, which sole purpose is to try and emulate the Half-Life Gravity Gun. Or something to that effect.

    Buuuuuut but but but, as the newbie I am, im not that far into scripting yet. Therefore I figured i would make a post here asking you awesome scripter people for advice.

    So far im just building a proof-of-concept simple level, with nothing but primitives, to get the gameplay working. after that Ill focus on getting the looks right.

    So, the general idea is:

    Click mouse : Grab an object that youre pointing at. If far away, drag it towards you. (To determine where im pointing at, should I create a vector parrallel to the optic axis?)

    Hold down mouse: Trigger a timer function which counts upwards and returns forceValue (int). Object position is fixed (jittery behaviour comes later for the eyecandiness) at a point just outside the tip of the gun.

    Release mouse: Addforce *forceValue to grabbed object, which is then thrown in the direction you're looking at.

    Let rigidbodies do the rest, and hours of endless fun ensues.

    Does anyone have a clue as to how I should start scripting the behaviour of this gun?

    Ive already got the FPS functionality from the FPS tutorial (including a nice little crosshair), and I'll sort gun model and animations etc when Ive got the functionality down.

    Any input will be appreciated :)

    EDIT: I may have come off like I wanted someone to basically write the code for me, thats not the case. The general principle of a gun like this, and maybe snippets demonstrating certain behaviour :)
    Thanks

    -Theformand
     
  2. asgeir

    asgeir

    Joined:
    Nov 13, 2009
    Posts:
    7
    If I had to venture a guess it would go something like this:

    To find the target object you could do a raycast from the camera's position, transformed by the camera's transform. http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html

    Then you could disable its Rigidbody, if you want to simplify how it moves towards you, and then simply give it a target position in world space and use a component to smoothly animate it towards the target.

    Then re-enable the rigidbody and add a force to it http://unity3d.com/support/documentation/ScriptReference/Rigidbody.AddForce.html using the camera forward vector transformed to world space and scaled with your forceValue.
     
  3. magwo

    magwo

    Joined:
    May 20, 2009
    Posts:
    402
    Disabling and enabling rigid bodies will result in a lot of "energy" explosions due to large intersections with other bodies when enabling occurs. I'd rather use phsyics all the way. Every frame you calculate a point in space, which is camerapos + cameraforward * desireddistance. And just use a PD controller to set the force on the rigidbody being picked up. So the distance from desired position is the proportinal part, and velocity towards the point is the derivative part.. this will prevent endless oscillation around the pickup point.


    Edit: Actually I'll revise that.. you'll also need at least proportional force with regards to "transversal" (or whatever it's called) velocity to prevent orbiting behaviour.
     
  4. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Whoa, I have no idea what you just said there. Im not big on physics, atleast not in this regard. I only know stuff about physics of light rays etc...

    What do you mean with orbital behaviour? is this a problem regarding the position of the rigidbody after pickup?

    I really appreciate the input, both of you.
     
  5. magwo

    magwo

    Joined:
    May 20, 2009
    Posts:
    402
    Yes well, my proposed solution involves physics-based controlling of the rigid body. It would look somewhat programmed, but still be truly physics-based.

    With transversal velocity I mean basically angular velocity relative to the desired position.

    I suggest you start with controlling the position of the body, then look at ways to make it fixed rotationally, relative to the camera.
     
  6. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    So, Ive successfully implemented Raycast now, and by printing out the value of a boolean, I can see that it is working.

    Next step is to indentify the object which is intersecting the Raycast, so that I can mess with the transform of this object.

    For some reason, I cant get RaycastHit working. Probably because I dont know exactly how to read a scripting reference yet :p

    Heres the little script ive got so far.

    Code (csharp):
    1. var objectfound: boolean = false;
    2.  
    3.  
    4. function Update () {
    5.     var fwd = transform.TransformDirection (Vector3.forward);
    6.     if (Physics.Raycast (transform.position, fwd, 10)) {
    7.         objectfound = true;
    8.         print (objectfound);
    9.         if (Input.GetButtonDown( "Fire1"))
    10.     {
    11.     //Mess with the transform of the found object.
    12.     //How do I tag the object intersecting the Raycast with an identity
    13.     //so that I can manipulate its transform?
    14.     }
    15.    
    16.     }
    17.     objectfound = false;   
    18.    
    19.    
    20. }

    Btw Magwo, is your game demo down atm? I love your design, hope the web playable comes up again at some point :)
     
  7. asgeir

    asgeir

    Joined:
    Nov 13, 2009
    Posts:
    7
    Use the overloaded raycast method that has an out parameter that is of type RaycastHit. The second one down in the script reference.
     
  8. bappy

    bappy

    Joined:
    Dec 19, 2009
    Posts:
    8
    to optimize your code i suggest you to raycast only if the fire event is start and not every frame...

    function Update ()
    {
    if (Input.GetButtonDown( "Fire1"))
    {
    //Mess with the transform of the found object.
    //How do I tag the object intersecting the Raycast with an identity
    //so that I can manipulate its transform?
    var fwd = transform.TransformDirection (Vector3.forward);
    RaycastHit hitinfo
    hitinfo = Physics.Raycast (transform.position, fwd, 10))
    if(hitinfo != null)
    {
    objectfound = true;
    print (objectfound + hitinfo.name);

    }
    else
    {
    objectfound = false;
    }
    }
    }

    In hitinfo you have the physics (rigidbody) of the your raycastobject

    sorry for the pseudo javascript code but i m a c# dev...
     
  9. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Im trying to get the overloaded version that has an out parameter to work, but my noobiness is getting the best of me.

    Im constantly getting errors because I cant figure out the syntax. The code im trying with is:





    Code (csharp):
    1.  
    2. function Update ()
    3. {
    4. if (Input.GetButtonDown( "Fire1"))
    5.     {
    6.         var fwd = transform.TransformDirection (Vector3.forward);
    7.        
    8.         hitinfo = Physics.Raycast (transform.position, fwd, 10);
    9.         if(hitinfo != null)
    10.             {
    11.            
    12.             print (hitinfo.transform);
    13.  
    14.             }
    15.         else
    16.         {
    17.        
    18.         }
    19.     }
    20. }
    21.  
    with this error:
    Code (csharp):
    1. Assets/RaycastScript1.js(13,40): BCE0019: 'transform' is not a member of 'boolean'.
    line 13 is the print statement.
    I removed the objectfound variable which used to
    be a boolean, but it still gives me this strange error. I also removed the line "RaycastHit hitinfo" from your code because I didnt understand the purpose of it?

    I can hear distant laughs, please forgive my starter level :)
     
  10. Raziaar

    Raziaar

    Joined:
    Dec 20, 2009
    Posts:
    82
    This is in C#, but this is how I'm doing my raycasting. Though take note that I'm doing the raycasting based from the camera screen coordinates of my mouse cursor.

    Code (csharp):
    1.  
    2. if (Input.GetButtonDown("Fire1"))
    3.         {
    4.             RaycastHit hit;
    5.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    6.  
    7.             if (Physics.Raycast(ray, out hit))
    8.             {
    9.                // Do stuff. Like instantiate an object at hit.point
    10.             }
    11.         }
    12.  

    Notice that the RaycastHit is used as an 'out' parameter, meaning that it does not have to be initialized before being sent into the Raycast method, because it is initialized within that method and the data then altered to be used later.

    I don't know if any of that applies for javascript or not.

    Also take note that I am using the third overloaded method. You can use any of the other ones for yours.



    To me it looks like your problem is that you are trying to assign the result of the Raycast into a hitinfo variable. This is bad. Raycast is a method that only returns a bool, either true or false. Notice how I use this fact in my IF statement to check if the ray hit something.
     
  11. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    A tiny goal has been reached:

    I now succesfully cast a ray emitting from the center of the screen, and if that ray collides with a rigidboy, the position of this rigidbody.transform is set to the position of an empty gameobject (pickuppoint) at the tip of the gun.

    But thats however, only on mouseclick. This means that the rigidbody drops back to the ground immediately.
    I still need to figure out how to make the rigidbody stay until mousebutton is no longer down.

    Also, obviously I need to find a way to actually MOVE the rigidbody towards the pickuppoint instead of just setting the position. Thanks so much for all your help so far.
    What is a PD controller?
     
  12. bappy

    bappy

    Joined:
    Dec 19, 2009
    Posts:
    8
    oups , sorry for this line "hitinfo = Physics.Raycast (transform.position, fwd, 10))
    "
    i wasnt in front of my code when i respond this and didn t remember that hitinfo was an out parameter :(

    to resolve your problem, you could use this pseudo algorithm :

    - add a global rigidbody variable to store the raycast hit object initialized to null. let s call it "movingobject".

    1 : On LeftmouseButtonDown function:

    if( movingobject ==null)
    -> do your raycast code and assign your rigidbody found to movingobject (movingobject = hitinfo.rigidbody)

    if (movingobject!=null)
    do nothing, we always have an object in the gravitygun

    2 : on update function :
    if(movingobject!=null)
    ->we have an object and need to move it in front of the gravitygun
    maybe something like this can do the tricks (take from the scriptreference doc)but i m not sure:
    "var speed = Vector3 (3, 3, 3);
    movingobject.MovePosition(transform.position + speed * Time.deltaTime);"

    if movingobject is already at the good position, accumulate your force...

    3 : on LeftmouseButtonUp function
    if(movingobject!=null)
    -> throw your object at the accumulate force
    -> then don t forget to set movingobject to null to reactivate the process.
    to throw your object you can look in the fps tutorial when you shoot the rocket...

    hope this will help
     
  13. asgeir

    asgeir

    Joined:
    Nov 13, 2009
    Posts:
    7
    Here is a crude version, in Boo, that I put together in about two hours:

    Code (csharp):
    1. import UnityEngine
    2.  
    3. class GravityGun(MonoBehaviour):
    4.     enum GravityGunState:
    5.         Idle
    6.         Attracting
    7.         Holding
    8.  
    9.     public attractSpeed = 40.0
    10.  
    11.     public repelSpeed = 50.0
    12.  
    13.     public effectiveRange = 30.0
    14.  
    15.     public targetLayerMask as LayerMask = -1
    16.  
    17.     public holdDistance = 4.0
    18.  
    19.     _camera as Camera
    20.  
    21.     _target as Rigidbody
    22.  
    23.     _oldTargetGravity as bool
    24.  
    25.     _state = GravityGunState.Idle
    26.  
    27.     def Start():
    28.         _camera = GetComponentInChildren(Camera)
    29.  
    30.     def FreeTarget():
    31.         if _target:
    32.             _target.freezeRotation = false
    33.             _target.useGravity = _oldTargetGravity
    34.  
    35.     def OnIdle():
    36.         if Input.GetButton('Fire1'):
    37.             hit as RaycastHit
    38.             if Physics.Raycast(_camera.transform.position,
    39.                     _camera.transform.forward, hit, effectiveRange,
    40.                     targetLayerMask):
    41.                 if hit.rigidbody:
    42.                     _state = GravityGunState.Attracting
    43.  
    44.                     _target = hit.rigidbody
    45.                     _oldTargetGravity = _target.useGravity
    46.  
    47.                     _target.useGravity = false
    48.                     _target.freezeRotation = true
    49.  
    50.     def OnAttracting():
    51.         if not Input.GetButton('Fire1'):
    52.             _state = GravityGunState.Idle
    53.  
    54.             FreeTarget()
    55.             _target = null
    56.  
    57.             return
    58.  
    59.         _target.rotation = _camera.transform.rotation
    60.  
    61.         targetPosition = (_camera.transform.position +
    62.                 _camera.transform.forward * holdDistance)
    63.         _target.velocity = -_camera.transform.forward * attractSpeed
    64.  
    65.         offset = targetPosition - _target.position
    66.         if offset.sqrMagnitude <= (holdDistance * holdDistance):
    67.             _state = GravityGunState.Holding
    68.  
    69.     def OnHolding():
    70.         if not Input.GetButton('Fire1'):
    71.             _state = GravityGunState.Idle
    72.  
    73.             FreeTarget()
    74.             _target.velocity = _camera.transform.forward * repelSpeed
    75.             _target = null
    76.  
    77.             return
    78.  
    79.         _target.rotation = _camera.transform.rotation
    80.  
    81.         targetPosition = (_camera.transform.position +
    82.                 _camera.transform.forward * holdDistance)
    83.         _target.MovePosition(targetPosition)
    84.  
    85.     def FixedUpdate():
    86.         if _state == GravityGunState.Idle:
    87.             OnIdle()
    88.         elif _state == GravityGunState.Attracting:
    89.             OnAttracting()
    90.         elif _state == GravityGunState.Holding:
    91.             OnHolding()
    92.  
    93.  
    It's pretty unrefined and doesn't handle the target clipping into things or its interation with other objects in the scene too well.
     
  14. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Thank you very much asgeir, that is a good foundation to build upon. Yes it is a little crude, but thats fixable im sure. It does act a little weird with other geometry, but desribes the behaviour im after pretty good. For example, with a working code I just figured out that it might be a good idea to lower the alpha of the rigidbody youve picked up, since its hard to aim with a giant box obstructing your wiew...

    My next job is to try and convert it to javascript, since I cant code in Boo. Python is from way before I even started looking at C++ :p

    Thanks alot, this helped me along a good bit
     
  15. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Okay, so now ive tried to convert your Boo script into Java, which sort of went okay. Its not quite working and I think I know why. Have a look at my script:

    Code (csharp):
    1. enum GravityGunState{
    2. Idle,
    3. Attracting,
    4. Holding
    5. }
    6. var attractSpeed = 40.0;
    7. var repelSpeed = 50.0;
    8. var effectiveRange = 30.0;
    9. var targetLayerMask : LayerMask = -1;
    10. var holdDistance= 4.0;
    11. private var _camera: Camera;
    12. private var _target: Rigidbody;
    13. private var _oldTargetGravity: boolean;
    14. private var _state = GravityGunState.Idle;
    15.  
    16. function Start()
    17. {
    18. _camera = GetComponentInChildren(Camera);
    19. }
    20. function FreeTarget()
    21. {
    22.     if(_target)
    23.     {
    24.     _target.freezeRotation = false;
    25.     _target.useGravity = _oldTargetGravity;
    26.     }
    27. }
    28. function OnIdle()
    29. {
    30.     if(Input.GetButton("Fire1"))
    31.     {
    32.     var hit: RaycastHit;
    33.         if(Physics.Raycast(_camera.transform.position, _camera.transform.forward, hit, effectiveRange, targetLayerMask))
    34.         {
    35.             if(hit.rigidbody)
    36.             {
    37.             _state = GravityGunState.Attracting;
    38.             _target = hit.rigidbody;
    39.             _oldTargetGravity = _target.useGravity;
    40.             _target.freezeRotation = true;
    41.             }
    42.         }
    43.     }
    44. }
    45.  
    46. function OnAttracting()
    47. {
    48.     if (Input.GetButtonDown == null)
    49.     {
    50.         _state = GravityGunState.Idle;
    51.         FreeTarget();
    52.         _target = null;
    53.        
    54.         return;
    55.        
    56.         }
    57.         _target.rotation = _camera.transform.rotation;
    58.         targetPosition = (_camera.transform.position + _camera.transform.forward * holdDistance);
    59.         _target.velocity = -_camera.transform.forward * attractSpeed;
    60.        
    61.         offset = targetPosition - _target.position;
    62.         if (offset.sqrMagnitude <= (holdDistance * holdDistance))
    63.         {
    64.         _state = GravityGunState.Holding;
    65.         }
    66.     }
    67. function OnHolding()
    68. {
    69.     if (Input.GetButtonDown == null)
    70.     {
    71.     _state = GravityGunState.Idle;
    72.     FreeTarget();
    73.     _target.velocity = _camera.transform.forward * repelSpeed;
    74.     _target = null;
    75.    
    76.     return;
    77.     }
    78.     _target.rotation = _camera.transform.rotation;
    79.     targetPosition = (_camera.transform.position + _camera.transform.forward * holdDistance);
    80.     _target.MovePosition (targetPosition);
    81. }
    82.  
    83.  
    84.  
    85. function FixedUpdate ()
    86. {
    87. if (_state == GravityGunState.Idle)
    88.     {
    89.     OnIdle();
    90.     }
    91. else if (_state == GravityGunState.Attracting)
    92.     {
    93.     OnAttracting();
    94.     }  
    95.     else if (_state == GravityGunState.Holding)
    96.     {
    97.     OnHolding();
    98.     }
    99. }
    The behaviour is this: You click to pick up an object, but it does not fire upon release. I think the problem is the way I interpreted the "if not" statements in the boo script. I translated
    Code (csharp):
    1.  if not Input.GetButton('Fire1'):
    into:

    Code (csharp):
    1. if (Input.GetButtonDown == null)
    Which im not quite sure serves the same purpose. But im too tired to figure out the correct way of using an if statement like youve done. Anyone else able to form an "if not" statement in Javascript?

    And for some reason, whenever I grab an object, it slowly "slides" downwards. Im not sure my if-statements are causing this, but they might.

    if (time.Denmark >= late)
    {
    newbie.transform.rotate = sleep.Position;
    }

    zzZZzzz
     
  16. Raziaar

    Raziaar

    Joined:
    Dec 20, 2009
    Posts:
    82
    GetButtonDown returns true or false.

    I don't know boo, but I'm guessing it would be translated like this.

    Code (csharp):
    1.  if not Input.GetButton('Fire1'):
    into

    Code (csharp):
    1. if (!Input.GetButton("Fire1")
    Which basically says... do something if Fire1 isn't pressed.

    I didn't look at his script, I'm simply trying to answer your question regarding your conversion. When you're just using GetButtonDown == null, that doesn't seem to make sense to me because GetButtonDown is a method and requires a parameter, and equating a bool(the return value of GetButtonDown) to a null value doesn't make sense.
     
  17. asgeir

    asgeir

    Joined:
    Nov 13, 2009
    Posts:
    7
    You are forgetting _target.useGravity = false in OnIdle->if hit.rigidbody That is why you get the sliding behaviour.

    You should probably be using: if (!Input.GetButton("Fire1")) {}
     
  18. username85

    username85

    Joined:
    Jan 6, 2010
    Posts:
    17
    Here is my first attempt to implement what you described. Please note this is my third day using Unity, so it might not be the best way to implement it. The one sure thing is that it works. I encourage suggesting any adjustments/improvements by more experienced people.

    You have to attach this script to your pointing object (e.g. camera or pointing gun's tip). Adjust the variables in the editor. Then you play like this: you go towards a Rigidbody and click it once when pointing at it from a close distance (Catch Range). This will catch the object and move it in front of you (Hold Distance). Then you click and hold the mouse button to charge the force. The less you hold the button the less force you apply down to (Min Force), and the more you hold it the more force you apply up to (Max Force). You release the mouse button to throw the object with the current force.

    I have used print statements in the code for debugging so I can see the force value while playing, you should remove them.

    Code (csharp):
    1.  
    2. var catchRange = 30.0;
    3. var holdDistance = 4.0;
    4. var minForce = 1000;
    5. var maxForce = 10000;
    6. var forceChargePerSec = 3000;
    7. var layerMask : LayerMask = -1;
    8.  
    9. enum GravityGunState { Free, Catch, Occupied, Charge, Release};
    10. private var gravityGunState : GravityGunState = 0;
    11. private var rigid : Rigidbody = null;
    12. private var currentForce = minForce;
    13.  
    14. function FixedUpdate () {
    15.     if(gravityGunState == GravityGunState.Free) {
    16.         if(Input.GetButton("Fire1")) {
    17.             var hit : RaycastHit;
    18.             if(Physics.Raycast(transform.position, transform.forward, hit, catchRange, layerMask)) {
    19.                 if(hit.rigidbody) {
    20.                     rigid = hit.rigidbody;
    21.                     gravityGunState = GravityGunState.Catch;
    22.                    
    23.                     // for debuging, remove it
    24.                     print("force: " + currentForce);
    25.                 }
    26.             }
    27.         }
    28.     }
    29.     else if(gravityGunState == GravityGunState.Catch) {
    30.         rigid.MovePosition(transform.position + transform.forward * holdDistance);
    31.         if(!Input.GetButton("Fire1"))
    32.             gravityGunState = GravityGunState.Occupied;
    33.     }
    34.     else if(gravityGunState == GravityGunState.Occupied) {
    35.         rigid.MovePosition(transform.position + transform.forward * holdDistance);
    36.         if(Input.GetButton("Fire1"))
    37.             gravityGunState = GravityGunState.Charge;
    38.     }
    39.     else if(gravityGunState == GravityGunState.Charge) {
    40.         rigid.MovePosition(transform.position + transform.forward * holdDistance);
    41.         if(currentForce < maxForce) {
    42.             currentForce += forceChargePerSec * Time.deltaTime;
    43.         }
    44.         else {
    45.             currentForce = maxForce;
    46.         }
    47.         if(!Input.GetButton("Fire1"))
    48.             gravityGunState = GravityGunState.Release;
    49.            
    50.         // for debuging, remove it
    51.         print("force: " + currentForce);
    52.     }
    53.     else if(gravityGunState == GravityGunState.Release) {
    54.         rigid.AddForce(transform.forward * currentForce);
    55.         currentForce = minForce;
    56.         gravityGunState = GravityGunState.Free;
    57.        
    58.         // for debuging, remove it
    59.         print("");
    60.     }
    61. }
    62.  
    63. @script ExecuteInEditMode()
    64.  
     
  19. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Wow, I must have been really tired last night to miss that !if thing :)

    I cant believe the amount of help im getting in this forum, thanks so much guys, now I can focus on other fun aspects of the game. Getting these scripts to work just as i want them to and general game design :)

    Thanks a bunch
     
  20. Legendary

    Legendary

    Joined:
    Oct 24, 2010
    Posts:
    4
    Awesome script username85, but I can't really getting it to work.

    I added the script to my FPS Controllers Main Camera, and I have a few objects in my scene with Mesh Colliders+Rigidbodies. Fire1 = Mouse Button 1, right? I have tried to increase the catch range to 4000 but I still can't pick up my objects even if I center the object at the screen..

    Have I forgotten about anything?
     
  21. Strider Studios

    Strider Studios

    Joined:
    Nov 19, 2010
    Posts:
    2
    I want to pick up only specific objects in the environment. I am using all of the objects in the game as rigidbodies either kinematic or normal. How would I do this "I am currently a noob at scripting"
     
  22. Strider Studios

    Strider Studios

    Joined:
    Nov 19, 2010
    Posts:
    2
    I have a weapon system in my game. Can I simply put this script onto a weapon so that it can only be used with that particular weapon?
     
  23. Shaemon

    Shaemon

    Joined:
    Jan 3, 2011
    Posts:
    2
    I have a problem. When I pick something up and throw it it works fine. But the object slowly falls downward while I am holding it.
    Do you know how I could fix this?
    Btw I am making a zombie game where you can pick up objects an throw them as weapons or making blockades.
     
  24. almat96

    almat96

    Joined:
    Apr 6, 2011
    Posts:
    1
    for some reason you cannot pick up rigid bodies that are touching the terrain.
     
  25. uvavoo

    uvavoo

    Joined:
    Oct 15, 2007
    Posts:
    60
    I have been experimenting with this script. Thanks to the author.
    I can answer a couple of the latest questions.
    @Strider Studio
    "I want to pick up only specific objects in the environment."
    Create a new layer, call it something like GravityGunLayer. Any object you wish to pick up, simply give it this layer.
    In the Gravity Gun script you will see the entry 'Layer Mask" , Select 'GravityGunLayer' from the scroll down list. Your gun will only pick up objects with this layer.
    And yes you can add the script to your weapon. (usually something like MainCamera/Weapons/MachineGun/RocketLauncher/GravityGun).
    @Shaemon
    "I have a problem. When I pick something up and throw it it works fine. But the object slowly falls downward while I am holding it."
    I had this problem and I solved it by giving the Rigidbody more drag. I set my drag to 1 and it remains steady.
     
  26. uvavoo

    uvavoo

    Joined:
    Oct 15, 2007
    Posts:
    60
    I am using this script for a gravity gun.


    However, if I pick up an object, say a large rock, and move through the environment, the rock does not collide correctly, just passes through other objects in the scene. I would expect it to collide with other objects. The rock has a rigidibody and collider attached. Anyone any ideas.
     
  27. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Without actually looking at this script, there are two things you need to do to create a gravity gun.

    1) any object you wish to pick up has to have a rigidbody.
    2) turn gravity off for those objects and add explosive force to it that forces it to the gravitational point. (reverse explosive force)

    This way, as you walk around, the objects are affected by physics but still attempt to retain their central cohesion. If objects move too quickly or wobble around the center, consider adding a touch of damping to them.

    It is not necessary to use layers. A simple OverlapSphere would get you all the close objects and draw them in. You simply cycle through all the colliders and find ones that have rigid bodies. You could hold them in a List or Array object and then simply add forward velocity based on the camera's facing to get them to shoot.
     
  28. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,411
  29. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    I've made something similar for my game, but its rather a tractorBeam grabbing a single point on a transform (thought of the title 'wild9' on psx).
    Raycast - check if object has rigidbody - save the localpoint of the transform - applyForceAtPosition that pushes the object to the reticle.

    Example:
    Hold F to ignite TractorRay, if a rigidbody (the pink rectangle thingy has one) happens to be in the range of the ray it grabs it and forces its grabpoint to the reticle position (press B to toggle unbreakable TractorBeamTestMode)
    http://marrt.elementfx.com/

    but that gun is implemented for 2D-TopDown, you would have to save the distance of the grabpoint when grabbing and modify the holding depth manually via mouseWheel for 3D environment or something- or short: define the reticle position in 3D space instead of 2D
     
    Last edited: Apr 23, 2012
  30. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    It is true, if you try and work to understand, people will be more than willing to help you. If you just post..."someone make me some code" no one wants to help. funny how that works. ;)
     
  31. mauri.h

    mauri.h

    Joined:
    Jul 26, 2013
    Posts:
    4
    Hey!

    Don't know if this is any help, but I included a few samples of special feature guns like gravity gun, portal gun, terrain generation gun, etc.
    All of it comes together in a Platformer Toolkit.

    Link to the asset store: http://u3d.as/content/mauricio/advanced-platformer-toolkit/5bK

    You can try out here: http://mauriciohollando.tk/ <- I also have a few other Unity demos on that site and soon will be adding a short series of tutorials for Unity.

    Hope this can be of help to someone :)
     
  32. melidian

    melidian

    Joined:
    Jul 16, 2013
    Posts:
    76
    I used Username85's script it works completely amazingly! Except that when holding objects the object will slowly move downwards I've been trying to fix it and just can't. Please help :)
     
  33. 4u2fap

    4u2fap

    Joined:
    Jan 30, 2013
    Posts:
    1
    you can simply add rigid.rigidbody.useGravity = false; when you pick it up and set it to true when you let it go so it will turn the gravity off when you pick it up and back on when you drop it. the only problem i have with the script is that the hold distance override the colliders so it pass through the wall/floor i have been trying to fix this for a while but cant seem to find anything so if anyone with more knowledge on unity scripting could give me any direction on how to prevent this it would be very appreciated.

    p.s.: if i am able to make this script work ill post the end result here
     
  34. rodriguez80alvaro

    rodriguez80alvaro

    Joined:
    Oct 24, 2017
    Posts:
    2
    Which basically says... do something if Fire1 isn't pressed.

    I didn't look at his script, I'm simply trying to answer your question regarding your conversion. When you're just using GetButtonDown == null, that doesn't seem to make sense to me because GetButtonDown is a method and requires a parameter, and equating a bool(the return value of GetButtonDown) to a null value doesn't make sense.

    Example: https://www.zz.com.ve/en/offer/hosting