Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Move GameObject Based On The Direction Of Mouse Position From A Point

Discussion in 'Scripting' started by Jared_P, Mar 2, 2017.

  1. Jared_P

    Jared_P

    Joined:
    Apr 15, 2014
    Posts:
    12
    Basically, I have a map in 2D, with some buttons for level selection and some fancy clouds on top ;).
    I made them work together and added some cool features.
    Then, I realized that it would be more cooler if I'll add a scrolling effect!
    Now my problem is that I tried coding it and gone through different ways but I just can't achieve the right thing...

    Here's my idea:
    I want the map (not the camera) to move to the direction of the mouse position from a certain point
    (like from the center of the screen) then base the speed from its distance from that point (the farther the
    mouse from the point, the faster the scrolling will be).
    I think the logic is the same as how joysticks move a top-down character...

    *If you don't understand what I mean, take a look at Google Chrome's middle mouse button scroll.
    It's the best example that I can think of right now.

    Thanks in advance! :)
     
  2. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Two quick questions. Is this a 2D( orthographic camera) setup? And is your map a sprite thats just much larger than the screen?
     
  3. Jared_P

    Jared_P

    Joined:
    Apr 15, 2014
    Posts:
    12
    Exactly yes!
     
  4. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    I implement the googleDrag. But I also implemented an InstantMove , as well as a grab and drag in case you wanted to use any of those. Attach this script to your Map Sprite
    Code (CSharp):
    1. using System;using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MapMover : MonoBehaviour {
    6.  
    7.     // Units per Second
    8.     public float googleDragSpeed;
    9.  
    10.     float xMax;
    11.     float xMin;
    12.     float yMax;
    13.     float yMin;
    14.  
    15.     bool clickDrag = false;
    16.     bool googleDrag = false;
    17.     Vector3 startWorldCoords;
    18.     Vector3 oldMousePosition;
    19.  
    20.     void Awake()
    21.     {
    22.         GetBounds();
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         if (Input.GetKeyDown(KeyCode.A))
    28.             InstantMove(true);
    29.         if (Input.GetKeyDown(KeyCode.D))
    30.             InstantMove(false);
    31.         if (Input.GetMouseButtonDown(0))
    32.             StartClickDrag();
    33.         if (Input.GetMouseButtonUp(0))
    34.             EndClickDrag();
    35.         if (Input.GetMouseButtonDown(1))
    36.             StartGoogleDrag();
    37.         if (Input.GetMouseButtonUp(1))
    38.             EndGoogleDrag();
    39.         if (clickDrag)
    40.             ContinueClickDrag();
    41.         if (googleDrag)
    42.             ContinueGoogleDrag();
    43.     }
    44.  
    45.     private void StartClickDrag()
    46.     {
    47.         clickDrag = true;
    48.         oldMousePosition = Input.mousePosition;
    49.     }
    50.  
    51.     private void ContinueClickDrag()
    52.     {
    53.         Vector3 oldWorldPos = Camera.main.ScreenToWorldPoint(oldMousePosition);
    54.         Vector3 currentWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    55.         transform.position += (currentWorldPos - oldWorldPos);
    56.         transform.position = ClampedVector3(transform.position);
    57.         oldMousePosition = Input.mousePosition;
    58.  
    59.     }
    60.  
    61.     private void EndClickDrag()
    62.     {
    63.         clickDrag = false;
    64.     }
    65.  
    66.     private void StartGoogleDrag()
    67.     {
    68.         googleDrag = true;
    69.         startWorldCoords = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    70.     }
    71.  
    72.     private void ContinueGoogleDrag()
    73.     {
    74.         Vector3 currentWorldCoords = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    75.         float xDiff = startWorldCoords.x - currentWorldCoords.x;
    76.         float yDiff = startWorldCoords.y - currentWorldCoords.y;
    77.  
    78.         // 1 Unit from the startSpot = full GoogleDRagSpeed
    79.         Vector3 position = transform.position;
    80.         position.x += xDiff * googleDragSpeed * Time.deltaTime;
    81.         position.y += yDiff * googleDragSpeed * Time.deltaTime;
    82.         transform.position = ClampedVector3(position);
    83.     }
    84.  
    85.     private void EndGoogleDrag()
    86.     {
    87.         googleDrag = false;
    88.     }
    89.  
    90.     private void InstantMove(bool CenterToSpot)
    91.     {
    92.         Vector3 position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    93.         position.z = transform.position.z;
    94.         if (CenterToSpot)
    95.             position += transform.position;
    96.         else
    97.             position = transform.position - position;
    98.         position = ClampedVector3(position);
    99.         transform.position = position;
    100.     }
    101.  
    102.     private Vector3 ClampedVector3(Vector3 v)
    103.     {
    104.         Vector3 clampedV = v;
    105.         clampedV.x = Mathf.Min(Mathf.Max(clampedV.x, xMin), xMax);
    106.         clampedV.y = Mathf.Min(Mathf.Max(clampedV.y, yMin), yMax);
    107.         return clampedV;
    108.     }
    109.     private void GetBounds()
    110.     {
    111.         SpriteRenderer sr = GetComponent<SpriteRenderer>();
    112.         Sprite sprite = sr.sprite;
    113.  
    114.         // x and y Units are how many units it takes to get to edge
    115.         // of the screen from the middle (0,0)
    116.         float yUnits = Camera.main.orthographicSize;
    117.         float xUnits = yUnits * Camera.main.aspect;
    118.  
    119.         // figure out how much of the sprite is offscreen in Units
    120.         float xRight = sprite.texture.width - sprite.pivot.x;
    121.         xRight *= transform.localScale.x;
    122.         xRight /= sprite.pixelsPerUnit;
    123.         xMin = -(xRight - xUnits);
    124.  
    125.         float xLeft = sprite.pivot.x;
    126.         xLeft *= transform.localScale.x;
    127.         xLeft /= sprite.pixelsPerUnit;
    128.         xMax = (xLeft - xUnits);
    129.  
    130.         float yUp = sprite.texture.height - sprite.pivot.y;
    131.         yUp *= transform.localScale.y;
    132.         yUp /= sprite.pixelsPerUnit;
    133.         yMin = -(yUp - yUnits);
    134.  
    135.         float yDown = sprite.pivot.y;
    136.         yDown *= transform.localScale.y;
    137.         yDown /= sprite.pixelsPerUnit;
    138.         yMax = yDown - yUnits;
    139.     }
    140. }
    141.  

    Press A and D to do the instant Move. A moves the center to the spot your mouse is. D moves the Spot the mouse is to the center.
    Press and hold left mouse button to get a normal Grab and drag around feature.
    Press and hold right mouse button to get a Google Drag like you asked for. Note you must set GoogleDragSpeed in the inspector. its in Units Per Second: 2-3 is probably a good number.

    The method GetBounds finds out how big your map is, and how much of it is offscreen. Then it figures out the maximum your allowed to move the map around so it doesn't go past the edge of the screen and leave blank spaces.
    ClampedV is the function that clamps the position Vectors to these boundaries.
    Note: I think the GetBounds function is dependant on the pivot being in the center of the map. It might not work if the pivot is Vector2.zero (the bottom left edge)
     
    Jared_P likes this.
  5. Jared_P

    Jared_P

    Joined:
    Apr 15, 2014
    Posts:
    12
    @takatok, it works properly! Thank you for your time and have a nice day! :)
     
  6. Jared_P

    Jared_P

    Joined:
    Apr 15, 2014
    Posts:
    12
    Wait :D.... I have another quest to do:
    I also want to add a separate scrolling for the clouds on top of the map(...which will have a faster scroll speed than the map to make a parallax effect). Well, how do I do this?
     
  7. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Sorry for the late reply. I'd grab the offset from the GoogleDrag method. Then just get the X component of it. Multiply that by 1.5 or something and move the clouds by that much. Then the clouds will always move faster than the dragging map. You can even take the absolute value of the X difference so the clouds only move one direction, and don't move foreward and backwardd as you drag back and forth.