Results 1 to 2 of 2
  1. #1
    Join Date
    Aug 2010
    Location
    Denmark
    Posts
    233

    Velocity bug with hinge joints forces in C#

    Hi,

    At a local game jam I made a game with a friend in Unity called Suction Co-Op. It's a two-player game where each control the end of a dual suction cup. Read more about the game here: http://gustavdahl.net/suction-co-op.

    It works quite well via hinge joints motors. However, there is a bug where they won't reset their velocity, but instead keeps adding more and more speed.

    It is hard to explain, so I suggest you play it yourself right here: http://gustavdahl.net/Unity_games/Su...WebPlayer.html

    I am having difficulties about isolating the bug; I'm not sure how and when it happens, but when you experience it yourself it is very easy to see (you keep spinning around very fast!).

    One way to reproduce the bug is doing the following when the game plays: Press and hold D and Left Arrow at the same time, while you repeatedly taps the S and Down Arrow. This will make the cups keep on adding force without reseting it.

    As you can probably see, it makes the game very hard because of the high speed. We would love to eliminate the bug.

    We are all novice programmers, and this game was made in under 48 hours, hence the crappy slam code. I would really appreciate if anybody would look at it and see if they can catch the bug.

    Thanks in advance!

    The game uses States and simple keyboard input to make the players move. The script (written in C#) is attached to a cylinder where each end is attached through a hinge joint to an empty gameobject (hence making it stick to the wall).

    I know this is a long one, but since I am not sure where the bug precisely is, I have to copy-paste this long snippet (it is not the whole code): http://pastebin.com/ZfMkXrvv

    Code:
    public enum State
    {
        Suge,
        CanMove,
        Falling,
        DoubleSuge,
    }
    
    // Use this for initialization
    	void Start ()
        {
            Player1State = State.Falling;
            Player2State = State.Falling;
    
            hinges = new HingeJoint[2];
            hinges = GetComponents<HingeJoint>();
    
            hinges[0].connectedBody = empty1.rigidbody;
            hinges[1].connectedBody = empty2.rigidbody;
    	
    	}
    	
    	// Update is called once per frame
    	void Update ()
        {
            // SET STATES
            if (Input.GetKey(KeyCode.S) && player1Touch)
            {
                if (Player1State != State.Suge)
                    justPressedSuge1 = true;
                else
                    justPressedSuge1 = false;
                
                if (justPressedSuge1)
                {
                    // Reset cylinder rigidbody
                    rigidbody.velocity = Vector3.zero;
                    rigidbody.angularVelocity = Vector3.zero;
                }
    
                Player1State = State.Suge;
                transform.FindChild("Lys1").GetComponent<Light>().enabled = true;
                
            }
            else if (!Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.DownArrow))
            {
                Player1State = State.CanMove;
                transform.FindChild("Lys1").GetComponent<Light>().enabled = false;
            }
            else if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.DownArrow) && player1Touch && player2Touch)
            {
                Player1State = State.DoubleSuge;
                Player2State = State.DoubleSuge;
            }
    
            else
            {
                Player1State = State.Falling;
                transform.FindChild("Lys1").GetComponent<Light>().enabled = false;
            }
    
            // SWITCH ON STATES
            switch (Player1State)
            {
                case State.Suge:
    				
    				if (suckingNow1 == false)
    				{
    					suckTimes++;
    					suckingNow1 = true;
    				}
                    // Swallow to world (sticky)
                    hinges[0].connectedBody = null;
    
                    // Motor force = 0
                    JointMotor myForce_suge = hinges[0].motor;
                    myForce_suge.force = 0;
    
                    // Velocity = 0
                    myForce_suge.targetVelocity = 0f;
                    
                    
                    // Set all
                    hinges[0].motor = myForce_suge;
    
    
                    break;
    
                case State.CanMove:	
                    hinges[0].connectedBody = empty1.rigidbody;
    
                    if (Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.D) && Player2State == State.Suge)
                    {
                        // LEFT
                        // Motor target velocity
                        // Can't directly change the property
                        JointMotor myMotor = hinges[0].motor; // make new motor
                        myMotor.targetVelocity = targetVelocity; // assign value
                        hinges[0].motor = myMotor; // put value back in property
    
                        // Motor force 
                        JointMotor myForce = hinges[0].motor;
                        myForce.force = motorForce;
                        hinges[0].motor = myForce;
                    }
                    else if (Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.A) && Player2State == State.Suge)
                    {
                        // RIGHT
    
                        hinges[0].connectedBody = empty1.rigidbody;
    
                        // Motor target velocity
                        // Can't directly change the property
                        JointMotor myMotor = hinges[0].motor; // make new motor
                        myMotor.targetVelocity = -targetVelocity; // assign value
                        hinges[0].motor = myMotor; // put value back in property
    
                        // Motor force 
                        JointMotor myForce = hinges[0].motor;
                        myForce.force = motorForce;
                        hinges[0].motor = myForce;
                    }
                    else
                    {
                        // NOT MOVING
    
                        // Motor force = 0
                        //hinges[0].motor.force = 0; // DON'T WORK
                        JointMotor myForce = hinges[0].motor;
                        myForce.force = 0;
    
                        // Velocity = 0
                        myForce.targetVelocity = 0f;
    
                        // Set all
                        hinges[0].motor = myForce;                 
    
                    }
                    break;
    
                case State.Falling:
    					
    				suckingNow1 = false;
    			
                    // Connect to itself --> falls down
                    hinges[0].connectedBody = empty1.rigidbody;
    
    
                    // Motor force = 0
                    JointMotor myForce_again = hinges[0].motor;
                    myForce_again.force = 0;
                    
                    // Velocity = 0
                    myForce_again.targetVelocity = 0f; // put value back in property
    
                    // Set
                    hinges[0].motor = myForce_again;
    
                    break;
            }

  2. #2
    Join Date
    Jul 2010
    Posts
    21
    I cannot see anything wrong with your code... Have you thought of applying torques manually through script? You could do something like attach each player's cup to the same parent (I'll refer to this as pObj). You could attach a rigidbody and collider to pObj, and shift its center of mass through script based on which suction cup(s) is/are attached. You might need to set drag (not angular drag) to Infinity while the cup is attached a cup is attached. The torque could then be applied in FixedUpdate based on the other player's horizontal axis. When the suction is released, you could set the drag to its original amount, set the center of mass to its original position, then let PhysX take care of the rest.
    A witty saying proves nothing!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •