16.游戏场景-游戏主逻辑-主玩家相关
16.1 知识点
为防止特效影响主玩家飞机对象的显示,添加一个特效层。让主摄像机只渲染特效。主玩家飞机对象应该是默认层。我们新创建一个摄像机,用于渲染非特效层和UI层的对象,删除上面的音效监听器。调整几个摄像机的深度,从低到高分别是特效层,其他,UI层。对应主摄像机,新摄像机,NGUI摄像机。为了方便,我们把原来主摄像机的标签设置为普通摄像机,新创建的摄像机的标签设置为主摄像机。
分析主玩家飞机的需求。左右移动飞机的时候要有倾斜的效果。切换分辨率的时候边界判断也要适配。
创建主玩家角色脚本类PlayerObject脚本。继承MonoBehaviour类
// 玩家角色脚本类
public class PlayerObject : MonoBehaviour
{
}
PlayerObject脚本类创建血量,移动速度,选择速度,目标四元数角度,时候死亡等变量。
// 当前血量和最大血量
public int nowHp;
public int maxHp;
// 移动速度
public int speed;
// 旋转速度
public int roundSpeed;
// 目标四元数角度
private Quaternion targetQ;
// 是否死亡
public bool isDead;
添加角色死亡和受伤方法。死亡方法改变死亡标记显示游戏结束面板。受伤方法减少血量更新游戏面板上的血量显示,判断血量是否小于等于0调用死亡方法。
// 角色死亡方法
public void Dead()
{
// 标记角色已死亡
isDead = true;
// 显示游戏结束面板
GameOverPanel.Instance.ShowMe();
}
// 角色受伤方法
public void Wound()
{
// 如果已经死亡,返回,不再受伤
if (isDead)
return;
// 减少血量
this.nowHp -= 1;
// 更新游戏面板上的血量显示
GamePanel.Instance.ChangeHp(this.nowHp);
// 判断角色是否死亡
if (this.nowHp <= 0)
this.Dead();
}
实现玩家对象的移动和旋转逻辑。定义两个私有字段nowPos和frontPos,分别用于存储当前屏幕坐标和上一次玩家位置。此外,它还定义了两个私有字段hValue和vValue,用于存储水平和垂直输入值。PlayerObject类的Update方法中,首先检查玩家对象是否已经死亡。如果已经死亡,则直接返回,不再进行移动和旋转。接着获取水平和垂直输入值,并根据这些输入值计算目标旋转角度。然后,它使用Quaternion.Slerp方法让飞机朝着目标旋转角度旋转。在位移之前,它记录之前的位置,并使用Transform.Translate方法移动玩家对象。最后,进行极限判断并处理左右和上下溢出情况,防止飞机超出屏幕范围。首先将飞机当前位置从世界坐标系转换为屏幕坐标系,并赋值给nowPos变量。然后它分别判断了nowPos变量中x分量和y分量是否超出了屏幕宽度和高度的范围,如果是,则将飞机当前位置在对应轴上还原为移动之前的位置,并赋值给飞机的position属性。这样可以实现飞机不会超出屏幕左右或上下边缘。
// 当前世界坐标转屏幕上的点
private Vector3 nowPos;
// 上一次玩家的位置,即在位移前玩家所处的位置
private Vector3 frontPos;
// 水平和垂直的输入值
private float hValue;
private float vValue;
void Update()
{
// 如果角色已死亡,不再进行移动和旋转
if (isDead)
return;
// 移动和旋转逻辑
//得到ad键和ws键的输入
hValue = Input.GetAxisRaw("Horizontal");
vValue = Input.GetAxisRaw("Vertical");
// 旋转
// 如果没有按下左右方向键,则将目标四元数角度设置为 0 度
if (hValue == 0)
targetQ = Quaternion.identity;
// 如果按下左右方向键,根据左右方向键值确定旋转角度(20度或-20度),并设置为目标四元数角度
else
targetQ = hValue < 0 ? Quaternion.AngleAxis(20, Vector3.forward) : Quaternion.AngleAxis(-20, Vector3.forward);
// 让飞机朝着目标四元数去旋转,使用 Slerp 差值法使旋转更加平滑
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, targetQ, roundSpeed * Time.deltaTime);
//移动
// 在进行位移之前记录角色的上一次的位置
frontPos = this.transform.position;
// 进行移动:使用前后方向的输入值乘以速度来进行移动,同时使用左右方向的输入值按照世界坐标系进行移动
// 因为按下ad键的时候同时也会选择飞机对象,这样就移动的方向就不是直接左右移动 而是斜着向下偏移
this.transform.Translate(Vector3.forward * vValue * speed * Time.deltaTime);
this.transform.Translate(Vector3.right * hValue * speed * Time.deltaTime, Space.World);
// 进行极限边界判断:判断角色是否移出了屏幕范围
nowPos = Camera.main.WorldToScreenPoint(this.transform.position);
// 左右溢出判断
if (nowPos.x <= 0 || nowPos.x >= Screen.width)
{
this.transform.position = new Vector3(frontPos.x, this.transform.position.y, this.transform.position.z);
}
// 上下溢出判断
if (nowPos.y <= 0 || nowPos.y >= Screen.height)
{
this.transform.position = new Vector3(this.transform.position.x, this.transform.position.y, frontPos.z);
}
}
16.2 知识点代码
// 引用命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 玩家角色脚本类
public class PlayerObject : MonoBehaviour
{
// 当前血量和最大血量
public int nowHp;
public int maxHp;
// 移动速度
public int speed;
// 旋转速度
public int roundSpeed;
// 目标四元数角度
private Quaternion targetQ;
// 是否死亡
public bool isDead;
// 角色死亡方法
public void Dead()
{
// 标记角色已死亡
isDead = true;
// 显示游戏结束面板
GameOverPanel.Instance.ShowMe();
}
// 角色受伤方法
public void Wound()
{
// 如果已经死亡,返回,不再受伤
if (isDead)
return;
// 减少血量
this.nowHp -= 1;
// 更新游戏面板上的血量显示
GamePanel.Instance.ChangeHp(this.nowHp);
// 判断角色是否死亡
if (this.nowHp <= 0)
this.Dead();
}
// 当前世界坐标转屏幕上的点
private Vector3 nowPos;
// 上一次玩家的位置,即在位移前玩家所处的位置
private Vector3 frontPos;
// 水平和垂直的输入值
private float hValue;
private float vValue;
void Update()
{
// 如果角色已死亡,不再进行移动和旋转
if (isDead)
return;
// 移动和旋转逻辑
//得到ad键和ws键的输入
hValue = Input.GetAxisRaw("Horizontal");
vValue = Input.GetAxisRaw("Vertical");
// 旋转
// 如果没有按下左右方向键,则将目标四元数角度设置为 0 度
if (hValue == 0)
targetQ = Quaternion.identity;
// 如果按下左右方向键,根据左右方向键值确定旋转角度(20度或-20度),并设置为目标四元数角度
else
targetQ = hValue < 0 ? Quaternion.AngleAxis(20, Vector3.forward) : Quaternion.AngleAxis(-20, Vector3.forward);
// 让飞机朝着目标四元数去旋转,使用 Slerp 差值法使旋转更加平滑
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, targetQ, roundSpeed * Time.deltaTime);
//移动
// 在进行位移之前记录角色的上一次的位置
frontPos = this.transform.position;
// 进行移动:使用前后方向的输入值乘以速度来进行移动,同时使用左右方向的输入值按照世界坐标系进行移动
// 因为按下ad键的时候同时也会选择飞机对象,这样就移动的方向就不是直接左右移动 而是斜着向下偏移
this.transform.Translate(Vector3.forward * vValue * speed * Time.deltaTime);
this.transform.Translate(Vector3.right * hValue * speed * Time.deltaTime, Space.World);
// 进行极限边界判断:判断角色是否移出了屏幕范围
nowPos = Camera.main.WorldToScreenPoint(this.transform.position);
// 左右溢出判断
if (nowPos.x <= 0 || nowPos.x >= Screen.width)
{
this.transform.position = new Vector3(frontPos.x, this.transform.position.y, this.transform.position.z);
}
// 上下溢出判断
if (nowPos.y <= 0 || nowPos.y >= Screen.height)
{
this.transform.position = new Vector3(this.transform.position.x, this.transform.position.y, frontPos.z);
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com