Search Unity

make a cube stick with the cursor

Discussion in 'Scripting' started by morgansaysthis, Jul 28, 2007.

  1. morgansaysthis

    morgansaysthis

    Joined:
    Jan 12, 2007
    Posts:
    245
    im trying to do something really simple and its bothering the hell out of me


    im trying to make a cube follow the mouse on the Y,Z directions, and stay at zero on the X, so it looks like my GUI hand thing is grabbing it and i can move it up to the top of a tower, i cant get it to work




    i would be surprised if this was more than 3 lines of code so im feeling pretty stupid.....
     
  2. terransage

    terransage

    Joined:
    Jul 17, 2006
    Posts:
    290
    This is just an idea of how to do it, but I'm away from my home computer, so I can't test it:

    You might want to have a MouseFollow script activated when the cursor is over the cube to have it follow the "hand" (I have cblarsen's code below for the MouseFollow script, but you probably have that already). Then, when the cube is at the top of the tower (or at a certain height that makes it look like it's at the top of the tower), destroy the cube following the cursor and instantiate a Prefab of the cube at the top of the tower. You can also disable the script at that point and just have the cube "drop" on top of the tower instead of destroying/instantiating it.

    I suggested destroying/instantiating, because when the cube follows the cursor, it "jumps" close to the camera and "away" from the tower, but that distance from the camera can be adjusted too. (I only tried the script once, a long time ago, so I'm not sure exactly how it worked.)

    Anyway, here's cblarsen's code:
    Code (csharp):
    1. var wantedZDistanceFromCamera = 5.0;
    2.  
    3. function Update () {
    4.  
    5.    var mainCamera = FindCamera();    
    6.    // Position on the near clipping plane of the camera in world space
    7.    var p = mainCamera.ScreenToWorldPoint(Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
    8.    // Position relative to the eye-point of the camera
    9.    p -= mainCamera.transform.position;
    10.    // A relative position at the wanted z distance from the camera
    11.    var currentZDistanceFromCamera : float = Vector3.Dot(mainCamera.transform.forward, p );
    12.    p *= wantedZDistanceFromCamera / currentZDistanceFromCamera;
    13.    // The position in world space
    14.    p += mainCamera.transform.position;
    15.    
    16.    transform.position = p;    
    17.    
    18. }
    19.  
    20. function FindCamera ()
    21. {
    22.    if (camera)
    23.       return camera;
    24.    else
    25.       return Camera.main;
    26. }
    Now you have me thinking about this too, so I'll probably try it when I get home. Good luck! :)

    Edit: I wasn't paying attention to what you were saying about the x, y and z axes, but you can just write that into this code as well.
     
  3. terransage

    terransage

    Joined:
    Jul 17, 2006
    Posts:
    290
    Well, I experimented a little and borrowed from the Procedural examples (Lightning Bolt) to come up with this (for dragging the object and releasing it at its destination--constrained to y and z):
    Code (csharp):
    1. function OnMouseDown () {
    2.     var screenSpace = Camera.main.WorldToScreenPoint(transform.position);
    3.     var offset = transform.position - Camera.main.ScreenToWorldPoint(Vector3(Input.mousePosition.x,
    4. Input.mousePosition.y, screenSpace.z));
    5.     while (Input.GetMouseButton(0))
    6.     {
    7.         var curScreenSpace = Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);
    8.         var curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset;
    9.         transform.position = curPosition;
    10.         yield;
    11.  
    12.     }
    13. }
    14.  
    15. function OnMouseUp () {
    16.     rigidbody.isKinematic = false;
    17.     rigidbody.WakeUp();    
    18.            
    19. }
    20.  
    I'm probably telling you stuff that you already know, but you have to give the object a rigidbody with both Use Gravity and isKinematic checked, since the "pick up" part of the code only seems to work on an object that has no rigidbody or is kinematic. Then, when you want to drop it, just release the mouse button, and the isKinematic is disabled. The only problem I ran into is that it seems to work only once, even when I tried to put "rigidbody.isKinematic = true;" in the OnMouseDown part of the code. Not sure why....

    I'm not sure if this is the kind of thing you're looking for, but anyway, I learned a few things myself. :)

    Edit: I also tried:
    Code (csharp):
    1. function OnCollisionEnter(collision : Collision) {
    2.     rigidbody.isKinematic = true;
    3. }
    4.        
    5.  
    to make the cube kinematic again--and it worked; the cube froze in position. But for some reason the OnMouseDown refused to work the next time I tried to drag it. I suppose that if you wanted to move it again, you could use OnCollisionEnter to destroy the cube and instantiate the Prefab version with the same code. Hm, I'll try that now.

    Edit: Okay, I tried it. The Prefab was instantiated with isKinematic on and code intact, but it still couldn't be dragged. I now think it has to do with the fact that it's now in contact with the floor mesh. I noticed that when I placed the original the cube on or intersecting another mesh, the dragging didn't work at all.