在做人物跳跃功能的时候发现官方的方法在视觉效果上很差,其他一些方案比如加刚体等等都效果不好,于是自己写了一个模拟力作用的跳跃算法。
首先定义了5个全局变量来完成跳跃算法的实现
public float jumpSpeed = 2;//跳跃速度
public float gravity = 2;//模拟重力
public bool isJump = false;//是否在跳跃
public float jumpTime= 0.5f;//跳跃时间
public float jumpTimeFlag = 0;//累计跳跃时间用来判断是否结束跳跃
在Update()方法中实现在按下相应按键的时候改变人物状态
if(Input.GetKey(KeyCode.W)&& Input.GetKeyDown(KeyCode.Space)&& !isJump)
{
isJump = true;
playState = PlayState.Jump;
characterController.Move(transform.forward * speed*Time.deltaTime);
}
else if (Input.GetKey(KeyCode.W))
{
isMoving = true;
playState = PlayState.Moving;
characterController.Move(transform.forward * speed * Time.deltaTime);
}
else if (Input.GetKeyDown(KeyCode.Space)&&!isJump)
{
isJump = true;
playState = PlayState.Jump;
}else
{
playState = PlayState.Idle;
isMoving = false;
}
** 如果在跳跃状态,并且当前时间没有到达跳跃时间,则持续向上移动如果到达跳跃时间,那么持续下降直到遇到地面**
if (isJump)
{
if (jumpTimeFlag<jumpTime)
{
characterController.Move(transform.up * jumpSpeed*Time.deltaTime);
jumpTimeFlag += Time.deltaTime;
}else if(jumpTime < jumpTimeFlag)
{
characterController.Move(transform.up * -gravity * Time.deltaTime);
}
if(characterController.collisionFlags == CollisionFlags.Below)
{
jumpTimeFlag = 0;
isJump = false;
}
}
在不是跳跃状态的时候使人物始终接触地面
else
{
if (characterController.collisionFlags != CollisionFlags.Below)
characterController.Move(transform.up * -gravity * Time.deltaTime);
}
附完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PlayState
{
Moving,
Idle,
Jump
}
public class PlayerMove : MonoBehaviour
{
//private PlayerDir dir;
private CharacterController characterController;
public float speed = 3;
public float jumpSpeed = 2;//跳跃速度
public float gravity = 2;//模拟重力
public PlayState playState = PlayState.Idle;
public bool isMoving = false;
public bool isJump = false;//是否在跳跃
public float jumpTime= 0.5f;//跳跃时间
public float jumpTimeFlag = 0;//累计跳跃时间用来判断是否结束跳跃
private void Start()
{
//dir = this.GetComponent<PlayerDir>();
characterController = this.GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
//float distance = Vector3.Distance(dir.GetTargetPosition(),this.transform.position);
if(Input.GetKey(KeyCode.W)&& Input.GetKeyDown(KeyCode.Space)&& !isJump)
{
isJump = true;
playState = PlayState.Jump;
characterController.Move(transform.forward * speed*Time.deltaTime);
}
else if (Input.GetKey(KeyCode.W))
{
isMoving = true;
playState = PlayState.Moving;
characterController.Move(transform.forward * speed * Time.deltaTime);
}
else if (Input.GetKeyDown(KeyCode.Space)&&!isJump)
{
isJump = true;
playState = PlayState.Jump;
}else
{
playState = PlayState.Idle;
isMoving = false;
}
if (isJump)
{
if (jumpTimeFlag<jumpTime)
{
characterController.Move(transform.up * jumpSpeed*Time.deltaTime);
jumpTimeFlag += Time.deltaTime;
}else if(jumpTime < jumpTimeFlag)
{
characterController.Move(transform.up * -gravity * Time.deltaTime);
}
if(characterController.collisionFlags == CollisionFlags.Below)
{
jumpTimeFlag = 0;
isJump = false;
}
}
else
{
if (characterController.collisionFlags != CollisionFlags.Below)
characterController.Move(transform.up * -gravity * Time.deltaTime);
}
}
}