Search Unity

Transform & RotateAround Help

Discussion in 'Scripting' started by Cooper37, Jun 17, 2016.

  1. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Hi all! In this script, I have a point that moves around the player, and moves back and forth from the player with the X axis and Y axis joystick. Mind you, this is a 3rd person game. When the player walks around, I would like for the point to travel with the player, however, it contradicts with the Rotate Around and prevents it for working.

    How can I get the point to have the same affect as
    Code (csharp):
    1.  
    2. tossPoint.transform.position.x = transform.position.x;  
    3. tossPoint.transform.position.z = transform.position.z;
    4.  
    while keeping the RotateAround working in the script?

    Gear.js
    Code (csharp):
    1.  
    2. var tossPoint                    : Transform;
    3. function Update(){
    4.     tossPoint.transform.RotateAround(transform.position, Vector3.up, Input.GetAxisRaw("Stick X") * 130 * 0.02);
    5.     tossPoint.Translate(Vector3.forward * Input.GetAxisRaw("Stick Y") * 130 * 0.02);
    6. }
    7. function OnDrawGizmosSelected(){
    8.     Gizmos.color = Color.cyan;
    9.     Gizmos.DrawWireSphere(tossPoint.position, 40);
    10.  
    11.     Gizmos.color = Color.red;
    12.     Gizmos.DrawWireSphere(tossPoint.position, 20);
    13. }
    14.  
     
  2. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    So you want it to rotate around the player as they move? I guess a simple way would be to put the point inside a gameobject and have that parent gameobject be what follows the player.
     
  3. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Not really. I want to move the point in the same way if you were to use this method:
    Code (csharp):
    1.  
    2. tossPoint.transform.position.x = transform.position.x;
    3. tossPoint.transform.position.z = transform.position.z;
    4.  
    But I can't use this method and the RotateAround method at the same time. Actually, the transform position method takes precedence over RotateAround. How can I get the point(or Vector if possible) to have the same transforming position as the player(which this script is attached to), while keeping the RotateAround working?[/CODE]
     
  4. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Maybe this?
    Its in C# and I changed the Input string to "Mouse ..." instead of your "Stick ..."
    This assumes the tossPoint is starting in the correct position. If it isnt, then you would need to set it somewhere.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class TestRotateAroundFollow : MonoBehaviour
    5. {
    6.     public Transform tossPoint;
    7.     Vector3 offset;
    8.  
    9.     void Update()
    10.     {
    11.         Vector3 followPosition = transform.position;
    12.         followPosition.y = tossPoint.position.y;
    13.  
    14.         tossPoint.position = followPosition + offset;
    15.  
    16.         tossPoint.RotateAround(transform.position, Vector3.up, Input.GetAxisRaw("Mouse X") * 130f * .02f);
    17.         tossPoint.Translate(Vector3.forward * Input.GetAxisRaw("Mouse Y") * 130f * .02f);
    18.  
    19.         offset = (tossPoint.position - followPosition);
    20.     }
    21.  
    22.     void OnDrawGizmosSelected()
    23.     {
    24.         Gizmos.color = Color.cyan;
    25.         Gizmos.DrawWireSphere(tossPoint.position, 40);
    26.  
    27.         Gizmos.color = Color.red;
    28.         Gizmos.DrawWireSphere(tossPoint.position, 20);
    29.     }
    30. }
     
  5. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Nah. The this keyword didn't work, it's set in the right position and it's written in js. The Stick and Mouse have the same Input settings, so that wouldn't do any good either. I'll keep tinkering with it.
     
  6. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    OK, now I just took another route by making the tossPoint a child of my 3D orbit camera, and it does what I want it to do for the most part. Only thing is, when I look up and down, the tossPoint goes up and down as well. How can I get rid of Y axis movement to a child gameObject?
     
  7. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Did you click the "Spoiler: Click for code" Black box in my post? It will show you the code I wrote. That code is what I meant by "this", not the "this" keyword in code.
     
  8. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    It's a bit jittery when I move and turn at the same time, but at least it works! Thank you, kind sir! :)
     
  9. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    I wonder if that has to do with whether you move your character before or after this code. Try changing my code from Update to LateUpdate (assuming you do all your movement code in Update) and see if that helps with the jitter.
    If you move with FixedUpdate, then you might need to get into interpolation (using lerp and what not).
     
  10. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    I move within the Update, and LateUpdate gives the same results, if not worse lol. Maybe a bit of code tinkering would help?
     
  11. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Strangely enough, changing the offset variable to private and adding the z distance offset like I wanted manually eliminates the jitters. Thank you so much kind sir!

    Code (csharp):
    1.  
    2. private var offset : Vector3 = Vector3(0,0,70);
    3.  
     
  12. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Actually, there's one more dilemma. This line of code is responsible for pushing the tossPoint back and forth from the player:
    Code (csharp):
    1.  
    2. tossPoint.Translate(Vector3.forward * Input.GetAxis("Mouse Y") * 110f * .02f);
    3.  
    But at some point, I'd like the point to stop when close to the player, and can't travel on forever when away from the player. Is there a way to limit this?
    Code (csharp):
    1.  
    2.         var followPosition : Vector3 = transform.position;//This Vector follows our player's position
    3.         followPosition.y = tossPoint.position.y;//Excludes the y position and keeps it at its original position
    4.         tossPoint.position = followPosition + offset;//The point's position is equal to the player's, plus the offset
    5.         tossPoint.RotateAround(transform.position, Vector3.up, Input.GetAxis("Mouse X") * 130f * .02f);//Rotate around the player
    6.        
    7.         tossPoint.Translate(Vector3.forward * Input.GetAxis("Mouse Y") * 110f * .02f);
    8.  
    9.         offset = (tossPoint.position - followPosition);
    10.  
     
  13. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Im not sure why there is jitter. I dont remember seeing any jitter on my end, but maybe my eyes werent sensitive enough to notice it, or framerate might be affecting it?

    I am not at my computer, so I cant test it, but maybe something like this?
    Right after we set the offset, we will clamp its distance.
    Code (CSharp):
    1.  
    2. //....
    3. offset = (tossPoint.position - followPosition);
    4. float clampDistance = Mathf.Clamp(offset.magnitude, minDistance, maxDistance);
    5. offset = Vector3.ClampMagnitude(offset, clampDistance);
    6.  
     
  14. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    In a way, this is close to what I'm looking for. I know Clamp plays some part into this. It does stop the distance as far as max distance allowed here(which is 90), but I kinda want to stop it as if it has a minimum value(like 20). Imagine this diagram:
    clampDist(90)------------Player-----------clampDist(-90)

    This is what the line of code does. It ranges from the clamped value on the left, passes the player, and goes an extra 90.

    clamDist(90)-----------------STOP(20)---Player

    This is what I'm desiring. It's not greater than clampDist and no less than STOP. It barely reaches the player a bit. Thank you for your help too!
     
  15. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    I am pretty sure my code does prevent the toss object from going within your minDistance of 20, the issue is if you keep moving your mouse past the player enough it will then be seen as greater than 20 in the opposite direction, which according to this code would be fine.

    In other words, this code doesnt take into account whether the object is infront or behind the player. Did you want to limit it so that it never goes behind the player?
     
  16. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Yeah, I guess I should've been more specific on that part, but yes.
     
  17. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Now we run into the issue of what exactly counts as the front? How does your character turn? If your character turns with the mouse, I feel things would get weird to control with this code. Is this object expected to stay directly where the player is facing (players transform.forward), or is it just somewhere in front of the player like a half circle around the front of the player?
     
  18. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    The player can rotate if my orbit camera is still, but also moves relative to the main Camera. I believe this defines the front of the player.
    Code (csharp):
    1.  
    2. var forward : Vector3 = Camera.main.transform.TransformDirection(Vector3.forward);
    3.  
    This is how I rotate
    Code (csharp):
    1.  
    2. if(targetDirection != Vector3.zero && canMove){//We smoothly rotate here if we canMove
    3.         var newRotation = Quaternion.LookRotation(targetDirection);
    4.         transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime * rotationSmoothing);
    5.     }
    6.  
     
  19. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    This was the closest solution, but yeah, I need to know what front is for it to work.
    Code (csharp):
    1.  
    2. if(offset.magnitude <= 20){
    3.      offset.z = 20;
    4. }
    5.  
     
  20. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Ye, you were right about my other code not limiting the minDistance correctly. I have a fix for that, but I am running into another issue.

    I am able to clamp the distance and I am also able to keep the toss in front, however, both the clamp distance and keeping in front method are messing up the offset in a way that it messes up the RotateAround and Translate.
    Also, I have seen the toss suddenly just start drifting away. Not sure if its related to this issue or not.

    As I said in an earlier post, with the way I wrote the code, it assumes the toss object is starting in the correct state (position / rotation). However, when we start introducing these clamps and what not, we are in a way messing up that initial correct state that this code is assuming.

    Ill show you the code I have so you can see what I mean
    I commented out the line "//offset = ClampHorizontalMagnitudeBetween(offset, minDistance, maxDistance);" since it is easier to see the issue I am talking about without the clamping.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class TestRotateAroundFollow : MonoBehaviour
    5. {
    6.     public Transform tossPoint;
    7.     public float minDistance = 20f;
    8.     public float maxDistance = 90f;
    9.  
    10.     Vector3 offset;
    11.  
    12.     void Update()
    13.     {
    14.         Vector3 followPosition = transform.position;
    15.         followPosition.y = tossPoint.position.y;
    16.  
    17.         tossPoint.position = followPosition + offset;
    18.  
    19.         tossPoint.RotateAround(transform.position, Vector3.up, Input.GetAxisRaw("Mouse X") * 130f * .02f);
    20.         tossPoint.Translate(Vector3.forward * Input.GetAxisRaw("Mouse Y") * 130f * .02f);
    21.  
    22.         offset = (tossPoint.position - followPosition);
    23.         offset = KeepPointInFront(followPosition + offset, transform.position, transform.forward) - followPosition; //assuming transform.forward is the forward direction.
    24.        //offset = ClampHorizontalMagnitudeBetween(offset, minDistance, maxDistance); //Must be after KeepPointInFront to avoid jitter
    25.  
    26.         tossPoint.position = followPosition + offset; //Since we moved the tossPoint again, we update its position with the new clamped offset value to remove jitter.
    27.     }
    28.  
    29.     //We dont want to include the Y in this.
    30.     Vector3 ClampHorizontalMagnitudeBetween(Vector3 vector, float minMagnitude, float maxMagnitude)
    31.     {
    32.         float y = vector.y;
    33.         vector.y = 0;
    34.         vector = ClampMagnitudeBetween(vector, minDistance, maxDistance);
    35.         vector.y = y;
    36.         return vector;
    37.     }
    38.  
    39.     Vector3 ClampMagnitudeBetween(Vector3 vector, float minMagnitude, float maxMagnitude)
    40.     {
    41.         if(vector.sqrMagnitude < minMagnitude * minMagnitude)
    42.         {
    43.             return vector.normalized * minMagnitude;
    44.         }
    45.         else if(vector.sqrMagnitude > maxMagnitude * maxMagnitude)
    46.         {
    47.             return vector.normalized * maxMagnitude;
    48.         }
    49.         return vector;
    50.     }
    51.  
    52.     Vector3 KeepPointInFront(Vector3 point, Vector3 target, Vector3 targetForward)
    53.     {
    54.         if(!IsInDirection(point - target, targetForward))
    55.         {
    56.             return target + Vector3.ProjectOnPlane(point - target, targetForward.normalized);
    57.         }
    58.         return point;
    59.     }
    60.  
    61.     bool IsInDirection(Vector3 direction, Vector3 otherDirection)
    62.     {
    63.         return Vector3.Dot(direction.normalized, otherDirection.normalized) > 0;
    64.     }
    65.  
    66.     void OnDrawGizmosSelected()
    67.     {
    68.         Gizmos.color = Color.cyan;
    69.         Gizmos.DrawWireSphere(tossPoint.position, 40);
    70.  
    71.         Gizmos.color = Color.red;
    72.         Gizmos.DrawWireSphere(tossPoint.position, 20);
    73.     }
    74. }

    Now, one fix I think I might have found is to replace RotateAround with this...
    Code (CSharp):
    1.  
    2. tossPoint.rotation = Quaternion.LookRotation(transform.forward);
    3. tossPoint.Translate(Vector3.right * Input.GetAxisRaw("Mouse X") * 130f * .02f);
    I am not sure if that will be the result you want, but its all I can think of for now =).
     
  21. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    I just tried it out, for the most part, it does the same as some of the previous code we've done, but it's still the constant problem of having the distance of the point to the player going to far on both ends. We'll have to keep toying with it, but clamping and keeping it in front seems to be two new keys for getting this down.
     
  22. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Did you make sure to uncomment out the clamp code? Did you see the issue I was talking about?
    When I uncommemt out the clamp code and replace the RotateAround code with the 2 lines of code I showed before, everything seems to be fine in terms of staying within the correct distance and in front of the player.
     
  23. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Yeah, I did. It was weired but not the first time I saw it, happened in some other examples where it just floated off. Again, I'm going back to where if(offset.magnitude <= 20) { offset.z = 20;}

    This definitely clamps between 20 and 90, just that when it rotates a bit and it's less than 20, it pops back in front of of the player all oddly. I'm sure there's a way around this. The best answers are usually the simplest! ;)
     
  24. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Just to be extra sure we are seeing the same thing, I made a video showing the bad version and the good version.
    The bad version, which uses RotateAround, shows the issue where the toss object doesnt know what its correct initial state is anymore.
    The good version, which uses the 2 lines of code I showed before, shows that everything seems to be working fine.
    With both of these versions, there might still be a bug hidden somewhere that causes the toss object to start drifting away. It didnt happen when I recorded the video and I dont know if maybe I fixed it somehow, but I saw it when playing around with things. I am not sure if you saw that drift away bug or if you thought I was talking about the toss object not knowing its initial state anymore as seen in the bad version.



    Either way, you are claiming my new clamp code is not properly clamping, but in the video you can see it is clamping just fine. Either you are expecting it to work another way and I dont realize it, or we have something set up differently. My character is starting off facing Vector3.forward and my toss object is starting right on my player object while also facing Vector3.forward.

    Ill post the good version code all together just to make sure we are on the same track.
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class TestNewRotateAroundFollow : MonoBehaviour
    5. {
    6.     public Transform tossPoint;
    7.     public float minDistance = 20f;
    8.     public float maxDistance = 90f;
    9.  
    10.     Vector3 offset;
    11.  
    12.     void Update()
    13.     {
    14.         Vector3 followPosition = transform.position;
    15.         followPosition.y = tossPoint.position.y;
    16.  
    17.         tossPoint.position = followPosition + offset;
    18.  
    19.         tossPoint.rotation = Quaternion.LookRotation(transform.forward);
    20.         tossPoint.Translate(Vector3.right * Input.GetAxisRaw("Mouse X") * 130f * .02f);
    21.         tossPoint.Translate(Vector3.forward * Input.GetAxisRaw("Mouse Y") * 130f * .02f);
    22.  
    23.         offset = (tossPoint.position - followPosition);
    24.         offset = KeepPointInFront(followPosition + offset, transform.position, transform.forward) - followPosition; //assuming transform.forward is the forward direction.
    25.         offset = ClampHorizontalMagnitudeBetween(offset, minDistance, maxDistance); //Must be after KeepPointInFront to avoid jitter
    26.  
    27.         tossPoint.position = followPosition + offset; //Since we moved the tossPoint again, we update its position with the new clamped offset value to remove jitter.
    28.     }
    29.  
    30.     //We dont want to include the Y in this.
    31.     Vector3 ClampHorizontalMagnitudeBetween(Vector3 vector, float minMagnitude, float maxMagnitude)
    32.     {
    33.         float y = vector.y;
    34.         vector.y = 0;
    35.         vector = ClampMagnitudeBetween(vector, minDistance, maxDistance);
    36.         vector.y = y;
    37.         return vector;
    38.     }
    39.  
    40.     Vector3 ClampMagnitudeBetween(Vector3 vector, float minMagnitude, float maxMagnitude)
    41.     {
    42.         if(vector.sqrMagnitude < minMagnitude * minMagnitude)
    43.         {
    44.             return vector.normalized * minMagnitude;
    45.         }
    46.         else if(vector.sqrMagnitude > maxMagnitude * maxMagnitude)
    47.         {
    48.             return vector.normalized * maxMagnitude;
    49.         }
    50.         return vector;
    51.     }
    52.  
    53.     Vector3 KeepPointInFront(Vector3 point, Vector3 target, Vector3 targetForward)
    54.     {
    55.         if(!IsInDirection(point - target, targetForward))
    56.         {
    57.             return target + Vector3.ProjectOnPlane(point - target, targetForward.normalized);
    58.         }
    59.         return point;
    60.     }
    61.  
    62.     bool IsInDirection(Vector3 direction, Vector3 otherDirection)
    63.     {
    64.         return Vector3.Dot(direction.normalized, otherDirection.normalized) > 0;
    65.     }
    66.  
    67.     void OnDrawGizmosSelected()
    68.     {
    69.         Gizmos.color = Color.cyan;
    70.         Gizmos.DrawWireSphere(tossPoint.position, 40);
    71.  
    72.         Gizmos.color = Color.red;
    73.         Gizmos.DrawWireSphere(tossPoint.position, 20);
    74.     }
    75. }
     
  25. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    So, according to your video, the tosspoint cannot pass the player as if there is a wall behind the player. I think that is where we are miscommunicating on. This is what you have:


    This is what I'm after. The wheel!

     
  26. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    The problem I'm having is that the tossPoint does NOT stop at 20, but goes over the player, passes him, and stops at the opposite side of the wheel.
     
  27. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Sorry, I meant to say, "The camera and toss point rotate AROUND the player like a wheel, and the toss point can move back and forth in the blue area"
     
  28. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    For 1, we can change this code
    Code (CSharp):
    1. tossPoint.rotation = Quaternion.LookRotation(transform.forward);
    to this to make sure the tossPoint forward direction will always be the direction from the player to the tossPoint
    Code (CSharp):
    1.  
    2.         Vector3 lookDirection = (tossPoint.position - followPosition).normalized;
    3.         if(lookDirection.sqrMagnitude != 0) //We do this check since if tossPoint and followPosition are in the same spot, LookRotation will throw a warning.
    4.         {
    5.             tossPoint.rotation = Quaternion.LookRotation(lookDirection);
    6.         }
    Now on to our missunderstanding.
    Is this what you are looking for?

    If so, just comment out the KeepPointInFront line of code.
     
  29. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    That's pretty much it! I don't know how half of this stuff works so I'll probably have to simplify it, and this is just a small piece to something even more complex, but at least this step is as close to done as ever. Thanx so much for all your help and bless! :)
     
  30. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    =) no problem, hopefully all goes well. Look out for that weird drifting away bug that I saw happen randomly, but am not sure if I fixed it or not.
     
  31. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Yeah, there isn't any drifting bug going on so I took out some of the y axis restraints, as well as put the clamping function with everything else and got rid of some extra things, thus fixing a slight lag problem. In the end, I got more than what I needed. On to PART 2!!
    Code (csharp):
    1.  
    2. function Update(){
    3.         var followPosition : Vector3 = transform.position;//This Vector follows our player's position
    4.         followPosition.y = tossPoint.position.y;//Excludes the y position and keeps it at its original position
    5.         tossPoint.position = followPosition + offset;//The point's position is equal to the player's, plus the offset
    6.  
    7.         tossPoint.RotateAround(transform.position, Vector3.up, Input.GetAxis("Mouse X") * 130f * .02f);//Rotate around the player
    8.         tossPoint.Translate(Vector3.forward * Input.GetAxis("Mouse Y") * 110f * .02f);
    9.  
    10.         offset = (tossPoint.position - followPosition);
    11.  
    12.         //Manually Clamps
    13.         if(offset.sqrMagnitude < 20 * 20){ offset = offset.normalized * 20; }
    14.         else if(offset.sqrMagnitude > 90 * 90){ offset = offset.normalized * 90; }
    15.    
    16.         tossPoint.position = followPosition + offset;//Update position w/ new clamp offset
    17. }
    18.  function OnDrawGizmosSelected(){
    19.     Gizmos.color = Color.cyan;
    20.     Gizmos.DrawWireSphere(tossPoint.position, 40);
    21.  
    22.     Gizmos.color = Color.red;
    23.     Gizmos.DrawWireSphere(tossPoint.position, 20);
    24. }
    25.  
     
  32. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Now I see the drifting bug that you were talking about, but you know what? It doesn't even matter now. I feel so silly that we went through all this work, when I piratically had the script all along. I didn't realize it until I drew that diagram for you and had a look at it for myself.

    You see, the tossPoint, especially how it rotates and moves with the player, is similar to the more basic version of my camera script here. It moves the same was my camera does, just on the opposite side and doesn't move up and down, but back and forth. All I had to do was rotate and set the position for the player like in the script, and then control the distance with Mouse Y Axis, then clamp the distance. Now it works with no bugs! :D I'll just chalk this all up to a grand learning experience.
    Code (csharp):
    1.  
    2. var tossPoint : Transform;
    3. private var distance : float = 70.0;
    4. private var x : float = 0.0;
    5.  
    6. function Update(){
    7.     x += Input.GetAxis("Mouse X") * xSpeed * .02f;
    8.  
    9.     distance = Mathf.Clamp(distance + Input.GetAxis("Mouse Y") * ySpeed * .02f, 25, 70);
    10.     xSpeed = Input.GetButton("Sights") ? 90f : 130f; ySpeed = Input.GetButton("Sights") ? 90f : 110f;
    11.  
    12.     var rotation = Quaternion.Euler(0, x, 0);
    13.     var position = rotation * Vector3(0,0, distance) + transform.position;
    14.     position.y = 0;
    15.  
    16.     tossPoint.position = position;
    17. }
    18.  
     
    Last edited: Jun 20, 2016
  33. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    I'm still not sure how you guys wasted so much time on this. You could have just set up some child objects. A parent with the rotation controller and a child with the position controller. Your current method breaks the principle of single responsibility.

    Code (CSharp):
    1. public class TossRotationController : MonoBehaviour
    2. {
    3.     void Update()
    4.     {
    5.         float xDelta = Input.GetAxis("Mouse X");
    6.         transform.Rotate(Vector3.up * xDelta);
    7.     }
    8. }
    Code (CSharp):
    1. public class TossPositionController : MonoBehaviour
    2. {
    3.     public float Min;
    4.     public float Max;
    5.  
    6.     public float Range;
    7.  
    8.     void Update()
    9.     {
    10.         Range += Input.GetAxis("Mouse Y");
    11.         Range = Mathf.Clamp(Range, 20, 90);
    12.         transform.localPosition = new Vector3(0, 0, Range);
    13.     }
    14. }
     
  34. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    At least its working now =).

    Well, my first post in this thread was me saying to just use parenting to make things simple, but he replied with a no. I wasnt sure if he tried it out and it wasnt doing what he wanted or something. There was a bit of miscommunication in this thread ^^.
     
  35. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Is this two different scripts? Yeah I tried the parenting thing, but like I said, it does inherent the Y axis which I didn't want. One of the big themes we do when we develop our games is doing big things with small, simple code. So I tried everything in my power to accomplish this in one script in the smallest, most comprehensive format I could. But yes, at least it works lol
     
  36. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Yes.

    Just use the inverse of the parents Y position to keep it fixed at 0(or whatever FixedY should be).
    Code (CSharp):
    1. public class TossPositionController : MonoBehaviour
    2. {
    3.    public float Min;
    4.    public float Max;
    5.    public float Range;
    6.  
    7.    public float FixedY;
    8.  
    9.    void Update()
    10.    {
    11.      Range += Input.GetAxis("Mouse Y");
    12.      Range = Mathf.Clamp(Range, 20, 90);
    13.      transform.localPosition = new Vector3(0, -transform.parent.position.y + FixedY, Range);
    14.    }
    15. }
     
    Last edited: Jun 21, 2016
  37. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    FYI to anyone else following this ... Transform.RotateAround appears to be broken even in Unity2018 :(. Do whatever it takes to avoid it. Positive values give negative rotations around the correct axis, but simultaneously (semi-randomly) anti-rotate the Transform's own local rotation by 180 degrees.

    It appears someone at Unity got confused by Quaternions and added a gimbal-lock bug in their code :(.
     
  38. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    Could you elaborate a little? Is it still broken?

    I applied at a game company before a few years ago, and they wanted me to already know all the ins and outs of rotations, even though they were using Unity3D, which hides the math of quaternions and matrices in a sort of black box of native code that doesn't appear to be on the GitHub repository for the reference repository but is presumably a tad complicated, although I've spent some time figuring out some of the math. I think I may send them the information I've gained as a nice gesture.

    You can basically do the same thing as RotateAround by multiplying an Angle Axis created Quaternion to an existing transform, multiplying it first, something like so:

            Quaternion q = Quaternion.Euler(localObject);
    Quaternion i = Quaternion.Euler(increment);
    Quaternion b_frame = (q * i).normalized;
    Quaternion i_frame = (i * q).normalized;
    if (rotationType == RotationType.BodyFrame)
    t.localRotation = b_frame;
    else
    t.localRotation = i_frame;
    t.localRotation = t.localRotation.normalized;


    Example: Something like this does a 45 degree axis inertial rotation if prepended (I * q). You could make some nice 45 degree tilt rotations if you wanted.

            increment = new Vector3(Mathf.Sqrt(2f) / 2f, Mathf.Sqrt(2f) / 2f, 0f);
    //Quaternion i = Quaternion.AngleAxis(1f, increment);


    Side note: Rotating your X and Y axes the inertial frame way and the Z axis the body frame way will produce results that are similar to adding and subtracting Euler angles, and will produce gimbal lock even with Quaternions or rotation matrices.
     
  39. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    That was a year ago :) I'm not even sure which project it was on.

    I think it more likely I was doing something sublty wrong. e.g. I only fairly recently discovered (in the last few years) that Unity's Quaternions do matrix multiplication in what I'd consider the wrong order (IIRC their order makes sense if you're porting a mathematical algorithm and want it to "look the same on paper as in source code", but doesn't make sense if you're writing OOP code), and so it is possible I was simply multiplying matrices in reverse order by accident - oops! :O.

    Yep - either way, I no longer use any of the convenience methods if possible, and always do my Quaternion work "the long way", because it's guaranteed to be correct (so long as you get one thing right: Unity's matrix multiplication order) - which the (usually under-documented) API methods seemed less reliable with. Documentation is improving a lot, but life's too short to be debugging a Quaternion function / overloaded operator IMHO :).