Search Unity

  1. Looking for a job or to hire someone for a project? Check out the re-opened job forums.
    Dismiss Notice
  2. Unity 2020 LTS & Unity 2021.1 have been released.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Mouse click and mouse drag

Discussion in 'Scripting' started by tsash, Apr 13, 2010.

  1. tsash

    tsash

    Joined:
    Apr 7, 2010
    Posts:
    5
    I'm trying to make an RTS. Right now I'm working on control. I need to distinguish between mouse click and mouse drag. I wrote some code. It's heavily based on corresponding code from community RTS project (Generals). But I don't like this code. I feel it's too big and clumsy. There must be a way to make the same easier.

    Can somebody point me in right direction?

    And what if I want to have a different action for double click and triple click?

    Code (csharp):
    1.  
    2. // range in which a mouse down and mouse up event will be treated as "the same location" on the map.
    3. private var mouseButtonReleaseBlurRange : int = 20;
    4.  
    5. private var Button0DownPoint : Vector2;
    6. private var Button0UpPoint : Vector2;
    7.  
    8. private var Button1DownPoint : Vector2;
    9. private var Button1UpPoint : Vector2;
    10.  
    11. function Update ()
    12. {
    13.     //  CLICKS FOR MOUSE BUTTONS
    14.    
    15.     if (Input.GetButtonDown("Fire1"))
    16.     {
    17.         Button0DownPoint = Input.mousePosition;
    18.     }
    19.    
    20.     if (Input.GetButtonUp("Fire1"))
    21.     {
    22.         Button0UpPoint = Input.mousePosition;
    23.        
    24.         if (IsInRange(Button0DownPoint, Button0UpPoint))
    25.         {
    26.             Mouse0Click(Button0DownPoint);//Function where all actions associated with LMB clicks are performed
    27.         }
    28.     }
    29.    
    30.  
    31.     if (Input.GetButtonDown("Fire2"))
    32.     {
    33.         Button1DownPoint = Input.mousePosition;
    34.     }
    35.    
    36.     if (Input.GetButtonUp("Fire2"))
    37.     {
    38.         Button1UpPoint = Input.mousePosition;
    39.        
    40.         if (IsInRange(Button1DownPoint, Button1UpPoint))
    41.         {
    42.             Mouse1Click(Button1DownPoint);//Function where all actions associated with RMB clicks are performed
    43.         }
    44.     }
    45.        
    46.    
    47.     //  DRAGS FOR TWO MOUSE BUTTONS
    48.    
    49.     if (Input.GetButton("Fire1"))
    50.     {
    51.         if (Input.mousePosition != Button0DownPoint)
    52.         {
    53.             Mouse0Drag(Button0DownPoint);//Function where all actions associated with LMB drag are performed
    54.         }
    55.     }
    56.    
    57.     if (Input.GetButton("Fire2"))
    58.     {
    59.         if (Input.mousePosition != Button1DownPoint)
    60.         {
    61.             Mouse1Drag(Button1DownPoint);//Function where all actions associated with RMB drag are performed
    62.         }
    63.     }
    64. }
    65.  
    66. // if MB was not released exactly at the button down position, but with a slight offset.
    67.  
    68. function IsInRange(v1 : Vector2, v2 : Vector2) : boolean
    69. {
    70.     var dist = Vector2.Distance(v1, v2);
    71.     if (Vector2.Distance(v1, v2) < mouseButtonReleaseBlurRange)
    72.     {
    73.         return true;
    74.     }
    75.     return false;
    76. }
    77.  
    Maybe I can use EventType.MouseDrag somehow?

    And how can I make a time counter? So I can define a time between two clicks and then change it in Game Options. Like in Windows.
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Hi, welcome to the forum!

    Do you already know about the OnMouseDown and OnMouseDrag functions? As for double and triple clicking, you need to record the time of the first click and then check for subsequent clicks within a short time period - there's no event function for multiple clicks.
     
  3. Ramen Sama

    Ramen Sama

    Joined:
    Mar 28, 2009
    Posts:
    561
  4. tsash

    tsash

    Joined:
    Apr 7, 2010
    Posts:
    5
    Thank you, Andeee. I decided that my way was more versatile. Because OnMouseDown and OnMouseDrag only works with LMB. And I going to use all MB in my game.

    Anyway I have another problem. And I don't have enough program experience to solve it by myself.

    Again it is heavily based on scripts from community RTS project.

    I write an Array in one script. Then I send it to gameObject Manager.

    Code (csharp):
    1.  
    2. UnitManager.GetInstance().StartMove(trajectory);
    3.  
    And there I send it to my unit

    Code (csharp):
    1.  
    2. function StartMove(trajectory)
    3. {
    4.     for (var go : GameObject in selectedUnitsList) {
    5.         if (debugMode)
    6.         {
    7.             print("MoveSelectedUnits: Moving unit " + go.name);
    8.         }
    9.         go.SendMessage("SceduledMove", trajectory);
    10.     }
    11. }
    And in my Unit script I receive it

    Code (csharp):
    1.  
    2. function SceduledMove (trj)
    3. {
    4.     shiftMoveToTarget = true;
    5.     moveMode = MoveModeType.FORWARD;
    6.     Trajectory = trj;
    7.     print ("SceduledMove" + Trajectory);
    8.     targetPosition = Trajectory[0];
    9. }
    10.  
    The problem is I can't access this variable Trajectory from Update function.

    It prints this array from function SceduledMove, but in Update same variable Trajectory is empty.

    Code (csharp):
    1.  
    2. var Trajectory = new Array();
    3. function Update ()
    4. {
    5.     if (shiftMoveToTarget)
    6.     {
    7.         Moving (targetPosition);
    8.        
    9.        
    10.        
    11.         // check the distance
    12.         distanceToDestiantion = Vector3.Distance(targetPosition, transform.position);
    13.         //print ("Distance to other: " + dist);
    14.         if (distanceToDestiantion < targetReachedRadius)
    15.         {
    16.             print ("Update   " + Trajectory.length);
    17.             targetPosition = Trajectory[i];
    18.            
    19.             i++;
    20.            
    21.             if (i==(Trajectory.length-1))
    22.             {
    23.                 moveMode = MoveModeType.STOP;
    24.                 shiftMoveToTarget = false;
    25.                 distanceToDestiantion = 0.0;
    26.                 i = 1;
    27.             }
    28.         }
    29.     }
    30. }
    31.  
    What is wrong?
     
  5. KrankyBoy

    KrankyBoy

    Joined:
    Mar 27, 2009
    Posts:
    734
    Can you post the entire script which contains SceduledMove and Update? Because at first glance it appears to be OK.

    By the way its spelled ScheduledMove (In English anyway).
     
  6. tsash

    tsash

    Joined:
    Apr 7, 2010
    Posts:
    5
    Ok I isolated the code where the problem is.

    I have a game object "TestObject" and it has a child "TestObjectSon".

    Script "test1" attached to "TestObject". Script "test2" attached to "TestObjectSon".

    test1:

    Code (csharp):
    1.  
    2. var trajectory = new Array();
    3. private var distanceBetweenSteps:float = 2.0;
    4. var RMBDrag:boolean = false;
    5. private var Button1DownPoint : Vector2;
    6.  
    7.  
    8. function Update ()
    9. {
    10.     if (Input.GetButtonDown("Fire2"))
    11.     {
    12.         Button1DownPoint = Input.mousePosition;
    13.         RMBDrag = true;
    14.     }
    15.    
    16.    
    17.     if (Input.GetButton("Fire2"))
    18.     {
    19.         if (Input.mousePosition != Button1DownPoint)
    20.         {
    21.             var hit : RaycastHit;
    22.             var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    23.            
    24.             if ( Physics.Raycast (ray, hit))
    25.             {
    26.                 if (hit.collider.name == "Terrain")
    27.                 {
    28.                     // first value of Array
    29.                    
    30.                     if (RMBDrag)
    31.                     {
    32.                         trajectory.Add(hit.point);
    33.                         RMBDrag = false;
    34.                     }
    35.                    
    36.                     if (Vector3.Distance(trajectory[trajectory.length-1], hit.point) > distanceBetweenSteps)
    37.                     {
    38.                         trajectory.Add(hit.point);
    39.                     }
    40.                 }
    41.                
    42.                 else
    43.                 {
    44.                     // do nothing
    45.                 }
    46.             }
    47.         }
    48.     }
    49.    
    50.     if (Input.GetButtonUp("Fire2"))
    51.     {
    52.         print ("test 1 Array length  " + trajectory.length);
    53.         print ("test 1 Array  " + trajectory);
    54.         transform.Find("TestObjectSon").GetComponent(test2).test(trajectory);
    55.         trajectory.Clear();
    56.     }
    57. }
    58.  
    test2:
    Code (csharp):
    1.  
    2. var TestArray = new Array();
    3. var Switch:boolean = false;
    4.  
    5. function Update ()
    6. {
    7.     if (Switch)
    8.     {
    9.         print ("Update in test2 Array length  " + TestArray.length);
    10.         print ("Update in test2 Array " + TestArray);
    11.     }
    12. }
    13.  
    14. function test (Arr)
    15. {
    16.     TestArray = Arr;
    17.     print ("function test in test2 Array length  " + TestArray.length);
    18.     print ("function test in test2 Array  " + TestArray);
    19.     Switch = true;
    20. }
    21.  
    And it gives me in console:

    test 1 Array length 2

    test 1 Array (699,4, 0,0, 668,8),(716,9, 0,0, 682,2)

    function test in test2 Array length 2

    function test in test2 Array (699,4, 0,0, 668,8),(716,9, 0,0, 682,2)

    Update in test2 Array length 0

    Update in test2 Array


    What is wrong with my code? Why I can't access this TestArray from Update function in test2 script?
     
  7. KrankyBoy

    KrankyBoy

    Joined:
    Mar 27, 2009
    Posts:
    734
    I am not familiar with javascript, but if I had to guess, I would say here is what is happening:

    1) You create the array in test 1 - FINE
    2) You access this area in test 1 - FINE
    3) you pass this array into test2:test, and assign it to a class variable - NOT GOOD.
    4) you attempt to access that class var outside test2:test and its null because once test2:test leaves the method(which you call in test1) it loses the reference back to the original array which was just a copy passes into the method.

    In C++ anyway you would NEVER assign a class level pointer to a local pointer (created in a function), because once the function exits it removes the local pointer off the stack and so now you are left pointing at an undetermined memory location.
     
  8. tsash

    tsash

    Joined:
    Apr 7, 2010
    Posts:
    5
    Thank you very much, KrankyBoyGames, for your attention to my problem. I don't have a solid background in any programming language. That's why I'm asking stupid questions here.

    So actually TestArray from function test is not TestArray from function Update. Right?

    But why I can change variable Switch in function test? And it is still remain changed in Update. What is the difference?

    It is because the TestArray is an array? Or because I pass TestArray from outside of this game object?
     
  9. KrankyBoy

    KrankyBoy

    Joined:
    Mar 27, 2009
    Posts:
    734
    When you pass the Array from Test to Test2, you pass a COPY - so first of all any changes to the Array in test will NOT show up in Test2 unless you re-pass it.

    Secondly, the COPY of the array in Test2:Test will be wiped from memory WHEN the function ends. At this point, since TestArray = Arr; and Arr is now NULL, TestArray is pointing at NULL.

    Again I am not versed in javascript at all - so if I am wrong then I hope someone else will post as Javascript seems a bit complex in its pass-by-value and pass-by-reference rules.
     
  10. tsash

    tsash

    Joined:
    Apr 7, 2010
    Posts:
    5
    Interesting. Well, thank you again. At least I know now how my problem is called and what to type in search engine.

    And what I found from the very beginning of my search was this, and it says that "JavaScript always passes by value". But then I found this, and there bronxbomber92 wrote that "in Unity's JS every object is a reference (well, not really.. But you can't really create a struct which has pass-by-value semantics)."

    And it seems true, otherwise I couldn't have changed variable Switch from inside function test. So I need to find some article about pass-by-value and pass-by-reference rules specifically in Unity Script, not in JavaScript. Anybody knows where it can be found?
     
unityunity