Search Unity

Model Shaking Violently While Turned By Mouse. Help?

Discussion in 'Scripting' started by amcclay, May 31, 2009.

  1. amcclay

    amcclay

    Joined:
    Aug 8, 2006
    Posts:
    143
    Hi guys. So, if you would be so kind - could you try to attach this script to a model in Unity and try manipulating it by clicking and dragging on it? (The model just needs a box collider on it to detect the click)

    Notice that at certain edges when you drag it starts shaking between two extreme positions rapidly.

    Does anybody have any ideas how I would fix such an issue?

    Thanks!

    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.  
    9.  
    10. function Awake () {
    11.    
    12.    numberAverages = Mathf.Clamp (numberAverages, 1, numberAverages);
    13.    
    14. }
    15.  
    16. function OnMouseDown () {
    17.    var hit : RaycastHit;
    18.    var dir : Vector3;
    19.        
    20.    // Record initial variables
    21.    if (Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit))
    22.    {
    23.       originalRotation = transform.rotation;
    24.       dir = hit.point - transform.position;
    25.       offsetRotation = Quaternion.Inverse (Quaternion.LookRotation (dir));
    26.  
    27.        while (Input.GetMouseButton (0)  Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit))
    28.        {
    29.           currentDir = hit.point - transform.position;
    30.           transform.rotation =  Quaternion.LookRotation (currentDir) * offsetRotation * originalRotation;
    31.           yield;
    32.        }
    33.        
    34.    
    35.    }
    36. }
    37.  
     
  2. raiden

    raiden

    Joined:
    Feb 8, 2009
    Posts:
    333
    I put this together rather quickly, it may not be exactly what your after, but it might point you in the right direction. I did test this, and it works fine, but if I get some more time, I can possibly get it the way you want.

    Code (csharp):
    1.  
    2. function OnMouseOver() {
    3.     if (collider.tag == "yourObjectTag") {
    4.         if (Input.GetMouseButton(0)) {
    5.             var rotate = 30 * Time.deltaTime;
    6.             collider.transform.Rotate(0,rotate,0);
    7.         }
    8.     }
    9. }
    Hope this helps.

    -Raiden
     
  3. amcclay

    amcclay

    Joined:
    Aug 8, 2006
    Posts:
    143
    Hey Raiden. Thanks for the suggestion, But, I'm wondering, is this intended to be used as just a standalone script or as an additional function for the script I posted?

    I tried just attaching it to an object and it just rotates around the Y as you hold the mouse button down. What I'm trying to do is create a basic model viewer type app where you click on the model and drag it around to manipulate your view of it.
     
  4. raleighr3

    raleighr3

    Joined:
    Jul 9, 2008
    Posts:
    106
    Not sure why it is doing a little shake dance. It seems to happen right on the boundaries of the collider, right around where your Raycasts would start returning false. Perhaps there is some round off error in the calculations that Unity does that are causing a rapid fluctuation between true/false getting returned? Just a theory. Might want to raise the issue with support and see if you can get a Unity guru to chime in?

    In the meantime I do have an alternative method of doing rotations, just a quick and dirty little script:


    Code (csharp):
    1. private var currentDir : Vector3;
    2. private var mousePosition : Vector3;
    3. private var doRot;
    4. private var scale = 10;
    5. private var hit : RaycastHit;
    6. private var distance;
    7. // Make sure there is always a Rigidbody
    8.  
    9.  
    10. function Awake () {
    11.    
    12. }
    13.  
    14.  
    15.  
    16. function OnMouseDown () {
    17.        
    18.    // Record initial variables
    19.    if (Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit))
    20.    {
    21.       currentDir = hit.point - transform.position;
    22.       doRot = true;
    23.     }
    24. }
    25.  
    26. function OnMouseUp()
    27. {
    28.     doRot = false;
    29. }
    30.  
    31.  
    32. function OnMouseDrag()
    33. {
    34.     distance =  Vector3.Distance(Input.mousePosition,  mousePosition);
    35.     currentDir = hit.point - transform.position;
    36.     if(mousePosition.magnitude > Input.mousePosition.magnitude)
    37.     {
    38.         scale = -10;
    39.         Debug.Log("reverse rotatition");
    40.     }
    41.     else
    42.     {
    43.         scale = 10;
    44.     }
    45.     mousePosition = Input.mousePosition;
    46. }
    47.  
    48. function Update()
    49. {
    50.     if(doRot)
    51.     {
    52.         transform.Rotate(currentDir, scale*distance, 0);
    53.     }
    54. }
    55.  
    56.  
    57. function OnDrawGizmos() {
    58.         Gizmos.color = Color.green;
    59.         Gizmos.DrawRay(hit.point, -currentDir*3);
    60. }
    61.  
    62.  
     
  5. amcclay

    amcclay

    Joined:
    Aug 8, 2006
    Posts:
    143
    Thanks raleighr3! Oddly, when trying that script on my model it rotates at strange angles as I drag the mouse in various directions. Not sure what that's about.

    I forgot to mention, there is a post from a while ago that has an example of (almost) exactly what I want to do, but when I tried to repurpose the script I got the strange shaking problem.

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

    Ideally, I don't want my model to *have* to be a rigid body to do this, I just want to be able to (in script) add a box collider component to the model to allow it to be 'grabbed'
     
  6. raleighr3

    raleighr3

    Joined:
    Jul 9, 2008
    Posts:
    106
    Yeah, that script I wrote is really just a simple thing, just a starting point. all it does now is rotate an object around an axis defined by the points :(center of the collider bounds, closest point on the bounds where the mouse was clicked) It does not surprise me that some weird rotations happen on complex meshes.

    I'll take a look at that other post and see what's what.
     
  7. raiden

    raiden

    Joined:
    Feb 8, 2009
    Posts:
    333
    I'm a little late getting back to this, I wrote that snippet to suggest what could be expanded upon or modified in the direction of using mouse classes and functions to:

    1. Detect that your mouse has clicked on your model collider.
    2. Determine that the mouse button is held down over your model collider.
    3. Possibly use the Mouse Events to determine the direction the mouse is being dragged
    4. Update a rotation speed variable based on that direction.
    5. Rotate the model with the rotation speed.

    Thats the idea I had in mind, but nothing in code just yet.

    If I get some time, I'll try and write up this approach, if anyone sees where it will not work, please let me know.

    -Raiden
     
  8. amcclay

    amcclay

    Joined:
    Aug 8, 2006
    Posts:
    143
    Thanks guys. Basically, what I'm trying to achieve is something very close to the "Zen Bound" (iPhone) where you can kind of organically turn an object around with the mouse to examine it.

    It looks like this is going to be a bit more complicated than I thought. :(
     
  9. raleighr3

    raleighr3

    Joined:
    Jul 9, 2008
    Posts:
    106
    well, works better with a sphere collider instead of a box collider
     
  10. amcclay

    amcclay

    Joined:
    Aug 8, 2006
    Posts:
    143
    Yeah a sphere collider does seem to reduce the problem, but it definitely still occurs even with one.
     
  11. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    I am interested to see if you guys were able to come up with a solution to this?