Search Unity

Return player to original rotation after swinging on a HipJoint2D

Discussion in '2D' started by JasonKnight, May 28, 2015.

  1. JasonKnight

    JasonKnight

    Joined:
    May 15, 2015
    Posts:
    4
    So I have this code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerScript : MonoBehaviour {
    5.  
    6.     public float             speed                         = 50f;
    7.     public float             jump_power                     = 1.0f;
    8.     public float             jump_boost                     = 1.0f;
    9.     public bool             grounded                     = true;
    10.     public float             max_speed                     = 3;
    11.     public Rigidbody2D         rb2d                         = null ;
    12.     public bool             facing_right                 = true;
    13.     public bool             touching_swing_node         = false;
    14.     public bool                in_swing_mode                = false;
    15.     public GameObject         swing_node                     = null;
    16.     public HingeJoint2D     joint                        = null;
    17.     public Quaternion        before_swing;
    18.  
    19.     // Use this for initialization
    20.     void Start () {
    21.         rb2d = GetComponent<Rigidbody2D>();
    22.     }
    23.     void Flip() {
    24.         GameObject g = GameObject.FindWithTag ("PlayerSprite");
    25.         if (g) {
    26.             facing_right = !facing_right;
    27.             Vector3 the_scale = g.transform.localScale;
    28.             the_scale.x *= -1;
    29.             g.transform.localScale = the_scale;
    30.         }
    31.  
    32.     }
    33.     // Update is called once per frame
    34.     void Update () {
    35.         if (Input.GetButtonDown ("Jump") && grounded) {
    36.  
    37.             rb2d.velocity = new Vector2 (rb2d.velocity.x, jump_power);
    38.  
    39.  
    40.         }
    41.         if (Input.GetButtonUp("Jump") && grounded == false) {
    42.          
    43.             rb2d.velocity = new Vector2 (rb2d.velocity.x, 0.0f);
    44.              
    45.         }
    46.         if (Input.GetButtonDown ("Fire1")) {
    47.             print ("Fire1 pressed!");
    48.             if (touching_swing_node && !in_swing_mode) {
    49.                 print ("We are touching a SwingNode");
    50.                 if (swing_node != null) {
    51.                     print ("And we have a SwingNode!");
    52.                     // Oh goody, now we can swing.
    53.                     Swing();
    54.                 }
    55.             } else if (in_swing_mode) {
    56.                 StopSwing();
    57.             }
    58.  
    59.  
    60.         }
    61.  
    62.  
    63.     }
    64.     void FixedUpdate() {
    65.         float h = Input.GetAxis ("Horizontal");
    66.         rb2d.AddForce (Vector2.right * speed * h);
    67.         float tmax = max_speed;
    68.         if (in_swing_mode)
    69.             tmax = tmax * 1.8f;
    70.         float vel_x = rb2d.velocity.x;
    71.         if (h > 0 && !facing_right)
    72.             Flip ();
    73.         else if (h < 0 && facing_right)
    74.             Flip ();
    75.         if (vel_x > tmax) {
    76.             rb2d.velocity = new Vector2 (tmax, rb2d.velocity.y);
    77.  
    78.         } else if (vel_x < -tmax) {
    79.             rb2d.velocity = new Vector2 (-tmax, rb2d.velocity.y);
    80.  
    81.         }
    82.  
    83.  
    84.     }
    85.     void Swing() {
    86.         if (in_swing_mode == true) {
    87.             print ("in_swing_mode is true!");
    88.             return;
    89.         }
    90.  
    91.         print ("Name is: " + swing_node.name);
    92.         before_swing = transform.localRotation;
    93.         in_swing_mode = true;
    94.         if (joint == null) {
    95.             joint = gameObject.AddComponent<HingeJoint2D>();
    96.             joint.connectedBody = swing_node.GetComponent<Rigidbody2D>();
    97.             //joint.distance = 2.0f;
    98.         }
    99.         float vel_x = rb2d.velocity.x;
    100.         Vector2 new_force = new Vector2 ();
    101.         if (vel_x > max_speed) {
    102.             new_force = new Vector2 (max_speed * 1.2f, rb2d.velocity.y);
    103.         } else if (vel_x < -max_speed) {
    104.             new_force = new Vector2 (-max_speed * 1.2f, rb2d.velocity.y);
    105.         }
    106.         rb2d.AddForce(new_force);
    107.  
    108.     }
    109.     void StopSwing() {
    110.         print ("Destroying Joint!");
    111.         Destroy (joint);
    112.  
    113.         in_swing_mode = false;
    114.         transform.localRotation = before_swing;
    115.     }
    116.  
    117. }
    118.  

    And it works.

    For reference, here is the SwingNodeScript:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SwingNodeScript : MonoBehaviour {
    5.     // Use this for initialization
    6.     void Start () {
    7.  
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update () {
    12.  
    13.     }
    14.     void OnTriggerEnter2D(Collider2D col) {
    15.         GameObject po = GameObject.FindWithTag ("Player");
    16.         PlayerScript p = po.GetComponent<PlayerScript> ();;
    17.         p.swing_node = gameObject;
    18.         p.touching_swing_node = true;
    19.         print ("Entering SwingNode");
    20.     }
    21.     void OnTriggerExit2D(Collider2D col) {
    22.         GameObject po = GameObject.FindWithTag ("Player");
    23.         PlayerScript p = po.GetComponent<PlayerScript> ();
    24.         p.touching_swing_node = false;
    25.         p.swing_node = null;
    26.         print ("Leaving SwingNode");
    27.     }
    28. }
    29.  
    And this is working more or less to my satisfaction,

    For some reason the post above was cut off, and I can't seem to edit it.

    Essentially the problem is this: The player's rotation goes crazy, and when they land after releasing the swing, they could be upside down, on their side etc.

    If I set the localRotation to Quaternion.identity, this fixes the rotation, but causes the player to shoot up into the sky and then land back down.

    I just want, once the player releases the swing to return the head to the upright position, and the feet pointing down.
     
    Last edited: May 28, 2015
  2. LiberLogic969

    LiberLogic969

    Joined:
    Jun 29, 2014
    Posts:
    138
    Have tried setting the RigidBody2D.fixedAngle to true?
     
  3. JasonKnight

    JasonKnight

    Joined:
    May 15, 2015
    Posts:
    4
    Yes, that works! Thank you. Have to set it in code, when swinging starts I set to false, and when done set to true.
     
  4. JasonKnight

    JasonKnight

    Joined:
    May 15, 2015
    Posts:
    4
    Well, it kind of works, the other issue is that when I restore the original rotation, the player "teleports" to a different position.

    This comes about with: transform.rotation = before_swing;

    I thought a Quaternion represented a rotation, not a position?
     
  5. LiberLogic969

    LiberLogic969

    Joined:
    Jun 29, 2014
    Posts:
    138
    Hmm, I'm not really sure why its altering the position, I believe your right about Quaternions only storing rotation values. It could potentially be related to the and parent object the player is a part of (if this is the case). Maybe you could try to store the rotation value on the Z axis since that's all you will need in a 2D game. You could try something like this :

    Code (CSharp):
    1. // When you attach the joint
    2. originalZRotation = player.transform.rotation.eulerAngles.z; //local float field
    3.  
    4. // When the player is released from the joint
    5. player.transform.rotation = Quaternion.Euler(new Vector3(0, 0, originalZRotation));
     
  6. JasonKnight

    JasonKnight

    Joined:
    May 15, 2015
    Posts:
    4
    Here is the latest code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerScript : MonoBehaviour {
    5.  
    6.     public float             speed                         = 50f;
    7.     public float             jump_power                     = 1.0f;
    8.     public float             jump_boost                     = 1.0f;
    9.     public bool             grounded                     = true;
    10.     public float             max_speed                     = 3;
    11.     public Rigidbody2D         rb2d                         = null ;
    12.     public bool             facing_right                 = true;
    13.     public bool             touching_swing_node         = false;
    14.     public bool                in_swing_mode                = false;
    15.     public GameObject         swing_node                     = null;
    16.     public HingeJoint2D     joint                        = null;
    17.     public float            before_swing                = 0.0f;
    18.     public GameObject        sprite                        = null;
    19.  
    20.     // Use this for initialization
    21.     void Start () {
    22.         rb2d = GetComponent<Rigidbody2D>();
    23.  
    24.     }
    25.     void Flip() {
    26.         if (sprite) {
    27.             facing_right = !facing_right;
    28.             Vector3 the_scale = sprite.transform.localScale;
    29.             the_scale.x *= -1;
    30.             sprite.transform.localScale = the_scale;
    31.         }
    32.  
    33.     }
    34.     // Update is called once per frame
    35.     void Update () {
    36.         if (Input.GetButtonDown ("Jump") && grounded) {
    37.  
    38.             rb2d.velocity = new Vector2 (rb2d.velocity.x, jump_power);
    39.  
    40.  
    41.         }
    42.         if (Input.GetButtonUp("Jump") && grounded == false) {
    43.            
    44.             rb2d.velocity = new Vector2 (rb2d.velocity.x, 0.0f);
    45.                
    46.         }
    47.         if (Input.GetButtonDown ("Fire1")) {
    48.             print ("Fire1 pressed!");
    49.             if (touching_swing_node && !in_swing_mode) {
    50.                 print ("We are touching a SwingNode");
    51.                 if (swing_node != null) {
    52.                     print ("And we have a SwingNode!");
    53.                     // Oh goody, now we can swing.
    54.                     Swing();
    55.                 }
    56.             } else if (in_swing_mode) {
    57.                 StopSwing();
    58.             }
    59.  
    60.  
    61.         }
    62.  
    63.  
    64.     }
    65.     void FixedUpdate() {
    66.         float h = Input.GetAxis ("Horizontal");
    67.         rb2d.AddForce (Vector2.right * speed * h);
    68.         float tmax = max_speed;
    69.         if (in_swing_mode)
    70.             tmax = tmax * 1.8f;
    71.         float vel_x = rb2d.velocity.x;
    72.         if (h > 0 && !facing_right)
    73.             Flip ();
    74.         else if (h < 0 && facing_right)
    75.             Flip ();
    76.         if (vel_x > tmax) {
    77.             rb2d.velocity = new Vector2 (tmax, rb2d.velocity.y);
    78.  
    79.         } else if (vel_x < -tmax) {
    80.             rb2d.velocity = new Vector2 (-tmax, rb2d.velocity.y);
    81.  
    82.         }
    83.  
    84.     }
    85.     void Swing() {
    86.         if (in_swing_mode == true) {
    87.             return;
    88.         }
    89.  
    90.         before_swing = transform.rotation.eulerAngles.z;
    91.         in_swing_mode = true;
    92.         if (joint == null) {
    93.             joint = gameObject.AddComponent<HingeJoint2D>();
    94.             joint.connectedBody = swing_node.GetComponent<Rigidbody2D>();
    95.             //joint.distance = 2.0f;
    96.         }
    97.         rb2d.fixedAngle = false;
    98.  
    99.     }
    100.     void StopSwing() {
    101.  
    102.         Destroy (joint);
    103.  
    104.         in_swing_mode = false;
    105.         rb2d.fixedAngle = true;
    106.         transform.rotation = Quaternion.Euler(new Vector3(0, 0, before_swing));
    107.  
    108.     }
    109.  
    110. }
    111.  
    And here is a video of the bug: http://jolierouge.net/wp-content/uploads/2015/05/UnityTwtichy.avi

    Basically, around the player I have a huge circle collider, when it triggers, it sets the boolean touching_swing_node. If you press Fire1, then it starts the swing, if you push the arrow keys you can increase the swing. when you press the Fire1 again, it "releases" and that is where that twitchyness is showing up. If you release on the close side of the swing node, it's less pronounced, but if you are on the far(right) side and you release, you jump all the way back to the left side.

    It's driving me batty.