c# Unity3D Special Falldamage - c#

So i am coding in Unity3D and i need to make so that i loose half of my maximum health which is 100 if my jump is over 1.533287.
My problem is that my player can double jump and is supposed to land on platforms higher than the start place of the jump.
}
void Start()
{
}
public int doubleJump = 0;
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
public int health = 100;
public float maxHeight;
public float height;
public int maxHealth = 100;
private Vector3 moveDirection = Vector3.zero;
// Update is called once per frame
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded)
{
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButtonDown("Jump"))
{
moveDirection.y = jumpSpeed;
}
doubleJump = 0;
}
if (!controller.isGrounded)
{
if (doubleJump == 0)
{
if (Input.GetButtonDown("Jump"))
{
moveDirection.y = jumpSpeed;
doubleJump = 1;
}
}
}
if (maxHeight < height) //This sets the maximum height
{
maxHeight = height;
}
height = transform.position.y;
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}

I would modify your code to use your player's rigidbody.
For example... if the player's velocity.y is in the positives, then he's moving upwards.
If the player's velocity.y is in the negatives, then it means they are falling.
Make it so that if the velocity.y is below a certain value, then they take fall damage.
That way if you player doubles jumps towards a platform, when they land the velocity.y might be a small negative number. However if they jumped off of that high platform, they'd have a longer fall time which means a larger negative velocity.
Here's an example, although I don't know what scale you're working in so the numbers may be inaccurate for your scene.
Your player double jumps towards a platform, and when they reach their maximum height their velocity.y is now equal to 0.
As they start falling, velocity.y dips into the negatives. This means that when your player lands, they'll have a negative velocity. Let's say -5.
You can make your code say something similar to
if(playerRigidBody.velocity.y <= -10)
{
FallDamage();
}
So if your player has been falling for a little while, they'd take fall damage. However since when they landed on your platform at a velocity of -5 they wouldn't take fall damage... and if they jump off the platform and land on the ground below their velocity will more than likely be below -10 in the example.
Hopefully this helps you figure this out!

Related

Why is my character's horizontal velocity lost when jumping?

GOAL
I'm relatively new to Unity and I want my character to be able to run and jump at the same time causing the character to go up diagonally.
PROBLEM
However after making some adjustments to give the character some acceleration, the jump seems to clear all existing velocity, meaning the character goes up and then to the side instead of both at the same time:
(I apologise if its a bit hard to see)
CODE
This is my character movement script:
Rigidbody2D rb;
BoxCollider2D bc;
[Header("Run")]
float xInput = 0f;
public float maxRunSpeed;
public float acceleration;
[Space]
[Header("Jump")]
public float jumpHeight;
public float lowJumpHeight;
public float fallSpeed;
public float airControl;
[Space]
public LayerMask groundLayer;
public bool onGround;
[Space]
public Vector2 bottomOffset;
public Vector2 boxSize;
public float coyoteTime;
void Start() {
// Gets a reference to the components attatched to the player
rb = GetComponent<Rigidbody2D>();
bc = GetComponent<BoxCollider2D>();
}
void Update() {
Jump();
// Takes input for running and returns a value from 1 (right) to -1 (left)
xInput = Math.Sign(Input.GetAxisRaw("Horizontal"));
}
// Applies a velocity scaled by runSpeed to the player depending on the direction of the input
// Increaces the velocity by accerleration until the max velocity is reached
void FixedUpdate() {
rb.velocity = Math.Abs(rb.velocity.x) < Math.Abs(xInput) * maxRunSpeed ? rb.velocity + new Vector2(acceleration * xInput, rb.velocity.y) * Time.deltaTime : new Vector2(xInput * maxRunSpeed, rb.velocity.y);
}
void Jump() {
// Checks whether the player is on the ground and if it is, replenishes coyote time, but if not, it starts to tick it down
coyoteTime = onGround ? 0.1f : coyoteTime - Time.deltaTime;
// Draws a box to check whether the player is touching objects on the ground layer
onGround = Physics2D.OverlapBox((Vector2)transform.position + bottomOffset, boxSize, 0f, groundLayer);
// Adds an upwards velocity to player when there is still valid coyote time and the jump button is pressed
if (Input.GetButtonDown("Jump") && coyoteTime > 0) {
rb.velocity = Vector2.up * jumpHeight;
}
// Increases gravity of player when falling down or when the jump button is let go mid-jump
if (rb.velocity.y < 0 ) {
rb.velocity += Vector2.up * Physics2D.gravity.y * (fallSpeed - 1) * Time.deltaTime;
} else if (rb.velocity.y > 0 && !Input.GetButton("Jump")) {
rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpHeight - 1) * Time.deltaTime;
}
}
Sorry for there being a lot of unecessary code, it's just im not sure what's causing the issue so i don't want to remove anything. Hopefully my comments make some sense?
This is happening because you're setting the velocity of your rigidbody directly with rb.velocity = Vector2.up * jumpHeight. So that will wipe all existing velocity.
If you want to just add a force to the velocity rather than replacing it entirely, you can do that with methods like Rigidbody2D.AddForce.
While in all other cases you keep your velocity values and only slightly modify them you are hard overwriting the absolute velocity in
rb.velocity = Vector2.up * jumpHeight;
erasing any velocity on X.
You could simply keep whatever you have on the other axis and only overwrite Y like
var velocity = rb.velocity;
velocity.y = jumpHeight;
rb.velocity = velocity;
or
rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
basically the same way you do it also in FixedUpdate for the horizontal direction.

Character controller get stuck

I am making a game with Unity. For some reason the character controller gets stuck.
Here is a video of that
This is the player controller code:
private CharacterController CharacterController;
public float Speed = 12;
private Vector3 Velocity;
private GameObject GroundCheck;
private bool IsGrounded;
public float CheckDistance = 0.4f;
public LayerMask GroundMask;
public float JumpHeight = 3;
public float Gravity = -9.81f;
private void Start()
{
GroundCheck = GameObject.Find("GroundCheck");
CharacterController = GetComponent<CharacterController>();
}
private void Update()
{
IsGrounded = Physics.CheckSphere(GroundCheck.transform.position, CheckDistance, GroundMask);
float X = Input.GetAxis("Horizontal");
float Y = Input.GetAxis("Jump");
float Z = Input.GetAxis("Vertical");
Vector3 Move = transform.right * X + transform.forward * Z;
CharacterController.Move(Move * Speed * Time.deltaTime);
if (Y == 1 && IsGrounded)
{
Velocity.y = Mathf.Sqrt(JumpHeight * -2 * Gravity);
}
if (IsGrounded && Velocity.y < 0)
{
Velocity.y = -2;
}
Velocity.y += Gravity * Time.deltaTime;
CharacterController.Move(Velocity * Time.deltaTime);
}
Happened to me too, judging by the code we watched the same youtube tutorial. The problem here is that you (and that tutorial guy) are making two calls to the Move function inside the Update function, this can cause the jitter you show on the video among other unexpected behaviors. You should only call the Move function once in the Update function and everything will be fine. So you need to combine X, Y, and Z movement in a single Vector3:
private void Update()
{
IsGrounded = Physics.CheckSphere(GroundCheck.transform.position, CheckDistance, GroundMask);
float X = Input.GetAxis("Horizontal");
float Y = Input.GetAxis("Jump");
float Z = Input.GetAxis("Vertical");
if (Y == 1 && IsGrounded)
{
Velocity.y = Mathf.Sqrt(JumpHeight * -2 * Gravity);
}
if (IsGrounded && Velocity.y < 0)
{
Velocity.y = -2;
}
Vector3 Move = transform.right * X * speed
+ transform.forward * Z * speed
+ transform.up * Velocity.y;
CharacterController.Move(Move * Time.deltaTime);
}
Note that now we are multiplying by the speed before, just the X and Z components, because we don't want the vertical velocity affected by the movement speed.
Although it should work now, there are a few details worth noting:
· You should name your variables in lower camel case: "move", not "Move".
· You don't really need a Vector3 for the vertical velocity, it could be just a float, since you are just using it for one axis. Note that you are reading Velocity.y, but never Velocity.x or Velocity.z. AFAIK this is because you copied the script from the mentioned Youtube tutorial, happened to me too until I realized.
· I don't really know why you are using "float Y = Input.GetAxis("Jump");" since the Jump key should not be an axis, if you run into problems try this instead:
private void Update()
{
IsGrounded = Physics.CheckSphere(GroundCheck.transform.position, CheckDistance, GroundMask);
if (IsGrounded && Velocity.y < 0)
{
Velocity.y = -2f;
}
float X = Input.GetAxis("Horizontal");
float Z = Input.GetAxis("Vertical");
if (Input.GetButtonDown("Jump") && IsGrounded)
{
Velocity.y = Mathf.Sqrt(JumpHeight * -2f * Gravity);
}
Vector3 Move = transform.right * X * speed
+ transform.forward * Z * speed
+ transform.up * Velocity.y;
CharacterController.Move(Move * Time.deltaTime);
}
Does it get stuck as in "It vibrates near the cube trying to climb up" or in "I can't move the character as soon as it touches the cube"?
My guess would be that your character tries to climb up the cube. The cube is approximately 2 meters high (at least if I can correctly get that from the video), your step offset is only 1, though.
Another thing to consider would be your character's skin width. From the Unity Manual:
It’s good practice to keep your Skin Width at least greater than 0.01 and more than 10% of the Radius.
But yours seems to have a good value.
If nothing helps, I would recommend actually going back to a CharacterController with a size of 2 meters. Citing the Unity Manual again:
You can modify the Height and Radius to fit your Character’s mesh
. It is recommended to always use around 2 meters for a human-like character.
One more thing: Start naming your variables after the C#-conventions, which would be camelCase. For example, your Velocity would become velocity, your GroundMask would become groundMask etc.

Unity mid air movement with velocitychange

I have made a script for player movement in a 3D game in Unity.
I like how the movement works, but when I jump while moving, the player keeps moving in that direction at the same speed till it falls to the ground, which is the expected behavior for this script.
But I want to be able to move the player in the air slightly (not fully controllable.)
I'm imagining kinda like a minecraft like movement to be exact.
Any advice to improve this code would be greatly apprecciated.
This is my code.
using System.IO;
using UnityEngine;
public class VelocityMovement : MonoBehaviour
{
#region Variables
public float speed;
public float gravity;
public float maxVelocityChange;
public float jumpHeight;
public float raycastDistance;
public Rigidbody rb;
#endregion
private void Awake()
{
//gets rigidbody, freezes rotation of the rigidbody, disables unity's built in gravity system on rigidbody.
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
rb.useGravity = false;
}
private void Update()
{
//Jump system
if(Grounded())
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector3(rb.velocity.x, CalculateJumpSpeed(), rb.velocity.z);
}
}
}
private void FixedUpdate()
{
//Moves the player when on the ground.
if (Grounded())
{
//Calculate how fast the player should be moving.
Vector3 targetVelocity = new Vector3(playerInputs.hAxis, 0, playerInputs.vAxis);
targetVelocity = transform.TransformDirection(targetVelocity);
targetVelocity *= speed ;
//Calculate what the velocity change should be
Vector3 velocity = rb.velocity;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0f;
//applies a force equal to the needed velocity change
rb.AddForce(velocityChange, ForceMode.VelocityChange);
}
//Adds gravity to the rigidbody
rb.AddForce(new Vector3(0, -gravity * rb.mass, 0));
}
//Checks if player is on the ground
private bool Grounded()
{
return Physics.Raycast(transform.position, Vector3.down, raycastDistance);
}
//calculates how high the player should be jumping
private float CalculateJumpSpeed()
{
return Mathf.Sqrt(2 * jumpHeight * gravity);
}
}
private void FixedUpdate()
{
//check how big the movement is. Swap SomeSmallValue with a float like 0.1f
float actualSpeed;
Vector3 velocity;
if(Grounded())
{
actualSpeed = speed;
//HERE IT IS NOT, THIS DOESN'T MATTER
velocity = rb.velocity
}
else{
actualSpeed = speed * SomeSmallValue;
//WITH THIS rb KEEPS THE SPEED IF ANY BUTTON IS PRESSED
velocity = 0;
}
//Moves the player ALWAYS.
//Calculate how fast the player should be moving.
Vector3 targetVelocity = new Vector3(playerInputs.hAxis, 0, playerInputs.vAxis);
targetVelocity = transform.TransformDirection(targetVelocity);
//if Grounded == true the movement is exactly the same than before, because actualSpeed = speed.
//If Grounded == false, the movement is so light
targetVelocity *= actualSpeed;
//Calculate what the velocity change should be
//I'VE PLACED THIS UP IN ORDER TO CALL Grounded() ONLY ONE TIME
//Vector3 velocity = rb.velocity;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0f;
//applies a force equal to the needed velocity change
rb.AddForce(velocityChange, ForceMode.VelocityChange);
//Adds gravity to the rigidbody
rb.AddForce(new Vector3(0, -gravity * rb.mass, 0));
}
If your code is working fine, try something like this. Just moved the grounded condition. Now the movement works also at air time. We check with that grounded bool how big the movement is.
If I understood you correctly you want to slow down what your movements do while mid air.
at least that is the case for left and right.
If I did undersand you correctly, you would make an else{} after the if(Grounded())
and go from there, may make some float variable that acts as a multiplier for you left/right control while mid air, aswell as another float variable for forward and backwards.
Inside that else you could just multiply you speed with the variables (depending on the axis) and you should get some form of slower movement there.
I hope that helped you out at least a bit.

Need helping getting a character controller to jump

So far I have a character controller that enables me to move around, sprint and crouch (no animation) , but I am unable to get the controller to jump. I know 100% the character is getting the input to jump, and the movement vector is around ~40 on the Y axis, so the player should be moving. The problem is, nothing happens. The player can still move around, and fall of ledges, but nothing happens when i press space
This is my code:
using UnityEngine;
public class KeyboardMovement : MonoBehaviour
{
private CharacterController controller;
public float walkSpeed;
public float sprintSpeed;
public float crouchSpeed;
public float jumpHeight;
Vector3 up = Vector3.zero;
Vector3 movement = Vector3.zero;
Vector3 forward = Vector3.zero;
Vector3 sideways = Vector3.zero;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
float speed = walkSpeed;
//If crouching, set speed to crouch speed. This ovverides sprinting
if (SingletonSettings.GetKey(SingletonSettings.Keybindings.crouch))
speed = crouchSpeed;
//Else if sprinting, set speed to sprint speed
else if (SingletonSettings.GetKey(SingletonSettings.Keybindings.sprint))
speed = sprintSpeed;
//Create vectors for movement
forward = transform.TransformDirection(Vector3.forward) * Input.GetAxis("Vertical");
sideways = transform.TransformDirection(Vector3.right) * Input.GetAxis("Horizontal");
//up = SingletonSettings.GetKey(SingletonSettings.Keybindings.jump) && controller.isGrounded ? Vector3.up * jumpHeight : Vector3.zero;
movement = (up * 100) + ((forward + sideways) * 10 * Time.deltaTime * speed);
//Combine vectors and Multiply by DeltaTime to ensure smooth movement at different framerates.
//Also multiply by 10*speed to ensure correct speed in different states
if (controller.isGrounded && Input.GetKey(KeyCode.Space))
{
movement.y = jumpHeight*50 * Time.deltaTime;
}
controller.SimpleMove(movement);
}
void OnGUI()
{
GUILayout.Label('\n' + Newtonsoft.Json.JsonConvert.SerializeObject(movement.y, Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
}));
}
}
CharacterController.SimpleMove from the docs
Moves the character with speed.
Velocity along the y-axis is ignored.
Gravity is automatically applied.
https://docs.unity3d.com/ScriptReference/CharacterController.SimpleMove.html
You should use CharacterController.Move
A more complex move function taking absolute movement deltas.
Attempts to move the controller by motion, the motion will only be constrained by collisions. It will slide along colliders
...
This function does not apply any gravity.
https://docs.unity3d.com/ScriptReference/CharacterController.Move.html
With this method, you'll need to apply gravity yourself
movement.y -= gravity * Time.deltaTime;
controller.Move(movement * Time.deltaTime);

Jumping without rigidbody in unity

I'm trying to add jumping to the controls of our control script but it just doesn't work yet and I'm getting kind of frustrated because I tried a lot to make it work. I don't use rigidbodies and rather want to use script based physics and - but later - raycasts (to detect ground). It's 3D but with a fixed perspective because the characters are sprites (we are thinking about trying a style similar to Don't Starve, Paper Mario etc.). And the thing I want to put in for now is to jump upwards when the character stands still and later on jumps that also let the character travel a bit of distance when the character moves. Well, you get the picture. For that I first need to get jumping working at all - and also gravity to put the character back down while also considering that the character could land on a ground that has a different height than the starting ground.
What happens now is that the character jumps just a tiny little bit, like not even a hop, and then falls down endlessly - or goes up endlessly when jump is pressed again. So, how do I fix that?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Controls3D : MonoBehaviour
{
public float player3DSpeed = 5f;
private bool IsGrounded = true;
private const float groundY = (float) 0.4;
private Vector3 Velocity = Vector3.zero;
public Vector3 gravity = new Vector3(0, -10, 0);
void Start()
{
}
void Update()
{
if (IsGrounded)
{
if (Input.GetButtonDown("Jump"))
{
IsGrounded = false;
Velocity = new Vector3(Input.GetAxis("Horizontal"), 20, Input.GetAxis("Vertical"));
}
Velocity.x = Input.GetAxis("Horizontal");
Velocity.z = Input.GetAxis("Vertical");
if (Velocity.sqrMagnitude > 1)
Velocity.Normalize();
transform.position += Velocity * player3DSpeed * Time.deltaTime;
}
else
{
Velocity += gravity * Time.deltaTime;
Vector3 position = transform.position + Velocity * Time.deltaTime;
if (position.y < groundY)
{
position.y = groundY;
IsGrounded = true;
}
transform.position = position;
}
}
}
If i were you, i think i wouldve changed the whole thing into a character controller, as this simplifies the process, a ####ton :P
If you figure out you do want to use the CC. This is the solution i usually use:
CharacterController controller = GetComponent<CharacterController>();
// is the controller on the ground?
if (controller.isGrounded)
{
//Feed moveDirection with input.
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
//Multiply it by speed.
moveDirection *= speed;
//Jumping
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
//Applying gravity to the controller
moveDirection.y -= gravity * Time.deltaTime;
//Making the character move
controller.Move(moveDirection * Time.deltaTime);
moveDirection is a Vector3 Type variable, and speed and jumpSpeed are public float values used to modify the speed.
Please NOTE: Character Controllers, let you program your own Physics.

Categories

Resources