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

Attempting to make a Fall Damage system.

Discussion in 'Scripting' started by TheUltimateRealDude1, Nov 10, 2019.

  1. TheUltimateRealDude1

    TheUltimateRealDude1

    Joined:
    Sep 27, 2019
    Posts:
    10
    Hello! I have tried many different ways to create a fall damage system, but they've all failed. I am using the Standard Assets FPSController thing as my Character Controller. Please somebody help! If someone could send a full script, that would be great!
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    What did you try? What did not work as you expected?
    If you are using a CharacterController, then you probably implemented your own way to track velocities of that character. Gravity increases the downwards velocity, thus your falling speed. So what speaks against using the downwards velocity (or total velocity) as basis for your fall damage? You could either use the value itself, scale it somehow, or write your own function to handle fall damage, but that's only a 'minor' game design choice then.
     
  3. TheUltimateRealDude1

    TheUltimateRealDude1

    Joined:
    Sep 27, 2019
    Posts:
    10
    Well, I'm not the best at scripting yet, and I have tried many ways of doing that (btw I forgot to tell you I have my own health bar system) so could you possibly give me an example I could work off of?
     
  4. Gunging

    Gunging

    Joined:
    Sep 6, 2016
    Posts:
    139
    Well I guess you could count the time a player's vertical velocity is negative?

    Code (CSharp):
    1. float fallTime = 0;
    2. bool hasFallen = false;
    3.  
    4. void Update() {
    5.   // If the velocity is negative
    6.   if (GetComponent<Rigidbody>().velocity.y < 0) {
    7.     // Count the time as "fall time"
    8.     fallTime += Time.deltaTime;
    9.  
    10.     // The player "has fallen" I guess
    11.     hasFallen = true;
    12.  
    13.   // As soon as the velocity is not negative, if the player fell, even a bit
    14.   } else if (hasFallen) {
    15.  
    16.     // If the player has fallen a considerable amount of time
    17.     if (fallTime > 1) {
    18.       // Hurt the player based on how long they fell
    19.       playerHealth -= fallTime;
    20.     }
    21.  
    22.     // Reset fall measurements
    23.     hasFallen = false;
    24.     fallTime = 0;
    25.   }
    26. }
     
    AntonioModer likes this.
  5. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    While this may work for specific games,it's a bit over-complicated and has weaknesses. Imagine, for example, that we have a low-gravity environment, where we fall down 10 seconds with a downwards velocity of 0.1cm/s. The fall damage should be neglectable, but since we only counted the time it would most likely be huge.
    What we need to do instead, is calculate the impact velocity. Thus, the damage (like in real life) depends on the speed of collision, or in other words the downwards acceleration of gravity over time - which increases downwards velocity accordingly and correctly, and thus scales the damage properly.

    I guess posting a working character controller is a bit much, so i'll link you a great tutorial by Sebastian Lague instead:


    If you follow it, you will end up with a CharacterController based movement, which tracks the y-axis velocity. The implementation of jumping and gravity happens in episode 9 iirc, but i would recommend you to watch and follow along with the whole thing from episode 7, where he starts implementing the CharacterController.
    The velocityY is applied every single frame. Things like jumping and gravity add a positive or negative value to it. So if you jump upwards with some strength, gravity will slow you down and eventually reverse your velocity and make you fall down again. When you fall of a tall building, gravity accelerated you downwards at an increasing rate - so the higher the building, the larger (negative) velocityY you end up with.
    Thus, we can use the negative value of velocityY as basis for your fall damage. The higher it is, the higher your fall damage should be. Depending on how much health your characters have, how much fall damage you want to apply, if there are caps or not.. and some other design decisions, you could now scale the velocityY value up or down, or clamp it to a range of numbers, or do any other thing with it to get the behavior you want. That is up to your game design, but at least the damage scales properly with fall speed, which is what you generally want.

    Hope this helps now :)
     
    GoliathAT likes this.
  6. TheUltimateRealDude1

    TheUltimateRealDude1

    Joined:
    Sep 27, 2019
    Posts:
    10
    Thanks everyone! Going to see what I can do now!
     
  7. TheUltimateRealDude1

    TheUltimateRealDude1

    Joined:
    Sep 27, 2019
    Posts:
    10
    Ok, so I call this case closed! I was able to create my own script based on other scripts that I found, Including @Gunging 's. Here is the script, in case anyone wants to use it =

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class FallingCheck : MonoBehaviour
    6. {
    7.     // See Gunging's post
    8.     float fallTime = 0;
    9.     bool hasFallen = false;
    10.     // Defines health bar object (I use the progressbar asset)
    11.     public ProgressBarCircle PbC;
    12.     GameObject player;
    13.  
    14.     private void Start()
    15.     {
    16.         // Sets health
    17.         PbC.BarValue = 100;
    18.         // Sets up player             the name of my player
    19.         player = GameObject.Find("FPSController");
    20.     }
    21.  
    22.  
    23.     void Update()
    24.     {
    25.  
    26.         // If player is above 10 on the y axis
    27.         if (player.transform.position.y > 10)
    28.         {
    29.             // See Gunging's post
    30.             fallTime += Time.deltaTime;
    31.  
    32.             // See Gunging's post
    33.             hasFallen = true;
    34.         }
    35.  
    36.         else if (hasFallen)
    37.         {
    38.  
    39.             // If the player has fallen a considerable amount of time
    40.             if (fallTime > 1)
    41.             {
    42.                 // Hurt the player based on how long they fell
    43.                 // Lose health      round to nearest whole number and multiply by 5 (for more health lost)
    44.                 PbC.BarValue -= Mathf.Round(fallTime * 1) / 1 * 5;
    45.             }
    46.  
    47.             // Reset fall measurements
    48.             hasFallen = false;
    49.             fallTime = 0;
    50.         }
    51.  
    52.  
    53.     }
    54. }
    Hope this helps anyone with the same problems. Big thanks to @Gunging and @Yoreki
     
    yojancuchau and billionlioe like this.
  8. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,386
    Not that there's anything wrong with it, necessarily, but I'm curious as to why you chose to put this script on a separate object other than the player itself.