Search Unity

Creating a Repulsion System

Discussion in 'Scripting' started by ATLAS-INTERACTIVE, Sep 28, 2016.



    Mar 3, 2014
    For the past few days, I have been working on a repulsion system but have been having a lot of trouble with it.
    According to our SVN I have made 20 modifications to this script, trying to get it working as expected.

    What I am trying to achieve is similar to the Repulsion Gel from Portal 2, where a small amount of upward force is employed to the player on collision, and when jumping down onto it, the force is inverted so your downward force becomes upward so you end up at roughly the same height again, but this appears to be harder than I thought.

    I have tried adding force although repeated jumping and landing causes a steady increase in force, which isn't much use as after 10 or so you exceed the camera's far clipping plane.

    In Portal 2, the force does not exceed a specific amount and does not add up the more you jump on it.

    As it is hard to explain, there are a few videos which show some in-game gameplay below:

    This is what I have at the moment:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    4. public class JumpPadBehaviour : MonoBehaviour
    5. {
    6.     [SerializeField]
    7.     private string playerTag;//set to Player in inspector
    8.     [SerializeField]
    9.     private Vector3 direction;
    10.     [SerializeField]
    11.     private float force;
    12.     [SerializeField]
    13.     private float maxVelocity = 20f;
    15.     void OnTriggerEnter(Collider collider)
    16.     {
    17.         if (collider.gameObject.CompareTag(this.playerTag))
    18.         {
    19.             Rigidbody rigidBody = collider.gameObject.GetComponent<Rigidbody>();
    20.             if (rigidBody != null)
    21.             {
    22.                 //rigidBody.velocity = rigidBody.velocity + this.direction * this.force;
    23.                 rigidBody.AddForce(this.direction * this.force, ForceMode.Impulse);
    24.                 //rigidBody.velocity = transform.up * rigidBody.velocity.magnitude;
    25.                 rigidBody.velocity = Vector3.ClampMagnitude(rigidBody.velocity, maxVelocity);
    26.             }
    27.         }
    28.     }
    29. }
  2. jmjd


    Nov 14, 2012
    Have you tried just reflecting the player's velocity, using Vector3.Reflect, using the jump pad's direction as the normal? Then I would just check to make sure the reflected velocity has a minimum magnitude, so that you still get some force when you just step onto it.
  3. takatok


    Aug 18, 2016
    Two things are going on here. First is understand the difference between ForceMode.Force (the default and what you get if you don't add this parameter) and ForceMode.Impulse

    ForceMode.Force is the amount of force per second
    ForceMode.Impulse is the amount of force per FRAME

    So assuming your running at 50 frames of physics per second. Only 1 frame of AddForce is being called in OnTriggerEnter. So you getting 50x the force applied by using ForceMode.Impulse

    Secondly, these AddForces aren't immediately calculated. They are queued up to be used by the physics engine and will be applied during the next Physics tick, and will be done before your next FixedUpdate.
    So your code is doing this:
    • Add a really big force with Force.Impulse
    • Clamp the current velocity to 20
    • Pass control back to Unity that now performs a physics Update
    • Adds the huge force to your object and its velocity exceeds 20
    You can try going back to a regular ForceMode.Force and /or also change your clamping code to:
    Code (CSharp):
    1. // Add this code to anything with a RigidBody to limit its
    2. // max velocity
    3. void FixedUpdate()
    4. {
    5. rigidBody.velocity = Vector3.ClampMagnitude(rigidBody.velocity, maxVelocity);
    6. }
    Note you would add the above code to the player NOT the jumpad script you've shown above.