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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question AddForce not working properly ( strange behaviour )

Discussion in 'Physics' started by FabioGavinelli, Aug 23, 2021.

  1. FabioGavinelli

    FabioGavinelli

    Joined:
    Nov 24, 2018
    Posts:
    10
    Hi all I encountered a strange behaviour that maybe someone can help me understand.
    I have a player that I can move aruond (player has rigid body non kinematic) and I want to implement a simple trap that when the player hit bounces him back and damage him.

    The problem is:
    - the first AddForce works only if I add another one after it
    - if I use only the second AddForce it works fine alone
    - if I use only the first AddForce it doesn't work and the player stay still in position
    - if I use both of the AddForce the second one is not performed but the first one is performed

    Code (CSharp):
    1.  
    2. private void OnCollisionEnter(Collision collision)
    3.     {
    4.         GameObject other = collision.gameObject;
    5.  
    6.         if(other.tag == "Player")
    7.         {
    8.             Vector3 playerPos = other.transform.position;
    9.             Vector3 trapPos = transform.position;
    10.             Vector3 pushForceDirection = playerPos - trapPos; // evaluate push dir
    11.  
    12.             Rigidbody playerRB = other.GetComponent<Rigidbody>();
    13.             if (playerRB)
    14.             {
    15.                 playerRB.AddForce(pushForceDirection * 100, ForceMode.Impulse); // this is what i want
    16.                 playerRB.AddForce(Vector3.up * 100, ForceMode.Impulse); // this is for test
    17.             }
    18.             else
    19.             {
    20.                 Debug.LogError("No rigidbody found on player");
    21.             }
    22.  
    23.         }
    24.     }
    25.  
     
  2. mustafacomert00

    mustafacomert00

    Joined:
    Feb 17, 2020
    Posts:
    5
    In some cases pushForceDirection can be (0, 0, 0), I recommend observing the value of pushForceDirection while running these tests.
     
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,434
    I wouldn't put AddForce() within OnCollisionEnter().

    Instead, raise some flag and store the relevant data in class variables (i.e. resolveCollision = true, otherObject = collision.gameObject). Then check for that flag within FixedUpdate(). If the flag is true, then resolve the collision, apply AddForce(), and clear the flag (resolveCollision = false), everything within FixedUpdate().
     
  4. FabioGavinelli

    FabioGavinelli

    Joined:
    Nov 24, 2018
    Posts:
    10
    I checked the values and the vector is always not zero


    Isn't this polling system more computationally expensive??
    Why you wouldn't put AddForce() whitin OnCollisionEnter()?? (this question may be very basic but I would learn if there is something that I don't know)
     
  5. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,434
    No, it's just checking for a bool. That doesn't have any impact.

    Because OnCollisionEnter() might be called several times per physics update depending of the situation. For example, if the object collides with two other objects simultaneously. With the approach I suggested you ensure that a collision raises exactly one AddForce() per physics update, regardless the number of colliders or any other possible corner cases.
     
  6. FabioGavinelli

    FabioGavinelli

    Joined:
    Nov 24, 2018
    Posts:
    10
    @Edy Thanks for your replies and suggestions. I tried implementing what you suggested but I still have the same problem.

    I'm going to leave here a copy of the project so if someone want is free to see the problem in action and maybe the solution is easier to solve like this. Also maybe I'm making a noob error that is in another part of the project.

    [Project File]
    https://drive.google.com/file/d/1zxpi90o2IPJ5Si13zzWXm0XrgzzxlYzl/view?usp=sharing
    [Instructions]
    To replicate the problem just go on "RazorTrap" script and try comment the AddForce on the up vector
     
  7. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    Whenever you multiply a direction by some scalar value you probably want to make sure it is normalized first. This bit of code:
    pushForceDirection * 100
    will produce unpredictable results unless you normalize pushForceDirection. See https://docs.unity3d.com/ScriptReference/Vector3.Normalize.html

    I can imagine a situation where the impulse you assign as a result of this non-normalized calculation is small enough to the point where ground friction just absorbs all of it. That would explain why giving another impulse in the upward direction suddenly solves it - because then the character lifts off the ground and there is no more friction to eat horizontal movement.