character mesh is going underneath the character controller - c#

I'm not sure if someone is going to help me with this problem but here is my issue any ways
My player movement script was working perfectly fine before I enter this code and I'm pretty sure it's something in my script from the past that is causing my character mesh to have a huge offset downwards from my character controller yes, I have the curves set up probably here is the Ik tutorial I followed to get this issue. Thanks for your help you're a life saver for anyone who does help. Here is the video https://www.youtube.com/watch?v=MonxKdgxi2w
public class PlayerMovement : MonoBehaviour
{
#region Variables
private Vector3 Velocity;
private Vector3 PlayerMovementInput;
private Vector2 PlayerMouseInput;
private float xRot;
private CharacterController controller;
public Transform PlayerCamera;
Animator anim;
public float DefaultSpeed;
public float Speed;
public float RunSpeed;
public float Jumpforce;
public float Sensitivity;
public float Gravity = -9.81f;
private Vector3 rightFootPosition, leftFootPosition, leftFootIKPosition, rightFootIkPosition;
private Quaternion leftFootIkRotation, rightFootIKRotation;
private float lastPekvisPositionY, lastRightFootPositioonY, lastLeftFootPositionY;
[Header("Feet Grounder")]
public bool enableFeetIk = true;
[Range(0, 2)] [SerializeField] private float heightFromGroundRaycast = 1.14f;
[Range(0, 2)] [SerializeField] private float raycastDownDIstance = 1.5f;
[SerializeField] private LayerMask environmentLayer;
[SerializeField] private float pelvisOffset = 0f;
[Range(0, 1)] [SerializeField] private float pelvisUpAndDownSpeed = 0.28f;
[Range(0, 1)] [SerializeField] private float feetToIkPositionSpeed = 0.5f;
public string LeftFotAnimVariableName = "LeftFootCurve";
public string rightFootAnimVariableName = "RightFootCurve";
public bool useProIkFeature = false;
public bool showSolverDebug = true;
#endregion
# region Initialization
private void Start()
{
controller = GetComponentInChildren<CharacterController>();
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
anim = GetComponentInChildren<Animator>();
}
private void Update()
{
PlayerMovementInput = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
PlayerMouseInput = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
MovePlayer();
MoveCamera();
}
#endregion
#region PlayerMovement
private void MovePlayer()
{
Vector3 MoveVector = transform.TransformDirection(PlayerMovementInput);
if (PlayerMovementInput != Vector3.zero && !Input.GetKey(KeyCode.LeftShift))
{
Speed = DefaultSpeed;
//WALK
anim.SetFloat("Speed", 0.5f, 0.1f, Time.deltaTime);
}
else if (PlayerMovementInput != Vector3.zero && Input.GetKey(KeyCode.LeftShift))
{
Speed = RunSpeed;
//RUN
anim.SetFloat("Speed", 1, 0.1f, Time.deltaTime);
}
else if (PlayerMovementInput == Vector3.zero)
{
//IDLE
anim.SetFloat("Speed", 0, 0.1f, Time.deltaTime);
}
if (controller.isGrounded)
{
Velocity.y = -1f;
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(Jump());
Velocity.y = Jumpforce;
}
}
else
{
Velocity.y -= Gravity * -2f * Time.deltaTime;
}
controller.Move(MoveVector * Speed * Time.deltaTime);
controller.Move(Velocity * Time.deltaTime);
}
private void MoveCamera()
{
xRot -= PlayerMouseInput.y * Sensitivity;
transform.Rotate(0f, PlayerMouseInput.x * Sensitivity, 0f);
PlayerCamera.transform.localRotation = Quaternion.Euler(xRot, 0f, 0f);
xRot = Mathf.Clamp(xRot, -90f, 90f);
}
private IEnumerator Jump()
{
anim.SetLayerWeight(anim.GetLayerIndex("Jump Layer"), 1);
anim.SetTrigger("Jump");
yield return new WaitForSeconds(0.983f);
anim.SetLayerWeight(anim.GetLayerIndex("Jump Layer"), 0);
}
#endregion
#region FeetGrounding
private void FixedUpdate()
{
if(enableFeetIk == false) { return; }
if( anim == null) { return; }
AdjustFeetTarget(ref rightFootPosition, HumanBodyBones.RightFoot);
AdjustFeetTarget(ref leftFootPosition, HumanBodyBones.LeftFoot);
FeetPositionSolver(rightFootPosition, ref rightFootIkPosition, ref rightFootIKRotation);
FeetPositionSolver(leftFootPosition, ref leftFootIKPosition, ref leftFootIkRotation);
}
private void OnAnimatorIK(int layerIndex)
{
if (enableFeetIk == false) { return; }
if (anim == null) { return; }
MovePelvisHeight();
anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
if(useProIkFeature)
{
anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, anim.GetFloat(rightFootAnimVariableName));
}
MoveFeetToIkPoint(AvatarIKGoal.RightFoot, rightFootIkPosition, rightFootIKRotation, ref lastRightFootPositioonY);
anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
if (useProIkFeature)
{
anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, anim.GetFloat(LeftFotAnimVariableName));
}
MoveFeetToIkPoint(AvatarIKGoal.LeftFoot, leftFootIKPosition, leftFootIkRotation, ref lastLeftFootPositionY);
}
#endregion
#region FeetGroundingMethods
void MoveFeetToIkPoint (AvatarIKGoal foot, Vector3 positionIkHolder, Quaternion rotationIkHolder, ref float lastFootPositionY)
{
Vector3 targetIkPosition = anim.GetIKPosition(foot);
if(positionIkHolder != Vector3.zero)
{
targetIkPosition = transform.InverseTransformDirection(targetIkPosition);
positionIkHolder = transform.InverseTransformPoint(positionIkHolder);
float yVariable = Mathf.Lerp(lastFootPositionY, positionIkHolder.y, feetToIkPositionSpeed);
targetIkPosition.y += yVariable;
lastFootPositionY = yVariable;
targetIkPosition = transform.TransformPoint(targetIkPosition);
anim.SetIKRotation(foot, rotationIkHolder);
}
anim.SetIKPosition(foot, targetIkPosition);
}
private void MovePelvisHeight()
{
if(rightFootIkPosition == Vector3.zero || leftFootIKPosition == Vector3.zero || lastPekvisPositionY == 0)
{
lastPekvisPositionY = anim.bodyPosition.y;
return;
}
float lOffsetPosition = leftFootIKPosition.y = transform.position.y;
float rOffsetPosition = rightFootIkPosition.y = transform.position.y;
float totalOffset = (lOffsetPosition < rOffsetPosition) ? lOffsetPosition : rOffsetPosition;
Vector3 newPelvisPosition = anim.bodyPosition + Vector3.up * totalOffset;
newPelvisPosition.y = Mathf.Lerp(lastPekvisPositionY, newPelvisPosition.y, pelvisUpAndDownSpeed);
anim.bodyPosition = newPelvisPosition;
lastPekvisPositionY = anim.bodyPosition.y;
}
private void FeetPositionSolver(Vector3 fromSkyPosition, ref Vector3 feetIkPositon, ref Quaternion feetIkRotations)
{
RaycastHit feetOutHit;
if (showSolverDebug)
Debug.DrawLine(fromSkyPosition, fromSkyPosition + Vector3.down * (raycastDownDIstance + heightFromGroundRaycast), Color.yellow);
if(Physics.Raycast(fromSkyPosition, Vector3.down, out feetOutHit, raycastDownDIstance + heightFromGroundRaycast, environmentLayer ))
{
feetIkPositon = fromSkyPosition;
feetIkPositon.y = feetOutHit.point.y + pelvisOffset;
feetIkRotations = Quaternion.FromToRotation(Vector3.up, feetOutHit.normal) * transform.rotation;
return;
}
feetIkPositon = Vector3.zero;
}
private void AdjustFeetTarget (ref Vector3 feetPositions, HumanBodyBones foot)
{
feetPositions = anim.GetBoneTransform(foot).position;
feetPositions.y = transform.position.y + heightFromGroundRaycast;
}
#endregion
}

Related

I'm trying to assign a float to velocityZ, velocityX but it doesnt work. it stays at 0

So I have to script that assigns moveDirection to a velocityX, and velocityY. I also have the second script that accesses it. I;m doing all this to create a 8 direction animation in unity.
So here's the code
private void ApplyFinalMovements()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
currentInput = new Vector2(_speed * verticalInput, _speed * horizontalInput);
#region CheckingInputsAnims
if (verticalInput>0)
isWalking = true;
else isWalking = false;
if (verticalInput<0)
isWalkingBackwards = true;
else isWalkingBackwards = false;
#endregion
float moveDirectionY = moveDirection.y;
moveDirection = transform.transform.TransformDirection(Vector3.forward * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y);
velocityZ = moveDirection.y;
velocityX = moveDirection.x;
moveDirection.y = moveDirectionY;
}
And the script that accesses the velocity in order to get it into animator
public class animationStateController : MonoBehaviour
{
Player player;
Animator animator;
private float velocityZ;
private float velocityX;
private void Start()
{
player = FindObjectOfType(typeof(Player)) as Player;
animator = GetComponent<Animator>();
}
void Update()
{
player.velocityZ = velocityZ;
player.velocityX = velocityX;
animator.SetFloat("VelocityZ", velocityZ, 0.1f, Time.deltaTime);
animator.SetFloat("VelocityX", velocityX, 0.1f, Time.deltaTime);
if (player.isWalking)
animator.SetBool("isWalking", true);
else animator.SetBool("isWalking", false);
if (player.isWalkingBackwards)
animator.SetBool("isWalkingBackwards", true);
else animator.SetBool("isWalkingBackwards", false);
if (player.isSprinting)
animator.SetBool("isSprinting", true);
else animator.SetBool("isSprinting", false);
if (player.startJump)
animator.SetBool("startJump", true);
else animator.SetBool("startJump", false);
if (player.midAir)
animator.SetBool("midAir", true);
else animator.SetBool("midAir", false);
if (player.endJump)
animator.SetBool("endJump", true);
else animator.SetBool("endJump", false);
if (player.isCrouching)
animator.SetBool("isCrouching", true);
else animator.SetBool("isCrouching", false);
}
}
Here's the whole code for Player:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine;
public class Player : MonoBehaviour
{
private CharacterController _controller;
private Camera playerCamera;
[Header("Stats")]
[Header("Functional Optons")]
[SerializeField] private bool canLook = true;
[SerializeField] private bool canMove = true;
[SerializeField] private bool canSprint = true;
[SerializeField] private bool canJump = true;
[SerializeField] private bool canCrouch = true;
[SerializeField] private bool WillSlideOnSlopes = true;
[SerializeField] private bool canUseHeadbob = true;
[SerializeField] private bool useFootsteps = true;
[SerializeField] private bool canInteract = true;
[SerializeField] private bool UseStamina = true;
public bool midAir;
private bool midAirLastFrame = false;
[Header("Animator Parameters")]
public float velocityZ;
public float velocityX;
[Header("Controls")]
public KeyCode sprintKey = KeyCode.LeftShift;
public KeyCode jumpKey = KeyCode.Space;
public KeyCode crouchKeyHold = KeyCode.LeftControl;
public KeyCode crouchKeySwitch = KeyCode.C;
public KeyCode interactKey = KeyCode.E;
[Header("Movement Parameters")]
[SerializeField] private float _speed = 3f;
[SerializeField] private float _sprintSpeed = 5f;
[SerializeField] private float _crouchSpeed = 2f;
[SerializeField] private float _slideSpeed = 12f;
public bool isWalking;
public bool isWalkingBackwards;
public bool isSprinting;
private bool SlidedLastFrame;
private Vector3 moveDirection;
private Vector2 currentInput;
[Header("Jumping Parameters")] // dźwięk spadania dodać po czasie się zwiększa
[SerializeField] private float _gravity = 9.81f;
[SerializeField] private float _jumpHeight = 3f;
[SerializeField] private float _fallSpeed;
[SerializeField] private float _fallDamage;
private float _landStartPos;
[SerializeField] private AudioClip[] jumpClips = default;
[SerializeField] private AudioClip[] landClips = default;
public bool startJump;
public bool endJump;
[Header("Crouching Parameters")]
[SerializeField] private float crouchHeight = 1f;
[SerializeField] private float standingHeight = 2.25f;
[SerializeField] private float timeToCrouch = 0.25f;
[SerializeField] private Vector3 crouchingCenter = new Vector3(0, 0f, 0);
[SerializeField] private Vector3 standingCenter = new Vector3(0, 0, 0);
public bool isCrouching;
private bool duringCrouchAnim;
[Header("Look Parameters")]
public float _sensitivity = 100f;
float xRotation = 0f;
private bool cursorShow = false;
[Header("Health Parameters")]
[SerializeField] private float maxHealth = 100f;
[SerializeField] private float timeBeforeRegenStarts = 8f;
[SerializeField] private float healthValueIncrement = 0.5f;
[SerializeField] private float healthTimeIncrement = 0.1f;
[SerializeField] private AudioClip[] hurtClips = default; //SZUKASZ AUDIO SOURCE ZYCIE
[SerializeField] private AudioSource playerAudioSource = default;
[SerializeField] private float currentHealth;
private Coroutine regeneratingHealth; //ogarnij couritine
public static Action<float> OnTakeDamage;
public static Action<float> OnDamage;
public static Action<float> OnHeal;
[Header("Stamina Parameters")]
[SerializeField] private float maxStamina = 100f;
[SerializeField] private float staminaUseMultiplier = 6f;
[SerializeField] private float timeBeforeStaminaRegen = 4.5f;
[SerializeField] private float staminaValueIncrement = 1.5f;
[SerializeField] private float staminaTimeIncrement = 0.1f;
[SerializeField] private float currentStamina;
private Coroutine regeneratingStamina;
public static Action<float> OnStaminaChange;
[Header("Headbob Parameters")]
private float walkBobSpeed = 14.65f;
private float walkBobAmount = 0.03f;
private float sprintBobSpeed = 20f;
private float sprintBobAmount = 0.06f;
private float crouchBobSpeed = 9.75f;
private float crouchBobAmount = 0.04f;
private float defaultYPos = 0;
private float timer;
[Header("Footstep Parameters")]
[SerializeField] private float baseStepSpeed = 0.5f;
[SerializeField] private float crouchStepMultiplier = 1.4f;
[SerializeField] private float sprintStepMultiplier = 0.6f;
[SerializeField] private AudioSource footstepAudioSource = default;
[SerializeField] private AudioClip[] woodClips = default;
[SerializeField] private AudioClip[] stoneClips = default;
[SerializeField] private AudioClip[] grassClips = default;
private float footstepTimer = 0;
private float GetCurrentOffset => isCrouching ? baseStepSpeed * crouchStepMultiplier : isSprinting ? baseStepSpeed * sprintStepMultiplier : baseStepSpeed; // ogarnij to i zaimplementuj do całego kodu
[Header("Sliding Parameters")]
private Vector3 hitPointNormal;
private bool IsSliding
{
get //dodaj to że po zakończeniu slide'a dalej cie wypycha w kierunek w który wcześniej zjeżdżałeś, abyś nie kończył na końcu.
{
if (_controller.isGrounded && Physics.Raycast(transform.position, Vector3.down, out RaycastHit slopeHit, 1.8f))
{
hitPointNormal = slopeHit.normal;
return Vector3.Angle(hitPointNormal, Vector3.up) > _controller.slopeLimit;
}
else
{
return false;
}
}
} // dodaj dźwięk ślizgania się
[Header("Interaction")]
[SerializeField] private Vector3 interactionRayPoint = default;
[SerializeField] private float interactionDistance = default;
[SerializeField] private LayerMask interactionLayer = default;
private Interactable currentInteractable;
private void OnEnable()
{
OnTakeDamage += ApplyDamage;
}
private void OnDisable()
{
OnTakeDamage -= ApplyDamage;
}
void Awake()
{
_controller = GetComponent<CharacterController>();
playerCamera = GetComponentInChildren<Camera>();
defaultYPos = playerCamera.transform.localPosition.y;
currentHealth = maxHealth;
currentStamina = maxStamina;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
Screen.SetResolution(1920, 1080, true);
}
void Update() // ogarnij machanie mieczem i niszczenie skrzynek
{
_speed = 3f;
isSprinting = false;
if (canLook)
MouseLook();
if (canSprint)
Sprinting();
if (canJump)
Jumping();
if (canCrouch)
Crouching();
if (canUseHeadbob)
HandleHeadbob();
if (useFootsteps)
HandleFootsteps();
if (canInteract)
{
HandleInteractionCheck();
HandleInteractionInput();
}
if (UseStamina)
HandleStamina();
if (Input.GetKeyDown(KeyCode.Tab) && cursorShow)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
cursorShow = false;
canLook = true;
}
else if(Input.GetKeyDown(KeyCode.Tab) && !cursorShow)
{
Cursor.lockState = CursorLockMode.Confined;
Cursor.visible = true;
cursorShow = true;
canLook = false;
}
if (canMove)
ApplyFinalMovements();
if (WillSlideOnSlopes && IsSliding)
{
moveDirection += new Vector3(hitPointNormal.x, -hitPointNormal.y, hitPointNormal.z) * _slideSpeed;
SlidedLastFrame = true;
}
_controller.Move(moveDirection * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
}
private void ApplyFinalMovements()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
currentInput = new Vector2(_speed * verticalInput, _speed * horizontalInput);
#region CheckingInputsAnims
if (verticalInput>0)
isWalking = true;
else isWalking = false;
if (verticalInput<0)
isWalkingBackwards = true;
else isWalkingBackwards = false;
#endregion
float moveDirectionY = moveDirection.y;
moveDirection = transform.transform.TransformDirection(Vector3.forward * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y);
velocityZ = moveDirection.y;
velocityX = moveDirection.x;
moveDirection.y = moveDirectionY;
}
private void MouseLook()
{
float mouseX = Input.GetAxis("Mouse X") * _sensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * _sensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90, 90);
playerCamera.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
transform.Rotate(Vector3.up * mouseX);
}
private void Sprinting()
{
if (Input.GetKey(sprintKey) && Input.GetAxis("Vertical") > 0 && !IsSliding && !isCrouching && canSprint)
{
isSprinting = true;
_speed = _sprintSpeed;
}
}
private void Jumping() // dodaj dźwięk spadania przy wysokich prędkościach, którego głośność się będzie zwiększała
{
startJump = false;
if (SlidedLastFrame && !IsSliding)
{
moveDirection.y = -1f;
SlidedLastFrame = false;
}
_fallSpeed = moveDirection.y;
if (midAir)
midAirLastFrame = true;
if (_controller.isGrounded)
midAir = false;
if (_controller.isGrounded && Input.GetKeyDown(jumpKey) && !IsSliding && canJump)
{
startJump = true;
playerAudioSource.PlayOneShot(jumpClips[UnityEngine.Random.Range(0, landClips.Length - 1)]);
moveDirection.y = _jumpHeight;
midAir = true;
}
else if (_controller.isGrounded)
{
if(midAirLastFrame)
endJump = true;
if (midAirLastFrame && !IsSliding && _fallSpeed < -3.5f) // ogarnijjj toooo
{
midAirLastFrame = false;
_landStartPos = playerCamera.transform.localPosition.y;
if (_fallSpeed <= -3.5f)
{
playerAudioSource.PlayOneShot(landClips[UnityEngine.Random.Range(0, landClips.Length - 1)]);
if (_fallSpeed <= -8f) _fallDamage = -moveDirection.y * 1.7f;
if (_fallSpeed <= -9f) _fallDamage *= 2f;
if (_fallSpeed <= -10f) _fallDamage *= 1.5f;
if (_fallSpeed <= -11f) _fallDamage *= 1.5f;
if (_fallSpeed <= -8f) {
Player.OnTakeDamage(_fallDamage);
Debug.Log("Took fallDamage = " + _fallDamage + "with fallspeed = " + _fallSpeed);
}
_fallDamage = 0f;
}
}
moveDirection.y = -1f;
}
else
{
midAir = true;
moveDirection.y -= _gravity * Time.deltaTime;
if (Physics.Raycast(playerCamera.transform.position, Vector3.up, 0.5f) && moveDirection.y > 0f)
{
moveDirection.y = 0f;
}
}
}
private void Crouching()
{
if (Input.GetKeyDown(crouchKeyHold) && !duringCrouchAnim && _controller.isGrounded)
{
StartCoroutine(CrouchStand());
}
else if (isCrouching)
{
_speed = _crouchSpeed;
}
}
private void HandleHeadbob()
{
if (!_controller.isGrounded)
{
return;
}
if (Mathf.Abs(moveDirection.x) > 0.1f || Mathf.Abs(moveDirection.z) > 0.1f)
{
timer += Time.deltaTime * (isCrouching ? crouchBobSpeed : isSprinting ? sprintBobSpeed : walkBobSpeed);
playerCamera.transform.localPosition = new Vector3(
playerCamera.transform.localPosition.x,
defaultYPos + Mathf.Sin(timer) * (isCrouching ? crouchBobAmount : isSprinting ? sprintBobAmount : walkBobAmount),
playerCamera.transform.localPosition.z);
}
}
private void HandleStamina()
{
if (isSprinting && currentInput != Vector2.zero)
{
if (regeneratingStamina != null)
{
StopCoroutine(regeneratingStamina);
regeneratingStamina = null;
}
currentStamina -= staminaUseMultiplier * Time.deltaTime;
if (currentStamina < 0)
{
currentStamina = 0;
}
OnStaminaChange?.Invoke(currentStamina);
if (currentStamina <= 0)
{
canSprint = false;
}
}
if (!isSprinting && currentStamina < maxStamina && regeneratingStamina == null)
{
regeneratingStamina = StartCoroutine(RegenerateStamina());
}
}
private void HandleFootsteps()
{
if (!_controller.isGrounded) return;
if (currentInput == Vector2.zero) return;
footstepTimer -= Time.deltaTime;
if (footstepTimer <= 0)
{
if (Physics.Raycast(playerCamera.transform.position, Vector3.down, out RaycastHit hit, 3))
{
switch (hit.collider.tag)
{
case "Footsteps/STONE":
footstepAudioSource.PlayOneShot(stoneClips[UnityEngine.Random.Range(0, stoneClips.Length - 1)]);
break;
default:
footstepAudioSource.PlayOneShot(stoneClips[UnityEngine.Random.Range(0, stoneClips.Length - 1)]);
break;
}
}
footstepTimer = GetCurrentOffset;
}
}
private void ApplyDamage(float dmg) //ogarnij te float
{
currentHealth -= dmg;
playerAudioSource.PlayOneShot(hurtClips[UnityEngine.Random.Range(0, landClips.Length - 1)]);
OnDamage?.Invoke(currentHealth);
if (currentHealth <= 0)
{
KillPlayer();
}
else if (regeneratingHealth != null)
{
StopCoroutine(regeneratingHealth);
}
regeneratingHealth = StartCoroutine(RegenerateHealth());
}
private void KillPlayer()
{
currentHealth = 0;
if (regeneratingHealth != null)
{
StopCoroutine(regeneratingHealth);
Debug.Log("DEAD");
}
}
private void HandleInteractionCheck()
{
if (Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), out RaycastHit hit, interactionDistance))
{
if (hit.collider.gameObject.layer == 8 && (currentInteractable == null || hit.collider.gameObject.GetInstanceID() != currentInteractable.GetInstanceID()))
{
hit.collider.TryGetComponent(out currentInteractable);
if (currentInteractable)
{
currentInteractable.OnFocus();
}
}
else if (currentInteractable)
{
currentInteractable.OnLoseFocus();
currentInteractable = null;
}
}
else if (currentInteractable)
{
currentInteractable.OnLoseFocus();
currentInteractable = null;
}
}
private void HandleInteractionInput()
{
if (Input.GetKeyDown(interactKey) && currentInteractable != null && Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), out RaycastHit hit, interactionDistance, interactionLayer))
{
currentInteractable.OnInteract();
}
}
private IEnumerator CrouchStand()
{
if (isCrouching && Physics.Raycast(playerCamera.transform.position, Vector3.up, 0.5f))
{
yield break;
}
duringCrouchAnim = true;
float timeElapsed = 0;
float targetHeight = isCrouching ? standingHeight : crouchHeight;
float currentHeight = _controller.height;
Vector3 targetCenter = isCrouching ? standingCenter : crouchingCenter;
Vector3 currentCenter = _controller.center;
while (timeElapsed < timeToCrouch)
{
_controller.height = Mathf.Lerp(currentHeight, targetHeight, timeElapsed / timeToCrouch);
_controller.center = Vector3.Lerp(currentCenter, targetCenter, timeElapsed / timeToCrouch);
timeElapsed += Time.deltaTime;
yield return null;
}
_controller.height = targetHeight;
_controller.center = targetCenter;
isCrouching = !isCrouching;
duringCrouchAnim = false;
}
private IEnumerator RegenerateHealth()
{
yield return new WaitForSeconds(timeBeforeRegenStarts);
WaitForSeconds timeToWait = new WaitForSeconds(healthTimeIncrement);
while (currentHealth < maxHealth)
{
currentHealth += healthValueIncrement;
if (currentHealth > maxHealth)
{
currentHealth = maxHealth;
}
OnHeal?.Invoke(currentHealth);
yield return timeToWait;
}
regeneratingHealth = null;
}
private IEnumerator RegenerateStamina()
{
yield return new WaitForSeconds(timeBeforeStaminaRegen);
WaitForSeconds timeToWait = new WaitForSeconds(staminaTimeIncrement);
while (currentStamina < maxStamina)
{
if (currentStamina > 0)
{
canSprint = true;
}
currentStamina += staminaValueIncrement;
if (currentStamina > maxStamina)
{
currentStamina = maxStamina;
}
OnStaminaChange?.Invoke(currentStamina);
yield return timeToWait;
}
regeneratingStamina = null;
}
}
First consider using an enum rather than multiple if...else statements for your current state.
Then, after reviewing the full code, i'm pretty sure the issue come from the fact that your not correctly assigning your values.
Try reverting player.velocityZ = velocityZ; to velocityZ = player.velocityZ; that should do the trick.
That might be it if i understand correctly.
public enum State
{
isWalking,
isWalkingBackwards,
isSprinting,
startJump,
midAir,
endJump,
isCrouching,
}
public class animationStateController : MonoBehaviour
{
Player player;
Animator animator;
private float velocityZ;
private float velocityX;
State lastAnim;
State currentAnim;
private void Start()
{
player = FindObjectOfType(typeof(Player)) as Player;
animator = GetComponent<Animator>();
}
void Update()
{
velocityZ = player.velocityZ;
velocityX = player.velocityX;
animator.SetFloat("VelocityZ", velocityZ, 0.1f, Time.deltaTime);
animator.SetFloat("VelocityX", velocityX, 0.1f, Time.deltaTime);
if (lastAnim != currentAnim)
{
animator.SetBool(currentAnim.ToString(), true)
animator.SetBool(lastAnim.ToString(), false);
}
lastAnim = currentAnim;
}
private void ApplyFinalMovements()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
currentInput = new Vector2(_speed * verticalInput, _speed * horizontalInput);
#region CheckingInputsAnims
if (verticalInput > 0)
currentAnim = State.isWalking;
else if (verticalInput < 0)
currentAnim = State.isWalkingBackwards;
#endregion
float moveDirectionY = moveDirection.y;
moveDirection = transform.transform.TransformDirection(Vector3.forward * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y);
velocityZ = moveDirection.y;
velocityX = moveDirection.x;
}
}

How to make FPS crawl?

I'm using Unity New Input System for my FPS game and I have figured out the movement and the mouselook. However, I'm trying to add a crawling feature to my moving script. I don't want the player to be holding down a button for crawling, it would be better to click a button to change the status from walking to crawling and then just move accordingly. and of course, the mouselook will differ in every state. How would I achieve that with the minimal code changes?
Movement class:
public class Movement : MonoBehaviour
{
[SerializeField] CharacterController controller;
[SerializeField] float walkSpeed = 10f;
[SerializeField] float runSpeed = 35f;
float moveSpeed;
Vector2 horizontalInput;
[SerializeField] float jumpHeight = 3.5f;
bool jump, running;
[SerializeField] float gravity = -30f; //-9.81
Vector3 verticalVelocity = Vector3.zero;
[SerializeField] LayerMask groundMask;
bool isGrounded;
Vector3 horizontalVelocity;
private void Update()
{
isGrounded = Physics.CheckSphere(transform.position, 0.1f, groundMask);
if (isGrounded)
{
verticalVelocity.y = 0;
}
// Jump: v = sqrt(-2 * jumpheight* gravity)
if (jump)
{
if (isGrounded)
{
verticalVelocity.y = Mathf.Sqrt(-2f * jumpHeight * gravity);
}
jump = false;
}
verticalVelocity.y += gravity * Time.deltaTime;
controller.Move(verticalVelocity * Time.deltaTime);
if (running)
{
moveSpeed = runSpeed;
horizontalVelocity = (transform.right * horizontalInput.x + transform.forward * horizontalInput.y) * moveSpeed;
controller.Move(horizontalVelocity * Time.deltaTime);
}
else
{
moveSpeed = walkSpeed;
horizontalVelocity = (transform.right * horizontalInput.x + transform.forward * horizontalInput.y) * moveSpeed;
controller.Move(horizontalVelocity * Time.deltaTime);
}
}
public void ReceiveInput(Vector2 _horizontalInput)
{
horizontalInput = _horizontalInput;
}
public void OnJumpPressed()
{
jump = true;
}
public void OnRunningPressed() {
running = true;
}
}
MouseLook class:
public class MouseLook : MonoBehaviour
{
[SerializeField] float sensitivityX = 8f;
[SerializeField] float sensitivityY = 0.5f;
float mouseX, mouseY;
[SerializeField] Transform playerCamera;
[SerializeField] float xClamp = 75f;
float xRotataion = 0f;
private void Update()
{
transform.Rotate(Vector3.up, mouseX * Time.fixedDeltaTime);
xRotataion -= mouseY;
xRotataion = Mathf.Clamp(xRotataion, -xClamp, xClamp);
Vector3 targetRotation = transform.eulerAngles;
targetRotation.x = xRotataion;
playerCamera.eulerAngles = targetRotation;
}
public void ReceiveInput(Vector2 mouseInput)
{
mouseX = mouseInput.x * sensitivityX;
mouseY = mouseInput.y * sensitivityY;
}
}
InputManager class:
public class InputManager : MonoBehaviour
{
[SerializeField] Movement movement;
[SerializeField] PlayerInteractions playerInteractions;
[SerializeField] MouseLook mouseLook;
PlayerControls controls;
PlayerControls.GroundMovementActions groundMovement;
Vector2 horizontalInput;
Vector2 mouseInput;
private void Awake()
{
controls = new PlayerControls();
groundMovement = controls.GroundMovement;
// groundMovement.[action].performed += context => do something
groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
groundMovement.Jump.performed += _ => movement.OnJumpPressed();
groundMovement.Running.performed += _ => movement.OnRunningPressed();
groundMovement.PickingUp.performed += _ => playerInteractions.OnPickingUp();
groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
groundMovement.Open.performed += _ => playerInteractions.OnOpenPressed();
}
private void Update()
{
movement.ReceiveInput(horizontalInput);
mouseLook.ReceiveInput(mouseInput);
}
private void OnEnable()
{
controls.Enable();
}
private void OnDestroy()
{
controls.Disable();
}
}
I failed to find anything like this online and I don't know how to achieve it using the new input system but here is my attempt:
public class crawlScript : MonoBehaviour
{
CapsuleCollider playerCol;
float originalHeight;
public float reducedHeight;
bool crawl = false;
void Start()
{
playerCol= GetComponent<CapsuleCollider>();
originalHeight= playerCol.height;
}
// Update is called once per frame
void Update()
{
if (crawl)
{
OnCrouch();
}
else if (!crawl)
{
GoUp();
}
}
public void OnCrouch()
{
playerCol.height= reducedHeight;
}
void GoUp()
{
playerCol.height = originalHeight;
}
public void OnCrawl()
{
crawl= true;
}
And added this to the InputManager class:
groundMovement.Crawl.performed += _ => crawlscript.OnCrawl();
You will need to
Create a public boolean variable for whether the player is crawling or not, because this will almost certainly be needed in the future by this script or other scripts.
Create a crawling animation
Create two functions for enabling and disabling crawl, that will toggle the animation, change the players walk speed, and do other things that you may want to add (like toggle the visibility of any objects in the player's hands until they get back up).
The code should look something like this:
public String crawlkey = "left shift";
public bool iscrawling = false;
// put in Update()
if(!crawling){
if(Input.GetKeyDown(crawlkey)){
iscrawling = true;
handleCrawlStart();
}
} else if(Input.GetKeyDown(crawlkey)){
iscrawling = false;
handleCrawlEnd;
}

How to make an object jump forward?

I've been having problems with getting my character to jump Forward. I've got it set to jump in place but I can't seem to get the JumpFor() to move forward as it jumps. I've tried Vector3 but it only works in 1 direction and transform.forward doesn't seem to work at all.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
//VARIABLES
[SerializeField] private float moveSpeed;
[SerializeField] private float walkSpeed;
[SerializeField] private float runSpeed;
private Vector3 moveDirection;
private Vector3 velocity;
[SerializeField] private bool isGrounded;
[SerializeField] private float groundCheckDistance;
[SerializeField] private LayerMask groundMask;
[SerializeField] private float gravity;
[SerializeField] private float jumpHeight;
//REFERENCES
private CharacterController controller;
private Animator anim;
private Collider Collider;
private void Start()
{
controller = GetComponent();
anim = GetComponentInChildren();
Collider = GetComponent(); ;
}
private void Update()
{
Move();
}
private void Move()
{
isGrounded = Physics.CheckBox(Collider.bounds.center, Collider.bounds.extents, transform.rotation, groundMask);
if (isGrounded && velocity.y < 0)
velocity.y = -2f;
float moveZ = Input.GetAxis("Vertical");
moveDirection = new Vector3(0, 0, moveZ);
moveDirection = transform.TransformDirection(moveDirection);
if (isGrounded)
{
if (moveDirection != Vector3.zero && !Input.GetKey(KeyCode.LeftShift))
{
Walk();
}
else if (moveDirection != Vector3.zero && Input.GetKey(KeyCode.LeftShift))
{
Run();
}
else if (moveDirection == Vector3.zero)
{
Idle();
}
moveDirection *= moveSpeed;
if (isGrounded && Input.GetKeyDown(KeyCode.Space) && moveDirection == Vector3.zero )
{
Jump();
}
if (isGrounded && Input.GetKeyDown(KeyCode.Space) && Input.GetKey(KeyCode.W) && moveDirection != Vector3.zero)
{
JumpFor();
}
anim.SetBool("Jump", false);
anim.SetBool("JumpUp", false);
}
if (!isGrounded)
anim.SetBool("Jump", true);
controller.Move(moveDirection * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
private void Idle()
{
anim.SetFloat("Speed", 0, 0.02f, Time.deltaTime);
}
private void Walk()
{
moveSpeed = walkSpeed;
anim.SetFloat("Speed", 0.6f, 0.1f, Time.deltaTime);
}
private void Run()
{
moveSpeed = runSpeed;
anim.SetFloat("Speed", 1, 0.1f, Time.deltaTime);
}
private void Jump()
{
velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
}
private void JumpFor()
{
velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
}
}
I Solved it. I ended up using the velocity vector in JumpFor() and gave it a new Vector3 Then I put velocity= transform.TransformDirection(velocity) so it uses the local axis instead of the global one. After that is et it so velocity = Vector3.zero when the player grounds.
Blockquote
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
//VARIABLES
[SerializeField] private float moveSpeed;
[SerializeField] private float walkSpeed;
[SerializeField] private float runSpeed;
[SerializeField] private float JumpDist;
private Vector3 moveDirection;
private Vector3 velocity;
[SerializeField] private bool isGrounded;
[SerializeField] private float groundCheckDistance;
[SerializeField] private LayerMask groundMask;
[SerializeField] private float gravity;
[SerializeField] private float jumpHeight;
//REFERENCES
private CharacterController controller;
private Animator anim;
private Collider Collider;
private Rigidbody rb;
private Transform tran;
private void Start()
{
controller = GetComponent<CharacterController>();
anim = GetComponentInChildren<Animator>();
Collider = GetComponent<BoxCollider>(); ;
rb = GetComponent<Rigidbody>();
tran = GetComponent<Transform>();
}
private void Update()
{
Move();
}
private void Move()
{
isGrounded = Physics.CheckBox(Collider.bounds.center, Collider.bounds.extents, transform.rotation, groundMask);
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float moveZ = Input.GetAxis("Vertical");
moveDirection = new Vector3(0, 0, moveZ);
moveDirection = transform.TransformDirection(moveDirection);
if (isGrounded)
{
velocity = Vector3.zero;
if (moveDirection != Vector3.zero && !Input.GetKey(KeyCode.LeftShift))
{
Walk();
}
else if (moveDirection != Vector3.zero && Input.GetKey(KeyCode.LeftShift))
{
Run();
}
else if (moveDirection == Vector3.zero)
{
Idle();
}
moveDirection *= moveSpeed;
if (isGrounded && Input.GetKeyDown(KeyCode.Space) && moveDirection == Vector3.zero )
{
Jump();
}
if (isGrounded && Input.GetKeyDown(KeyCode.Space) && Input.GetKey(KeyCode.W) && moveDirection != Vector3.zero)
{
JumpFor();
}
anim.SetBool("Jump", false);
anim.SetBool("JumpUp", false);
}
if (!isGrounded)
{
anim.SetBool("Jump", true);
}
controller.Move(moveDirection * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
private void Idle()
{
anim.SetFloat("Speed", 0, 0.02f, Time.deltaTime);
}
private void Walk()
{
moveSpeed = walkSpeed;
anim.SetFloat("Speed", 0.6f, 0.1f, Time.deltaTime);
}
private void Run()
{
moveSpeed = runSpeed;
anim.SetFloat("Speed", 1, 0.1f, Time.deltaTime);
}
private void Jump()
{
velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
}
private void JumpFor()
{
velocity = new Vector3(0, Mathf.Sqrt(jumpHeight * -2 * gravity), Mathf.Sqrt(jumpHeight * -2 * gravity));
velocity= transform.TransformDirection(velocity);
}
}
Blockquote

Unity/C#: Consistency for controllable ball rolling

I created a movable 2D ball character but when it stops moving the ball continues spinning for a bit without moving, how can I fix this?
Here is the existing code:
public class Controller : MonoBehaviour
{
public float TotalJumpForce;
public float TotalDropForce;
public float jumps;
public float speed;
public float jumpForce;
public float dropforce;
bool isGrounded = false;
public Transform isGroundedChecker;
public float checkGroundRadius;
public LayerMask groundLayer;
Rigidbody2D rb;
void Start()
{
stalltimer = 1000;
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
TotalJumpForce = rb.velocity.y + jumpForce;
TotalDropForce = rb.velocity.y + dropforce;
CheckIfGrounded();
Move();
Jump();
Drop();
}
void Move()
{
float x = Input.GetAxisRaw("Horizontal");
float moveBy = x * speed;
rb.velocity = new Vector2(moveBy, rb.velocity.y);
}
void Jump()
{
if (Input.GetKeyDown("w"))
{
if (jumps > 0)
rb.velocity = new Vector2(rb.velocity.x, TotalJumpForce);
jumps = jumps - 1;
}
}
void Drop()
{
if (Input.GetKeyDown("s"))
{
rb.velocity = new Vector2(rb.velocity.x, TotalDropForce);
}
}
void CheckIfGrounded()
{
Collider2D collider = Physics2D.OverlapCircle(isGroundedChecker.position, checkGroundRadius, groundLayer);
if (collider != null)
{
isGrounded = true;
jumps = 2;
stalls = 3;
}
else
{
isGrounded = false;
}
}
}
Changing angular and linear drag doesn't make a difference. Changing the gravity scale doesnt seem to make a diffrence either.
You could check for input and reset the rb.angularVelocity in case there is no input
void Move()
{
var x = Input.GetAxisRaw("Horizontal");
var moveBy = x * speed;
rb.velocity = new Vector2(moveBy, rb.velocity.y);
if(Mathf.Approximately(move, 0f))
{
rb.angularVelocity = 0;
}
}

Unity/C#: I can not work out why this variable doesn't exist in the current context

This the entirety of my code because this problem is completely confusing me:
public class Controller : MonoBehaviour
{
public float stalls;
public float IntegerYVelocity;
public float TotalJumpForce;
public float TotalDropForce;
public float jumps;
public float speed;
public float jumpForce;
public float dropforce;
bool isGrounded = false;
public Transform isGroundedChecker;
public float checkGroundRadius;
public LayerMask groundLayer;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
TotalJumpForce = rb.velocity.y + jumpforce;
TotalDropForce = rb.velocity.y + dropforce;
CheckIfGrounded();
Move();
Jump();
Drop();
Stall();
}
void Move()
{
float x = Input.GetAxisRaw("Horizontal");
float moveBy = x * speed;
rb.velocity = new Vector2(moveBy, rb.velocity.y);
}
void Jump()
{
if (Input.GetKeyDown("w"))
{
if (jumps > 0)
rb.velocity = new Vector2(rb.velocity.x, TotalJumpForce);
jumps = jumps - 1;
}
}
void Drop()
{
if (Input.GetKeyDown("s"))
{
rb.velocity = new Vector2(rb.velocity.x, TotalDropForce);
}
}
void CheckIfGrounded()
{
Collider2D collider = Physics2D.OverlapCircle(isGroundedChecker.position, checkGroundRadius, groundLayer);
if (collider != null)
{
isGrounded = true;
jumps = 2;
}
else
{
isGrounded = false;
}
}
void Stall()
{
if (Input.GetKeyDown("q"))
{
if (stalls > 0)
rb.velocity = new Vector2(rb.velocity.x, 0);
stalls = stalls - 1;
}
}
}
But then i get this compiler error:
Assets\Controller.cs(29,42): error CS0103: The name 'jumpforce' does not exist in the current context
Which is confusing me because everything was fine until I added the stall void.
You forgot to capitalize the "F" in "jumpForce" on line 29.

Categories

Resources