16.玩家

  1. 16.游戏场景-游戏主逻辑-主玩家相关
    1. 16.1 知识点
      1. 为防止特效影响主玩家飞机对象的显示,添加一个特效层。让主摄像机只渲染特效。主玩家飞机对象应该是默认层。我们新创建一个摄像机,用于渲染非特效层和UI层的对象,删除上面的音效监听器。调整几个摄像机的深度,从低到高分别是特效层,其他,UI层。对应主摄像机,新摄像机,NGUI摄像机。为了方便,我们把原来主摄像机的标签设置为普通摄像机,新创建的摄像机的标签设置为主摄像机。
      2. 分析主玩家飞机的需求。左右移动飞机的时候要有倾斜的效果。切换分辨率的时候边界判断也要适配。
      3. 创建主玩家角色脚本类PlayerObject脚本。继承MonoBehaviour类
      4. PlayerObject脚本类创建血量,移动速度,选择速度,目标四元数角度,时候死亡等变量。
      5. 添加角色死亡和受伤方法。死亡方法改变死亡标记显示游戏结束面板。受伤方法减少血量更新游戏面板上的血量显示,判断血量是否小于等于0调用死亡方法。
      6. 实现玩家对象的移动和旋转逻辑。定义两个私有字段nowPos和frontPos,分别用于存储当前屏幕坐标和上一次玩家位置。此外,它还定义了两个私有字段hValue和vValue,用于存储水平和垂直输入值。PlayerObject类的Update方法中,首先检查玩家对象是否已经死亡。如果已经死亡,则直接返回,不再进行移动和旋转。接着获取水平和垂直输入值,并根据这些输入值计算目标旋转角度。然后,它使用Quaternion.Slerp方法让飞机朝着目标旋转角度旋转。在位移之前,它记录之前的位置,并使用Transform.Translate方法移动玩家对象。最后,进行极限判断并处理左右和上下溢出情况,防止飞机超出屏幕范围。首先将飞机当前位置从世界坐标系转换为屏幕坐标系,并赋值给nowPos变量。然后它分别判断了nowPos变量中x分量和y分量是否超出了屏幕宽度和高度的范围,如果是,则将飞机当前位置在对应轴上还原为移动之前的位置,并赋值给飞机的position属性。这样可以实现飞机不会超出屏幕左右或上下边缘。
    2. 16.2 知识点代码

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

×

喜欢就点赞,疼爱就打赏