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!
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.
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?
Well I guess you could count the time a player’s vertical velocity is negative?
float fallTime = 0;
bool hasFallen = false;
void Update() {
// If the velocity is negative
if (GetComponent<Rigidbody>().velocity.y < 0) {
// Count the time as "fall time"
fallTime += Time.deltaTime;
// The player "has fallen" I guess
hasFallen = true;
// As soon as the velocity is not negative, if the player fell, even a bit
} else if (hasFallen) {
// If the player has fallen a considerable amount of time
if (fallTime > 1) {
// Hurt the player based on how long they fell
playerHealth -= fallTime;
}
// Reset fall measurements
hasFallen = false;
fallTime = 0;
}
}
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:
https://www.youtube.com/watch?v=ZwD1UHNCzOc
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 ![]()
Thanks everyone! Going to see what I can do now!
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 =
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FallingCheck : MonoBehaviour
{
// See Gunging's post
float fallTime = 0;
bool hasFallen = false;
// Defines health bar object (I use the progressbar asset)
public ProgressBarCircle PbC;
GameObject player;
private void Start()
{
// Sets health
PbC.BarValue = 100;
// Sets up player the name of my player
player = GameObject.Find("FPSController");
}
void Update()
{
// If player is above 10 on the y axis
if (player.transform.position.y > 10)
{
// See Gunging's post
fallTime += Time.deltaTime;
// See Gunging's post
hasFallen = true;
}
else if (hasFallen)
{
// If the player has fallen a considerable amount of time
if (fallTime > 1)
{
// Hurt the player based on how long they fell
// Lose health round to nearest whole number and multiply by 5 (for more health lost)
PbC.BarValue -= Mathf.Round(fallTime * 1) / 1 * 5;
}
// Reset fall measurements
hasFallen = false;
fallTime = 0;
}
}
}
Hope this helps anyone with the same problems. Big thanks to @Gunging and @Yoreki
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.