Unity-BattleStar丨9. BattleStar实战:给游戏添加物理系统

2024-08-14 16:37:50 浏览数 (1)

本节要实现的目标:

1、玩家拾取血包增加血量

2、玩家可用激光对NPC造成伤害

一、导入资源文件

文件下载:地址

1、导入Package

2、运行_Scenes里面的BattleStar_GameScene场景,观察

二、NavMesh寻路系统

1、添加自动寻路脚本

我们发现,在Hierarchy里面有GameOverPosition,它代表着我们到达该地,将取得游戏胜利。我们添加自动寻路脚本,观察在迷宫中如何到达目的地。我们先将FPSController设置为NavMesh Agent,自动寻路到该位置看看实际效果。

给FPSController添加endPosition脚本、NavMeshAgent组件,并取消激活FPSController的First Person Controller脚本,避免功能冲突

代码语言:javascript复制
using UnityEngine;
using UnityEngine.AI;

public class endPosition : MonoBehaviour {

    NavMeshAgent agent;

    private void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        agent.destination = GameObject.Find("GameOverPosition").transform.position;
    }
} 

2、重设NavMesh寻路区域

我们发现,FPSController找到了目的地,但它在某地区是穿墙而过。这是不合逻辑的。我们重新设置下NavMesh寻路区域:

Navigation-Object-Mesh Renderer将Door设置成Walkable;Floor勾选Navigation Static-Walkable;Floor_Plane取消勾选Navigation Static;mazemodel-Not Walkable;outside-Not Walkable;Roof-Not Walkable;Wall_1、3-Walkable;Wall_2、4-Not Walkable。Bake

运行游戏,我们发现FPSController正确寻路到目标点,现在我们完成了系统的NavMesh寻路系统设置,接下来我们增加人物捡到血包加血功能

三、实现血包加血功能

观察游戏项目,我们发现控制人物血量的属性PlayerHealth在FPSController—Player脚本里面

1、除了场景中的血包外,我们再在FPSController附近另增加两个如下图所示血瓶,model位于Assets-Plugins-HealthMedicalSet-Models-bottle 02

2、添加Mesh Collider,更改Shader使其看起来更好看些

3、添加如下代码,让瓶子运行时自转

代码语言:javascript复制
using UnityEngine;

public class RotateSelf : MonoBehaviour {

    int RotateSpeed = 90;

	void Update () {
        transform.Rotate(Vector3.up * RotateSpeed * Time.deltaTime, Space.World);
	}
}

4、激活FPSController的First Person Controller脚本,停止运行End Position,可看到如下效果。后续这类操作不再赘述

5、给血瓶增添触发代码

a、修改FPSController-Player代码,public int static playerHealth=5改为public int playerHealth=5,这样我们便能在面板看到初始血量,当然,我们赋值的应该是下方的PlayerHealth属性

b、我们给血瓶赋予脚本blood,该脚本用于给玩家增加血量

本操作用到了Collider的OnTriggerEnter方法。当带有Collider组件的物体接触到外物时,会触发它的OnColliderEnter方法,但当该物体开启Is Trigger时,两个物体就变为可穿透状态了。当穿透时,系统会自动触发OnTriggerEnter方法

代码语言:javascript复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class blood : MonoBehaviour
{

    void OnTriggerEnter(Collider other)
    {
        if (other.name == "FPSController")
        {
            if (other.GetComponent<Player>().PlayerHealth < 5)
            {
                other.GetComponent<Player>().PlayerHealth  = 1;
                //计算方法: 把左边的变量和第一个符号移到右边, 变量1 = 变量1   表达式运算结果)
                //如:i  = 1           则是: i = i   1
                //i  = 1   2 * 3  则是: i = i   (1   2 * 3)
            }
        }
    }
}

6、我们只完成了给人物增加血量,但人物一开始血量是满的,我们再增加一个减血瓶,效果是接触后减3滴血,观看效果

代码语言:javascript复制
using UnityEngine;

public class blood_down : MonoBehaviour {

    void OnTriggerEnter(Collider other)
    {
        if (other.name == "FPSController")
        {
            other.GetComponent<Player>().PlayerHealth -= 3;
        }
    }
}

减血、加血过多是因为碰撞后未立即销毁对象,出现多次减血加血现象,这对我们观察无影响。读者可自行尝试在代码里添加Destroy(gameObject)销毁目标

四、玩家用激光对NPC造成伤害

本节用到的关键代码是Physics.Raycast,可回顾上篇文章——Physics.Raycast()知识点讲解,和我们之前做过的动画项目——Unity动画射线Physics.Raycast()

本节设计思路:准星位于屏幕中央,即从屏幕中央处开火。运用Physics.Raycast()方法,当按下鼠标左键时发射射线,返回射线检测到的物体。如果是机器人,则更改机器人的血量值,使其减少展现出造成伤害的效果

当然,这要求我们不断检测是否按下鼠标左键,若写在Update函数中,会很消耗计算资源。我们运用协程方法StartCorotine()方法,来不断执行该命令,减少资源消耗

1、本项目是有准星来瞄准的,但我们发现捡到枪后准星并没有出现,我们将HUDCanvas—GamePanel—ReticleImage的Scalex、y、z设置成2,放大准星

2、本项目玩家发射子弹是采用了开火动画 射线检测方式,代码位于Gun中,Gun作为组件放在FPSController—FirstPersonCharacter—GunWithHand上。当射线碰撞检测到Robot,会调用Robot代码中的RobotHealth,使RobotHealth--使其受伤。下面展示的Robot中的代码,保证当Robot生命值为0时,调用RobotDie()方法

代码语言:javascript复制
    private float robotHealth;
    public float RobotHealth
    {
        get
        {
            return robotHealth;
        }

        set
        {
            robotHealth = value;

            healthImage.localScale = new Vector3(value / 5, 1, 1);

            if (robotHealth == 0)
            {
                RobotDie();
            }
        }
    }

当然,我们发现Robot代码中也包含如下代码,我们也可在Gun中直接调用这段代码,造成机器人生命值减一的效果

代码语言:javascript复制
    public void RobotGetHurt()
    {
        RobotHealth -= 1;
    }

3、当Robot生命值下降后,在Robot代码的RobotHealth属性set中,本项目写了healthImage.localScale = new Vector3(value / 5, 1, 1)代码,用来缩放Robot头上血条,呈现出减血的效果

Transform.localScale 自身缩放

代码语言:javascript复制
//扩大物体的x轴向0.1个单位
transform.localScale  = Vector3(0.1,0,0);

本项目的Gun、GunModelTrigger、HealthPackage、Robot代码包含本节内容,读者可重点观察,加深本节印象。

最后新开“第九章U3D代码注解”一文记录本章重点代码,用于速查定义节省时间

0 人点赞