14.下平台
14.1 知识点
要点分析
RoleObj脚本添加当前玩家是否在下落状态的外部属性
//得到当前玩家是否在下落状态
public bool isFall => roleAnimator.GetBool("isFall");
在Update检跳跃时位移变化时,添加或条件,假如是下落状态Y 坐标也需要变化
//跳跃状态时 Y 坐标的变化
//下落状态时 Y 坐标也需要变化
if(isJump || isFall)
添加玩家下落方法。切换动画且把当前平台y设置成一个很小的值,防止被平台拉回来。由于是自由落体,我们Y上的速度应该从0开始。在下落时只允许跳一次,修改跳跃计数为1.
/// <summary>
/// 玩家下落方法
/// </summary>
public void Fall()
{
//动作的切换
roleAnimator.SetBool("isFall", true);
//相当于把平台设置为null的感觉
//把它设置为一个非常小的数 那么这样 在更新跳跃下落时
//就不会把它拉回之前平台的位置了
nowPlatformY = -9999;
//由于是自由落体 我们Y上的速度应该从0开始
//避免之前有残留 所以我们将其清0
nowYSpeed = 0;
//由于在下落时只允许跳一次 所以我们将计数从1开始
//这样再下落过程中就不会进行二段跳了
jumpIndex = 1;
}
在平台逻辑处理类的每帧检测玩家平台变化的函数中,假如玩家下落时也进入切换平台逻辑。且添加检测当前所在平台是否满足了下平台的条件,满足的话让玩家下落。
/// <summary>
/// 用于每帧检测玩家平台变化的函数
/// </summary>
public void UpdateCheck()
{
//当玩家跳跃时 才会切换平台
//当玩家下落时 也会切换平台
if(obj.isJump || obj.isFall)
{
//...
}
//只会检测当前所在平台 是否满足了下平台的条件
if( nowPlatform != null &&
!nowPlatform.CheckObjFallOnMe(obj.transform.position))
{
obj.Fall();
}
}
14.2 知识点代码
RoleObj
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoleObj : MonoBehaviour
{
//移动速度
public float moveSpeed = 5;
//初始跳跃时的 竖直上抛速度
public float initYSpeed = 10;
//重力加速度
public float G = 9.8f;
//影子对象
public GameObject shadowObj;
//当人跳这么高时 影子缩放为0 消失
public float jumpMaxH = 5;
//影子的位置
private Vector3 shadowPos;
//跳跃当中 实时的速度是多少
private float nowYSpeed;
//当前平台的 Y 值
private float nowPlatformY;
//是否可以主动下落
private bool canFall;
//二段跳计数
private int jumpIndex;
//动画控制相关组件
private Animator roleAnimator;
//输入移动相关的系数
private float horizontalMove;
//用于处理上下平台的逻辑对象
PlatformLogic platformLogic;
//得到当前玩家是否是跳跃状态
public bool isJump => roleAnimator.GetBool("isJump");
//得到当前玩家是否在下落状态
public bool isFall => roleAnimator.GetBool("isFall");
void Start()
{
roleAnimator = this.GetComponent<Animator>();
shadowPos = shadowObj.transform.position;//避免影子挡住脚
platformLogic = new PlatformLogic(this);
}
void Update()
{
#region 移动相关逻辑
//得到水平方向的输入 一般就是左右键输入
//-1 0 1 三个值
horizontalMove = Input.GetAxisRaw("Horizontal");
//面朝左
if (horizontalMove < 0)
this.transform.rotation = Quaternion.Euler(0, -90, 0);
else if (horizontalMove > 0)
this.transform.rotation = Quaternion.Euler(0, 90, 0);
//当有输入时,直接朝面朝向移动即可
if (horizontalMove != 0)
this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
//跑步动画的切换
roleAnimator.SetBool("isRun", horizontalMove != 0);
#endregion
#region 跳跃逻辑
if(Input.GetKeyDown(KeyCode.Space) && jumpIndex != 2)
{
//跳跃
roleAnimator.SetBool("isJump", true);
//当前Y速度 = 竖直上抛的初始速度
nowYSpeed = initYSpeed;
//二段跳计数 只能连续跳两次
++jumpIndex;
}
//跳跃状态时 Y 坐标的变化
//下落状态时 Y 坐标也需要变化
if(isJump || isFall)
{
//位移逻辑
this.transform.Translate(Vector3.up * nowYSpeed * Time.deltaTime);
//收到重力加速度的影响 每一帧 都去改变当前的移动速度
nowYSpeed -= G * Time.deltaTime;
//当竖直方向的速度小于等于0 就应该播放 下落的动画
roleAnimator.SetBool("isFall", nowYSpeed <= 0);
//判断是否落在了对应平台上
if( this.transform.position.y <= nowPlatformY )
{
//停止跳跃动画
roleAnimator.SetBool("isJump", false);
roleAnimator.SetBool("isFall", false);
//避免下落时 落到"平台里" 把它拉回来
Vector3 pos = this.transform.position;
pos.y = nowPlatformY;
this.transform.position = pos;
//落地时才去清楚二段跳计数
jumpIndex = 0;
}
}
#endregion
#region 影子相关逻辑
//移动相关
shadowPos.x = this.transform.position.x;//跟随玩家动
shadowPos.y = nowPlatformY;//影子的y的位置 一定是和平台一致的
shadowObj.transform.position = shadowPos;
//缩放相关
shadowObj.transform.localScale = 1.5f * Vector3.one * Mathf.Max(0, (jumpMaxH - (this.transform.position.y - nowPlatformY))) / jumpMaxH;
#endregion
#region 平台切换相关逻辑
platformLogic.UpdateCheck();
#endregion
}
/// <summary>
/// 去改变平台相关信息的
/// </summary>
/// <param name="y"></param>
/// <param name="showShadow"></param>
/// <param name="canFall"></param>
public void ChangePlatformData(float y, bool showShadow, bool canFall)
{
//改变当前平台的Y
this.nowPlatformY = y;
//是否显示影子
shadowObj.gameObject.SetActive(showShadow);
//是否可以在该平台下落
this.canFall = canFall;
}
/// <summary>
/// 玩家下落方法
/// </summary>
public void Fall()
{
//动作的切换
roleAnimator.SetBool("isFall", true);
//相当于把平台设置为null的感觉
//把它设置为一个非常小的数 那么这样 在更新跳跃下落时
//就不会把它拉回之前平台的位置了
nowPlatformY = -9999;
//由于是自由落体 我们Y上的速度应该从0开始
//避免之前有残留 所以我们将其清0
nowYSpeed = 0;
//由于在下落时只允许跳一次 所以我们将计数从1开始
//这样再下落过程中就不会进行二段跳了
jumpIndex = 1;
}
}
PlatformLogic
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 平台逻辑处理类
/// </summary>
public class PlatformLogic
{
//对应游戏对象
private RoleObj obj;
//游戏对象当前所在平台
private Platform nowPlatform;
//游戏中所有平台数据
private List<Platform> platformData;
public PlatformLogic(RoleObj obj)
{
this.obj = obj;
nowPlatform = null;
platformData = PlatformDataMgr.Instance.platformList;
}
/// <summary>
/// 用于每帧检测玩家平台变化的函数
/// </summary>
public void UpdateCheck()
{
//当玩家跳跃时 才会切换平台
//当玩家下落时 也会切换平台
if(obj.isJump || obj.isFall)
{
//让每一次遍历寻找到的平台 是这一瞬间最高的平台 而不是整个跳跃轨迹中的最高平台
nowPlatform = null;
for (int i = 0; i < platformData.Count; i++)
{
//不停的判断玩家是否处于落在某个平台的条件下
if( platformData[i].CheckObjFallOnMe(obj.transform.position) &&
(nowPlatform == null || nowPlatform.Y < platformData[i].Y))
{
//记录当前平台
nowPlatform = platformData[i];
//更新玩家相关的平台数据
obj.ChangePlatformData(nowPlatform.Y, nowPlatform.canShowShadow, nowPlatform.canFall);
}
}
}
//只会检测当前所在平台 是否满足了下平台的条件
if( nowPlatform != null &&
!nowPlatform.CheckObjFallOnMe(obj.transform.position))
{
obj.Fall();
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com