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. Dismiss Notice

Drag-Rotate Object?

Discussion in 'iOS and tvOS' started by SteveB, Jun 15, 2009.

  1. SteveB

    SteveB

    Joined:
    Jan 17, 2009
    Posts:
    1,451
    First off I swore I saw this topic mentioned elsewhere but alas I can't find it with a site:forum.unity3d.com search in google and with the search function here on the forums...

    ...I want to rotate a 3D object (not GUI) in the game world like a wheel or gear by "physically" turning it with my finger, and I'm assuming I don't merely want to Raycast/collide/drag against the object, but actually drag "around" the wheel as in the act of actually turning it.

    Anyone perchance have some direction for me that they can offer? :D


    Thanks!
    -Steve
     
  2. amcclay

    amcclay

    Joined:
    Aug 8, 2006
    Posts:
    143
    Hey there. So, I've been dealing with this same issue for weeks, and have still not been able to find a satisfactory solution.

    In any case, the two best solutions I've managed are the ones found here:

    http://forum.unity3d.com//viewtopic.php?t=14293

    and finally this script written by mike_mac on the IRC:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MikesTrackBall : MonoBehaviour {
    6.  
    7.     // Use this for initialization
    8.     void Start ()
    9.     {
    10.    
    11.     }
    12.    
    13.     void Update ()
    14.     {
    15.         RaycastHit hit;
    16.  
    17.         if (Input.GetMouseButton(0))
    18.         {
    19.             if (Physics.Raycast (Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
    20.             {
    21.                 float x = -Input.GetAxis("Mouse X");
    22.                 float y = -Input.GetAxis("Mouse Y");
    23.                 float speed = 10;
    24.                 transform.rotation *= Quaternion.AngleAxis(x*speed, Vector3.up);
    25.                 transform.rotation *= Quaternion.AngleAxis(y*speed, Vector3.right);
    26.             }
    27.         }
    28.     }
    29.    
    30. }
    31.  
    Unfortunately, the latter (which I am using) has a problem where it doesn't behave much like a track/arcball should. For example, if you rotate an object that is facing you to the LEFT by dragging LEFT and then attempt to ROLL the object to the RIGHT, since you are seeing the object from a profile you would want to drag the mouse UP (rolling the object over its side) but moving up will ALWAYS pitch the object UP regardless of where it is facing. In this sense, it is less like a track ball and more like a pitch/roll control that always uses the model's facing . If that makes any sense.

    Either way, try both and see if either one works for you. It would be awesome if others that had their own implementation would share too.
     
  3. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,630
    I tried converting one of the scripts to work on the iphone. It works properly when you let go of the object but it rotates in the opposite direction you would expect when touched. Can anyone see what the problem is?

    Code (csharp):
    1.  
    2. var numberAverages : int = 3;
    3.  
    4. private var originalRotation : Quaternion;
    5. private var offsetRotation : Quaternion;
    6.  
    7. // Make sure there is always a Rigidbody
    8. @script RequireComponent (Rigidbody)
    9. @script RequireComponent (SphereCollider)
    10.  
    11.  
    12. function Awake () {
    13.    
    14.    numberAverages = Mathf.Clamp (numberAverages, 1, numberAverages);
    15.    
    16. }
    17.  
    18. function Update () {
    19.    var hit : RaycastHit;
    20.    var dir : Vector3;
    21.  
    22.    
    23.    if (iPhoneInput.touchCount > 0) {    
    24.         rigidbody.angularVelocity = Vector3.zero;
    25.  
    26.         // Get movement of the finger since last frame
    27.         var touchPosition:Vector2 = iPhoneInput.GetTouch(0).position;
    28.  
    29.         // Record initial variables
    30.         if (Physics.Raycast (camera.main.ScreenPointToRay(touchPosition), hit)) {
    31.             originalRotation = transform.rotation;
    32.             dir = hit.point - transform.position;
    33.             offsetRotation = Quaternion.Inverse (Quaternion.LookRotation (dir));
    34.             Spin (dir);
    35.         }
    36.    }
    37. }
    38.  
    39.  
    40. function Spin (dir : Vector3) {
    41.    var hit : RaycastHit;
    42.    var previousDirList : Array = new Array ();
    43.    var currentDir : Vector3;
    44.    var touchPosition:Vector2;
    45.    var touched : boolean;
    46.    
    47.    // Initialize previous dir list
    48.    for (var i : int = 0; i < numberAverages; i++) {
    49.       previousDirList.Add (currentDir);
    50.    }
    51.    
    52.    currentDir = dir;
    53.    
    54.    touchPosition = iPhoneInput.GetTouch(0).position;
    55.    while (iPhoneInput.touchCount > 0  Physics.Raycast (camera.main.ScreenPointToRay(touchPosition), hit)) {
    56.       touchPosition = iPhoneInput.GetTouch(0).position;
    57.       // Remove first element of the array
    58.       previousDirList.RemoveAt (0);
    59.       // Add current dir to the end
    60.       previousDirList.Add (currentDir);
    61.       currentDir = hit.point - transform.position;
    62.      
    63.       transform.rotation =  Quaternion.LookRotation (currentDir) * offsetRotation * originalRotation;
    64.       yield;
    65.    }
    66.    
    67.    // User let go of the mouse so make the object spin on its own
    68.    var avgPreviousDir : Vector3 = Vector3.zero;
    69.    for (dir in previousDirList) {
    70.       var d : Vector3 = dir;
    71.       avgPreviousDir = avgPreviousDir + d;
    72.    }
    73.    
    74.    avgPreviousDir /= numberAverages;
    75.    Kick (currentDir, avgPreviousDir);
    76. }
    77.  
    78.  
    79. function Kick (r2 : Vector3, r1 : Vector3) {
    80.    var linearVelocity : Vector3;
    81.    var angVelocity : Vector3;
    82.    
    83.    // Calculate the angular velocity:  omega = r x v / r^2
    84.    linearVelocity = (r2 - r1) / Time.deltaTime;
    85.    rigidbody.angularVelocity = Vector3.Cross (r2, linearVelocity) / r2.sqrMagnitude;
    86.  
    87. }
    88.  
    [/code]
     
  4. Holocene

    Holocene

    Joined:
    Feb 21, 2009
    Posts:
    347
    Hi, guys,

    Did you happen to find a solution to the arcball / trackball style control? I have been searching for a viable solution for a while.

    Thanks,

    Greg
     
  5. wgrand

    wgrand

    Guest

    Joined:
    Mar 11, 2010
    Posts:
    14
    Did you ever find a solution to this?
     
  6. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,250
    This is what I do:

    Code (csharp):
    1.  
    2. var touch0 : iPhoneTouch;
    3. thisTransform = transform;
    4.  
    5. thisTransform.RotateAround (thisTransform.position, Vector3(0, 1, 0), -touch0.deltaPosition.x);
    6. thisTransform.RotateAround (thisTransform.position, Vector3(1, 0, 0), touch0.deltaPosition.y);
    I change the axes of rotation depending on where the camera is. In this case, it rotates in the X and Y axes.

    The only problem is that the direction of rotation depends on how the object is currently rotated. If it is facing the camera, this works correctly. But if you rotate the object all the way around, the directions are reversed, and it rotates opposite to the direction of the drag.
     
  7. wgrand

    wgrand

    Guest

    Joined:
    Mar 11, 2010
    Posts:
    14
    I found an answer to the inverted rotation issue. I'm not sure what the cause is for the inversion, but if you replace iPhoneInput.GetTouch(0).position with Input.mousePosition, it works.
     
  8. crevelop

    crevelop

    Joined:
    Nov 9, 2010
    Posts:
    13