How to select and move an object to mouse position (javascript)?

Discussion in 'Scripting' started by Velo222, Apr 29, 2012.

  1. Velo222

    Velo222

    Member

    Joined:
    Apr 29, 2012
    Messages:
    589
    I am a beginner in both unity and javascript. The overall gist of my project is to make an rts-like game, where I can click on units and move them to locations on my map. Currently, I have a simple object (sphere) and a floor (plane) in my scene.

    I'm trying to select my sphere in the game and move it to a location in the game world based on where i click my mouse on the floor/plane. So far I've been messing around with the Input.mousePosition function along with the transform.translate things and I've been very unsuccessful.



    Currently I have this useless code:

    Code (csharp):
    1. #pragma strict
    2.  
    3. static var mousePosition : Vector3;
    4.  
    5. function Start () {
    6. }
    7.  
    8. function OnMouseDown()
    9.     {
    10.     transform.Translate(Input.mousePosition);
    11.     }
    12.    
    13. function Update () {
    14.  
    15. }
    I've tried associating this code with both my sphere and my main camera, but to no avail. I hate to admit it but I've been trying to do this for hours, and I'm getting absolutely no where :( I'd like to keep it to simple statements or functions if possible. Does anyone have some ideas? Even some good tutorials on how to select and move an object to a different location in the game world would be great.
     
    Last edited: Apr 29, 2012
  2. Tobias J.

    Tobias J.

    New Member

    Joined:
    Feb 21, 2012
    Messages:
    423
    No ideas for a tutorial on moving transforms, but here's a few which will cover it sooner or later.

    Good luck! :)
     
  3. Bluntweapon

    Bluntweapon

    Member

    Joined:
    Feb 24, 2012
    Messages:
    156
    There really isn't any tutorials I can find, but I can certainly point you in the right direction.

    Getting the mouse position in the world is a little harder than you think. According to this, even though it gives you a Vector3, it is essentially a 2D vector containing the screen position of your mouse (i.e. the location of your mouse on the screen itself). The z value is always 0.

    To get the world location is a little harder. Normally if you know what the OnScreen point is you can use Camera.ScreenToWorldPoint, but this requires you to also know the distance away from the camera, so what we have to do instead is cast a ray from the camera and see what the ray hits. After that it's a simple Physics.Raycast to get a point of impact (or nothing if there's nothing to hit).

    Note also Transform.Translate moves the transform in a direction for a number of units (all based on the input Vector3). If you want to set the transform to a particular location, you'll have to set its Transform instead, like in this example.

    The code probably looks something like this (untested, and I've never used OnMouseDown before, so lets hope those are correct)
    Code (csharp):
    1.  
    2. function OnMouseDown() {
    3.    
    4.     //Get the mouse position
    5.    
    6.     //Cast it into a ray
    7.     var screenRay : Ray = Camera.main.ScreenPointToRay( mousePosition );
    8.    
    9.     //Initializing some variables
    10.     var hitInfo : RaycastHit;
    11.    
    12.     //Grab the information we need
    13.     Physics.Raycast( screenRay, hitInfo );
    14.     //Note this function also returns a boolean about whether it actually hit anything, so you can use that to check first if hitInfo is null or not
    15.    
    16.     //And find the point of impact
    17.     var pointOfImpact : Vector3 = hitInfo.point;
    18.    
    19.     //Move the object in question
    20.     this.transform.position = pointOfImpact;
    21. }
    22.  
    You may also want to consider moving the object upwards a bit after this, since the it is likely to be sticking out of something halfway.
     
    Last edited: Apr 29, 2012
  4. Velo222

    Velo222

    Member

    Joined:
    Apr 29, 2012
    Messages:
    589
    Thanks for the replies guys. Ya I've heard of this "raycasting" with vectors and such, it sounds complicated, however I see why i need it.

    The mouse position only gives the x,y of the mouse pointer on the 2d screen so-to-speak, so ya I need a 3rd point of reference to give it the depth in 3d space.

    This is definitely a good starting point, but like I said I'm completely new to both unity and javascript, so I'm going to keep working on this. Thanks for the ideas and help :)
     
  5. Velo222

    Velo222

    Member

    Joined:
    Apr 29, 2012
    Messages:
    589
    Just had a quick question as I'm working on the code BluntWeapon gave me, lets say I want to change the "main camera" in the code to another camera in my scene (say Camera2)? How would I do this? I'm assuming then the ray would originate from Camera2?

    In the "Ray = Camera.main.ScreenPointToRay( mousePosition );" line.
     
  6. Tobias J.

    Tobias J.

    New Member

    Joined:
    Feb 21, 2012
    Messages:
    423
    No. Look under 'class variables' here.
     
  7. Ellis

    Ellis

    Member

    Joined:
    Nov 18, 2012
    Messages:
    90
    It works but when I click my object (Capsule) gets half way through the ground! Can I maybe make it add 1 on the y-axis? Also how can I make it smooth so it looks like its walking over to the position instead of it teleporting?
     
  8. LeftyRighty

    LeftyRighty

    Member

    Joined:
    Nov 2, 2012
    Messages:
    852
    (I'm a newbie too... so take this with a little pinch of salt :) )

    Code (csharp):
    1.  
    2.  //And find the point of impact
    3.     var pointOfImpact : Vector3 = hitInfo.point;
    4.  
    5.     //Move the object in question
    6.     this.transform.position = pointOfImpact;
    7.  
    In this code the object's origin is put at the location of pointOfImpact... so there would be two approaches:

    move the objects origin to the bottom of the mesh (not entirely sure how you'd do that, but i'm dabbling with mesh imports and creating a 3d object in blender with it's origin at the bottom works)

    add a vector to the pointOfImpact to raise it up (ie this.transform.position = (pointOfImpact + vector3(0,1,0)) or something similar)

    http://docs.unity3d.com/Documentation/ScriptReference/Vector3-operator_add.html



    I think smoothing for this would be to lerp the object from where it is to where you want it to be

    http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Lerp.html

    so "start.position" would be object.position and "end.position" would be the pointOfImpact


    not sure about the animation stuff yet :(
     
  9. Ellis

    Ellis

    Member

    Joined:
    Nov 18, 2012
    Messages:
    90
    NullReferenceException: Object reference not set to an instance of an object

    Assets/Scripts/Select.js(25,67): BCE0005: Unknown identifier: 'object'.
     
  10. Velo222

    Velo222

    Member

    Joined:
    Apr 29, 2012
    Messages:
    589

    It sounds like you are not referencing the object you want to move correctly now.

    If you are trying object.position, don't do that. Just use "this.transform.position" (if your script is attached to the object you want to move). Or you can also just use "transform.position" and it will "automatically" reference the transform of the object your script is attached to.

    Otherwise you would have to manually reference your character/object into a variable like this:

    var object = GameObject.Find("Insert name of your object here");

    Then you could use object.transform.position in the rest of your script, once your gameobject is referenced. Unity has to have it's hand held so-to-speak as to what game object or objects you're trying to do stuff with.
     
  11. Ellis

    Ellis

    Member

    Joined:
    Nov 18, 2012
    Messages:
    90
    nope, wont work... Eather the error or it just jumps around weirdly, not smooth, just jumping around, not even to the place my mouse is... :p
     
  12. Scenia

    Scenia

    New Member

    Joined:
    Jan 7, 2013
    Messages:
    3
    Try adjusting the last argument in the Lerp function to a smaller value (Time.deltaTime*0.1 should work), this sounds like your Lerp speed is so high the Interpolation results in a value beyond your target position.

    That last line would look something like this:
    Code (csharp):
    1.  
    2. transform.position = Vector3.Lerp(transform.position, pointOfImpact+Vector3(0,1,0), Time.deltaTime * 0.1);
    3.  
    This should make the object smoothly approach the pointOfImpact.

    If it stilll doesn't work (or you don't like how fast/slow it reaches its target), replace "0.1" with "speed" and declare that as a public variable ( var speed : float; ) at the beginning of the script, that way you can adjust the value directly in the Inspector and tweak it until you like the result.

    This won't work any more when you have multiple objects, though. You'll need a way to select an object and move only that one. As it is right now, the script will move all objects to the target position once you click there.
    I'm not sure how that works (I'm pretty new to this as well...), but I think there's an event handler for clicking an object, you could use that to flag the clicked object with a boolean "selected" and execute the rest of the script only if that variable is true.