- Home /
Question by
alemalespin97 · Aug 12, 2021 at 12:52 AM ·
physicsrigidbodyaddforceplayer movementlaunch
How to apply a force after launching the player?
I implemented a mechanic in my game that launches the player with the right mouse button in the direction of the first person camera. It is working as intended, but when the player launches into the air, they come to an abrupt stop and come straight back down once a certain travel distance is achieved. So at the end of the launch, I want to apply a force to the player in the same direction so that there is a bit of an arc to the fall. I've tried using addForce on a Rigidbody attached to the player, and a Boolean to trigger it at the end of the launch, but no luck. Any ideas on how to implement this?
public class PlayerMov : MonoBehaviour
{
enum MovementMode
{
Platformer,
Strafe
}
[SerializeField] //makes variable visible in inspector, despite it being private
private MovementMode _movementMode = MovementMode.Strafe;
[SerializeField]
private float _walkSpeed = 3f;
[SerializeField]
private float _runningSpeed = 6f;
[SerializeField]
private float _gravity = 9.81f;
[SerializeField]
private float _gravityPlatformer = -12f;
[SerializeField]
private float _jumpSpeed = 3.5f;
[SerializeField]
private float _doubleJumpMultiplier = 0.5f;
[SerializeField]
private GameObject _cameraRig;
public float jumpHeight = 1;
private CharacterController _controller;
private float _directionY;
private float _currentSpeed;
private bool _canDoubleJump = false;
public float turnSmoothTime = 0.2f;
float turnSmoothVelocity;
public float speedSmoothTime = 0.1f;
float speedSmoothVelocity;
private float velocityY;
//for game over screen
PlayerInfo playerInfo;
//to prevent gravity increasing forever
public float terminalVelocity = -3;
//for Bounce
public Transform camera;
public float bounceSpeed = 5f;
public float bounceDistance = 10f;
public float forceMultiplier = 1; //*************************************
private bool bounceActive;
private bool bouncePlayer;
private bool loaded;
public bool freeze;
public bool bounceEnded; //******************************************
SoldierMov soldier;
Vector3 direction;
//for tracking distance when bouncing
private Vector3 oldPos;
private float totalDistance = 0;
//Bounce sound effects
public AudioSource bounceLoadedInitial;
public AudioSource bounceLoadedLoop;
public AudioSource bounceLaunch;
void Start()
{
_controller = GetComponent<CharacterController>();
playerInfo = GameObject.Find("Player").GetComponent<PlayerInfo>();
soldier = GameObject.Find("Soldier_Prefab").GetComponent<SoldierMov>();
//variables for bounce
bounceActive = false;
bouncePlayer = false;
loaded = false;
freeze = false;
bounceEnded = false; //************************************************
}
void Update()
{
//Debug.Log("alive = " + playerInfo.GetAlive());
if (playerInfo.GetAlive() && freeze == false) //disables player movement if dead or freezing time with bounce
{
if (_movementMode == MovementMode.Strafe)
{
MovementStafe();
}
if (_movementMode == MovementMode.Platformer)
{
MovementPlatformer();
}
}
if (playerInfo.GetAlive()) //disables bounce if dead
{
//loads Bounce with right mouse button when near soldier, and launchs player upon button release
soldier = GameObject.Find("Soldier_Prefab(Clone)").GetComponent<SoldierMov>();
if (Input.GetButtonDown("Fire2") && soldier.playerNear) //load bounce when near soldier
{
//Debug.Log("BOUNCE IS LOADED");
oldPos = transform.position; //save position when bounce is loaded
loaded = true; //loads the bounce
freeze = true; //used to freeze player and soldier
//Play loaded bounce sound effect
bounceLoadedInitial.Stop();
bounceLoadedInitial.Play(); //play initial sfx
bounceLoadedLoop.PlayDelayed(bounceLoadedInitial.clip.length); //loop the second part of the sfx
}
else if (Input.GetButtonUp("Fire2") && loaded) //execute bounce upon button release
{
bounceLoadedLoop.Stop();
bounceLaunch.Play(); //play bounce launch sfx
direction = new Vector3(camera.forward.x, camera.forward.y, camera.forward.z);
bouncePlayer = true;
}
//Debug.Log("freeze = " + freeze + "\nloaded = " + loaded);
if (bouncePlayer)
{
Bounce();
}
else
{
bounceEnded = false;
}
if (bounceEnded)
{
//use addforce on rigidbody
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(direction * forceMultiplier, ForceMode.Impulse);
}
Debug.Log("bounceEnded = " + bounceEnded);
}
}
private void LateUpdate()
{
if (IsPlayerMoving() && _movementMode == MovementMode.Strafe)
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, _cameraRig.transform.localEulerAngles.y, transform.localEulerAngles.z);
}
private bool IsPlayerMoving()
{
return Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0;
}
private void MovementStafe()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
Vector3 moveDirection = new Vector3(horizontalInput, 0, verticalInput);
if (_controller.isGrounded)
{
_canDoubleJump = true;
if (Input.GetButtonDown("Jump"))
{
_directionY = _jumpSpeed;
}
}
else
{
if (Input.GetButtonDown("Jump") && _canDoubleJump)
{
_directionY = _jumpSpeed * _doubleJumpMultiplier;
_canDoubleJump = false;
}
}
if (bounceActive == false) //gravity is active when bounce is inactive
{
//prevents gravity from increasing forever
if (_directionY > terminalVelocity)
{
_directionY -= _gravity * Time.deltaTime;
}
else
{
_directionY = terminalVelocity;
}
}
else //turn off gravity when bounce is active
{
_directionY = 0;
}
//Debug.Log("_directionY = " + _directionY);
moveDirection = transform.TransformDirection(moveDirection);
bool running = Input.GetKey(KeyCode.LeftShift);
float targetSpeed = (running) ? _runningSpeed : _walkSpeed;
_currentSpeed = Mathf.SmoothDamp(_currentSpeed, targetSpeed, ref speedSmoothVelocity, speedSmoothTime);
moveDirection.y = _directionY;
_controller.Move(_currentSpeed * Time.deltaTime * moveDirection);
}
private void MovementPlatformer()
{
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
Vector2 inputDir = input.normalized;
bool running = Input.GetKey(KeyCode.LeftShift);
if (inputDir != Vector2.zero)
{
float targetRotation = Mathf.Atan2(inputDir.x, inputDir.y) * Mathf.Rad2Deg + _cameraRig.transform.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, turnSmoothTime);
}
float targetSpeed = ((running) ? _runningSpeed : _walkSpeed) * inputDir.magnitude;
_currentSpeed = Mathf.SmoothDamp(_currentSpeed, targetSpeed, ref speedSmoothVelocity, speedSmoothTime);
velocityY += Time.deltaTime * _gravityPlatformer;
Vector3 velocity = transform.forward * _currentSpeed + Vector3.up * velocityY;
_controller.Move(velocity * Time.deltaTime);
_currentSpeed = new Vector2(_controller.velocity.x, _controller.velocity.z).magnitude;
if (_controller.isGrounded)
{
velocityY = 0;
}
if (Input.GetKeyDown(KeyCode.Space))
{
if (_controller.isGrounded)
{
float jumpVelocity = Mathf.Sqrt(-2 * _gravityPlatformer * jumpHeight);
velocityY = jumpVelocity;
}
}
}
private void Bounce()
{
//track distance traveled during bounce
Vector3 distanceVector = transform.position - oldPos;
float distanceThisFrame = distanceVector.magnitude;
totalDistance += distanceThisFrame;
oldPos = transform.position;
//makes player travel a certain distance
if (totalDistance < bounceDistance) //launch player until bounce distance is achieved
{
bounceActive = true; //turns off gravity
_controller.Move(direction * bounceSpeed * Time.deltaTime);
}
else //stop Bounce once bounceDistance is achieved
{
//use addforce on rigidbody
//Rigidbody rb = GetComponent<Rigidbody>();
//rb.AddForce(direction * forceMultiplier, ForceMode.Impulse);
bounceActive = false; //turn gravity back on
bouncePlayer = false; //used to stop calling this function
loaded = false;
freeze = false;
bounceEnded = true; //***************************************************************
totalDistance = 0;
}
}
}
Comment