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

Question Rotate Item Using Mouse Input

Discussion in 'Scripting' started by Chrotesque, Dec 4, 2021.

  1. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    Hey all

    I want to replicate a rotation feature for my project that I saw in the steam game Ghost Hunters Corp (and likely many other games before): https://imgur.com/a/JcEunG3

    So I can rotate an item on its Y axis (to the right) as much as I want, when I tilt the mouse up / down it'll move towards or away from the camera, at all times. I would describe this as ignoring it's own X rotation axis.

    In my project, this is what happens: https://imgur.com/a/IXMNU1A

    I can also rotate to the right and left easily, however moving mouse up / down means it'll adhere to it's own rotational X axis and not always tilt towards or away from the camera.

    The code looks like this:
    Code (CSharp):
    1. float mouseX = 0, mouseY = 0;
    2.  
    3. var delta = Mouse.current.delta.ReadValue();
    4. mouseX += delta.x;
    5. mouseY += delta.y;
    6.  
    7. // mouse sensitivity plug
    8. mouseX *= mouseSensitivity * Time.deltaTime;
    9. mouseY *= mouseSensitivity * Time.deltaTime;
    10. float XaxisRotation = (mouseX * rotationSpeedMultiplier) / grabbedObjectMass;
    11. float YaxisRotation = ((mouseY*-1) * rotationSpeedMultiplier) / grabbedObjectMass;
    12. grabbedObject.transform.Rotate(Vector3.down * XaxisRotation, Space.Self);
    13. grabbedObject.transform.Rotate(Vector3.right * YaxisRotation, Space.Self);        
    Omitting Space.Self or changing it to Space.World won't work unfortunately.

    I also tried an alternative solution using Quaternions and Euler Angles on the Rigidbody instead:
    Code (CSharp):
    1. Vector3 EulerAngleVelocity = new Vector3(YaxisRotation, XaxisRotation, 0f);
    2. Rigidbody rb = grabbedObject.GetComponent<Rigidbody>();
    3.  
    4. Quaternion deltaRotation = Quaternion.Euler(EulerAngleVelocity * Time.deltaTime);
    5. rb.MoveRotation(rb.rotation * deltaRotation);
    Does the same thing functionally. Rotations / Quaternions seem like magic to me, I'm at a loss and can't find the solution to this. Also things like transform.LookAt don't seem to do the trick as none of the rotational axis should locked to anything.

    I hope somebody knows how to help me with that.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,760
    For rotations you generally want to keep your axes separate, as in track separate float values and drive two separate Transforms (each only on one axis) with the result. This lets you clamp each one (or not).

    I'm not sure I quite understand this: are you saying you WANT this behavior or that you observe this behavior and it is unwanted?
     
  3. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    Apologies for being unclear! I want the object to always tilt towards and away from the camera no matter how much I've rotated it to the right or left.

    Currently it'll tilt towards and away from it's own rotational y axis and that's unwanted.
     
    Last edited: Dec 4, 2021
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,760
    Gotcha! So what you want is two parented Transforms that you rotate independently.

    The hierarchy should probably look like this:

    MainRootObjectWithScriptsThatNeverRotatesWhatsoever
    RotateMeAroundTheXAxisOnly_ClampedPerhapsTo90DegreesBackAndForth
    RotateMeARoundTheYAxisUnclampedForever
    TheVisibleObjectWouldBePlacedHere


    To verify, just quickly make the above in the editor, no code, then go to each of the "Rotate" items and using the Editor, spin ONLY the axis indicated by the name above. That should immediately tell you without even pressing PLAY if the behavior is what you seek.

    Then it's just a quick "read mouse X, rotate Y and read mouse Y rotate X" script. Keep your own float variable for each direction, and it can just be one script with references to each one.

    PS: the above setup matches a world globe that you can look around and tilt back and forth.
     
  5. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    In my project I have 2 scripts attached to the player object, playermovement that deals with movement, sprinting, crouching, etc. and playercontrols - that one deals with grabbing items, holding them, throwing them and ultimately rotating them.

    Objects itself that the player is supposed to pick up simply use the tag "grabable" (don't judge). So the script simply checks if an item the player is looking at has the tag and if so, it can be interacted with.

    Now that being said, those objects don't have any scripts assigned to them. As such I simplified the structure you outlined to:
    Y (root)
    X (child)
    Cube (the actual visible object)

    Now as you said yourself, playing around with it in the editor shows the exact same behaviour I'm trying to avoid. On the Y-object I change the Y rotation and the cube inside rotates left / right.
    On the X-object I change the X rotation and the cube inside rotates forward / backwards, however it does it in the same way as if I was doing it to the cube itself.
    Here's two gifs: https://imgur.com/a/ITWXw2M
    Off-screen I'm changing the X rotation on the X-object and Y rotation on the Y-object.
    On the bottom gif I'm changing X and Y on the cube itself.

    It's essentially the same behaviour just with more steps. :p

    What am I not seeing or misunderstanding?