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. Dismiss Notice

Knockback Calculations

Discussion in 'Scripting' started by Dr_Horrible, May 27, 2014.

  1. Dr_Horrible

    Dr_Horrible

    Joined:
    May 27, 2014
    Posts:
    2
    Hi guys,
    I am having some problems with my knockback function.

    What it's supposed to do: When colliding with the CharacterController, it should be thrown back distanceX in the direction it came from.
    What it does: The CC is thrown back the direction he came from, but the distance varies.

    I looked up a knockback script and edited it to my needs, here's what i got:

    Code (csharp):
    1.  
    2. #pragma strict
    3.  
    4. var KnockbackForce:float = 5;
    5. var JumpForce : float = 0.5;
    6.  
    7.  
    8. //Knockback
    9. function OnTriggerEnter(col:Collider){
    10.  
    11.     if (col.tag == "Player"){
    12.        var dir = (col.transform.position - transform.position); //this was .normalized in the orginal  
    13.            dir.y =  JumpForce;                                  //so the player gets knocked up as well
    14.            dir = dir.normalized;                                //normalising here, so dir.y doesn't go unnomalized
    15.        var charMotor = col.GetComponent(CharacterMotor);
    16.        charMotor.SetVelocity(dir*KnockbackForce);
    17.        Debug.Log(dir.x + " / " + dir.y + " / " + dir.z);
    18.     }
    19. }
    20.  
    21. function Update () {
    22.  
    23. }
    24.  
    As i understood it, the normalised vector should have a magnitude of one, meaning v.x + v.y + v.z = 1.
    The Debug.Log gives back nothing like that. Sometimes the axes add up to ~0, sometimes they don't.
    naturally, the distance the CC is moved, varies wildly.
    Where is my error?

    Thank you in advance,
    Dr H.

    In case it matters:
    The Script is attached to a 1 * 10 * 10 cube, at the end of a configurable joint chain, that form a pendulum together.


    EDIT

    Ok, turns out the problem is indeed the cube.
    As the distance is calculated from the center rather than the surface, the values are smaller if the trigger is entered on the flat side.
    This obviously results in a shorter knockback.

    So my new question is this:
    How can i create a knockback-distance, that is the same wherever the trigger is entered?
    I thought about joining the distance from the cubes center to the surface to the dir.
    But just adding them won't do the trick.

    I know i could just go with a 10*10*10 cube collider or a sprere collider, but this is going to be a 3rd person game, so you will see quite well, that the character wasn't hit by the model, but only by some "invisible force".
     
    Last edited: May 27, 2014
  2. Zaladur

    Zaladur

    Joined:
    Oct 20, 2012
    Posts:
    392
    Close but not quite. The magnitude of a vector v is the square root of (v.x[SUP]2[/SUP] + v.y[SUP]2[/SUP] +v.z[SUP]2[/SUP]). I'm willing to bet your issue is that you are adding jump force in before normalizing. This will alter your xz values in the normalized vector. If you want a uniform xz knockback and a uniform y knockup, try something like this:

    Code (csharp):
    1.  
    2. var dir = (col.transform.position - transform.position);
    3. dir.y=0; //It doesnt seem like you want the height of the collider to determine if the player is shoved into the ground or shot into the sky.
    4. dir = dir.normalized;   //now you have a uniform xz direction of knockback away from the center of the object.
    5. dir.y =  JumpForce; //now add a uniform 'knockup' force  
    6.  
    If I have misinterpreted your goals, let me know.
     
  3. Dr_Horrible

    Dr_Horrible

    Joined:
    May 27, 2014
    Posts:
    2
    Thank you for the reply.
    As mentioned in my edit, the problem seems to be the collider.
    Since it calculates the vector for the direction from its center, it gives back different results as to where it's colliding with the player.
    I could not figure out a proper way to fix this with the setup i had.

    However, the knockback is applied by a trap that covers the whole width of a narrow corridor, so the trigger can't be entered from extreme angles.
    Additionaly i changed my model from a flat board to a cylinder.
    Thus, the variations in the direction vector aren't as large as before.
    So i guess this about works out for me.

    But there's more!
    I wanted the knockback force to be proportional to the speed of my pendulum.
    (Because obviously it has more power on the first swing than when it's almost stopped)

    To achieve this, i initially wanted to use the rigidbody.velocity.
    But i logged the values during the swing and they weren't as expected.
    So i ended up using a timer to determine the knockback force as well as if the pendulum is destroyable.
    This works fine a good 70% of the time.
    However, there are certain cases that get the pendulum to slow down or stop faster than intended.
    In those cases there is a knockback, even if the pendulum already stopped.
    This is not pretty and seems somewhat weird in the flow of the game.
    Is there a better solution to this?
    Maybe a good way to handle rigidbody.velocity i didn't think of?
    Looking forward to any reply!

    Dr. H

    Oh, also, here is what i work with at the moment:
    Code (csharp):
    1.  
    2. #pragma strict
    3. var KnockbackForce : float = 20.0;
    4. var JumpFactor : float = 0.5;
    5. var destructable : boolean = false;
    6. var hitpoints : int = 50;
    7. var timer : float = 15.0;
    8. var Activated : boolean = false;
    9.  
    10. //be sure gravity is turned off
    11. rigidbody.useGravity = false;
    12.  
    13.  
    14. function FixedUpdate () {
    15.     if (Activated == true){
    16.         timer -= 1*Time.deltaTime;
    17.     }
    18. }
    19.  
    20. function Update () {
    21.  
    22.     if (Activated == true){
    23.         rigidbody.useGravity = true;
    24.        
    25.         if (timer > 0){
    26.             KnockbackForce = 5 + (timer/3);
    27.             Debug.Log(KnockbackForce);
    28.            
    29.         }else if (timer <= 0){
    30.             destructable = true;
    31.             Debug.Log("I'm destructable now");
    32.         }
    33.        
    34.        
    35.         //Destroy if hp <= 0
    36.         if (hitpoints <= 0){
    37.         Destroy(gameObject);
    38.         }
    39.  
    40.     }
    41.  
    42. }
    43.  
    44.  
    45. //Activation
    46. function TrapActivated () {
    47. Activated = true;
    48. }
    49.  
    50.  
    51. //Knockback
    52. function OnTriggerEnter(col:Collider){
    53.  
    54.     if (col.tag == "Player"){  
    55.         if (destructable == false){
    56.            var dir = (col.transform.position - transform.position); //this was .normalized in the orginal  
    57.                dir.y =  JumpFactor;                                 //so the player gets knocked up as well
    58.                dir = dir.normalized;                                //normalising here, so dir.y doesn't go unnomalized
    59.            var charMotor = col.GetComponent(CharacterMotor);
    60.            charMotor.SetVelocity(dir * KnockbackForce);
    61.           // Debug.Log(dir.x + " / " + dir.y + " / " + dir.z);
    62.         }
    63.     }
    64. }
    65.  
    66.  
     
    Last edited: May 31, 2014