Tuesday, 6 May 2014

Drag and Rotate

In one of the prototypes i want to be able to drag and rotate a game object using the mouse. After some time googling the topic, i could not find anything on this topic or in a simple language that i could understand. The only thing that i could find helpful was rotate to face function and other code that had the same result.

This was semi-useful as this gave me a means to rotate and object. I could not get the rotate to face function to feel right so i complied bits of code from several forums, it looked something like this:

private var MouseDown = false;

function OnMouseDown()
{
  MouseDown = true;
}

function FixedUpdate ()
{
  if(MouseDown)
  {
   //Gets the mouse vectors
   var mousePos = Input.mousePosition;

   //Gets the mouse Position relative to the camera's Position
   var lookPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);

   //Creates an angle value
   var angle = Mathf.Atan2(lookPos.y, lookPos.x) * Mathf.Rad2Deg;

   //Rotates Object along Z axis using new value.
  transform.localEulerAngles -= new Vector3(0,0,angle);

  }
}

function OnMouseUp()
{
MouseDown = false;
}

This worked to a degree. When i clicked and dragged the mouse, the object would rotate. However, the object would snap and point to the mouse when the mouse was clicked. This was a problem as i only wanted it to rotate when the mouse was moved. Thus, to achieve what i wanted, i had to figure out a way for it to add rotation rather than rotating to the mouse.

On a side note:
var angle = Mathf.Atan2(lookPos.y, lookPos.x) * Mathf.Rad2Deg;
Only works because the objects were in the center of the screen. To rotate objects that are off center:
var angle = Mathf.Atan2(lookPos.y - transform.position.y, lookPos.x - transform.position.x) * Mathf.Rad2Deg;
This uses the center of the object rather that the center of the screen.

Firstly i tried to add rotation to the object when the mouse moved using the OnMouseDrag function. However the issue was that rotation was added every time the mouse was moved rather that how much the mouse was moved, this meant that the object would rotate too slow or too fast.

The solution to the problem was to use two angles and have the first one check against the second, if there was a difference, rotate by the difference. The final code looked like this:

private var Angle : float;
private var Oldangle : float;
private var Difference: float;
private var MouseDown = false;

function OnMouseDown()
{
 // This creates an angle from where the position of mouse is clicked.
 var mousePos = Input.mousePosition;
 var lookPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);

 //This stores the first angle
 Oldangle = Mathf.Atan2(lookPos.y, lookPos.x) * Mathf.Rad2Deg;

 MouseDown = true;
}

function FixedUpdate ()
{
 if(MouseDown)
 {
  //This creates a second angle based on the mouse’s current posistion
  var mousePos = Input.mousePosition;
  var lookPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);
  Angle = Mathf.Atan2(lookPos.y, lookPos.x) * Mathf.Rad2Deg;

  //This creates a value that the object will rotate by.
  Difference = Oldangle - Angle;

  //Traces if the mouse has moved
  if(Difference != 0)
  {
   //Rotate the object by the difference
   transform.localEulerAngles -= new Vector3(0,0, Difference);

   //Now the differenace has been added,
   //Change the starting angle to the current angle
   Oldangle = Angle;
  }
 }
}

function OnMouseUp()
{
 MouseDown = false;
}

This works exactly how i wanted it to. In layman's terms, when the mouse is clicked a new angle is created. Then in the update function a second angle is created and constantly updated. The second angle is checked against the first to see if they are the same, if they are not, rotate the object by the difference of the two angles. After the difference has been added, update the first angle using the mouse’s new position. Repeat until the mouse is released.

I could not find any drag and rotate code online so the second part of the code was my own work. The first part was a result of looking at several different ways of calculating angles.

On a side note, i learned that you can find an object’s rotation by printing transform.rotation. But to change an object’s rotation you need to use transform.localEulerAngles = new Vector3(#,#,#).

No comments:

Post a Comment