unity玩家血量控制,定时掉血,道具加血

首先将玩家,加血道具,掉血道具添加进场景中

为玩家挂接碰撞体和刚体

unity扣血函数_ci

而两种道具只需要挂接碰撞体

 

下面是玩家的挂接脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RubyController : MonoBehaviour
{
    //设置玩家无敌时间间隔
    public float timelnvincible = 2.0f;
    //设置是否无敌变量
    bool islnvincible;
    //定义变量,进行无敌时间的计时,无敌时间计时器
    float invincibleTimer;

    //设置最大生命值(生命上限)
    public int maxHealth = 5;
    //设置当前生命值的属性health
    //C#中支持面向对象程序设计中的封装概念,对数据成员的保护
    //数据成员变量,默认一般都应该设为私有,只能通过当前类的方法或属性进行访问
    //属性是公有的,可以通过取值器get、赋值器set设定对应字段的访问规则,满足规则才能够访问
    int currentHealth;
    public int health
    {
        get { return currentHealth; }
        //set {currentHealth=value;}
    }


    //为了防止角色发生抖动(若要防止角色发生旋转,需要将角色中的Rigidbody 2D组件中的Constraints中的Z轴锁定)
    //声明刚体对象
    Rigidbody2D rigidbody2D;

    //获取用户输入
    float horizontal;
    float vertical;

    //该方法以单位每秒来表示移动速度
    //将速度暴露出来,使其可调
    public float speed = 3.0f;

    private void Start()
    {
        //获取当前游戏对象的刚体组件
        rigidbody2D = GetComponent<Rigidbody2D>();
        //游戏开始前,玩家满血
        //初始化当前生命值
        currentHealth = maxHealth;
    }

    //每帧调用一次Update
    void Update()
    {
        horizontal = Input.GetAxis("Horizontal");
        vertical = Input.GetAxis("Vertical");

        //判断是否处于无敌状态,来进行计时器倒计时
        if(islnvincible){
            //如果无敌,进入倒计时
            //每次update减去一帧所消耗的时间
            invincibleTimer -= Time.deltaTime;
            if (invincibleTimer<0)
            {
                islnvincible = false;
            }
        }
        
    }
    //为了使物理计算保持稳定(只要牵扯物理引擎相关方法,都需要放到FixedUpdate函数中)
    //固定时间间隔执行的方法(不论硬件条件如何)
    private void FixedUpdate()
    {
        Vector2 position = rigidbody2D.position;
        position.x = position.x + speed * horizontal * Time.deltaTime;//Time.deltaTime表示帧所需要的时间
        //因为每台机器的帧数刷新不同,所以需要乘上各台电脑的每帧刷新的时长,这样就能确保各台电脑每次按下按键后的移动距离都相同
        position.y = position.y + speed * vertical * Time.deltaTime;
        rigidbody2D.MovePosition(position);
    }
    //更改生命值的方法
    public void ChangeHealth(int amount)
    {
        //假设玩家受伤害的时间间隔是2秒
        if (amount<0)//当玩家扣血时
        {
            //判断玩家当前是否处于无敌状态
            if (islnvincible)
            {
                return;//当玩家处于无敌状态时,return后面的所有函数内的语句都不执行,不掉血也不输出信息
            }
            islnvincible = true;
            invincibleTimer = timelnvincible;
        }

        //限制方法,限制当前生命值的赋值范围:0-最大生命值
        currentHealth = Mathf.Clamp(currentHealth+amount,0,maxHealth);//Mathf是一个静态类中的静态方法,不需要创建对象即可直接调用,Mathf是一个通用的数学函数
        //在控制台输出生命信息
        Debug.Log("当前生命值:"+currentHealth+"/"+maxHealth);
    }

    // Start is called before the first frame update
    //void Start()
    //{
    //    //只有将垂直同步设置成0,才能锁帧,否则锁帧的代码无效(但实际操作上设置为1同样也可锁帧)
    //    //垂直同步的作用就是显著减少游戏画面撕裂、跳帧,因为画面的渲染不是整个画面一同渲染的,而是逐行逐列渲染的
    //    QualitySettings.vSyncCount = 0;
    //    //设置应用程序帧数为10
    //    Application.targetFrameRate = 10;

    //}

    // Update is called once per frame
    //void Update()
    //{
    //    //获取水平输入,按向左,会获得-0.1f;按向右会获得1.0f
    //    float horizontal = Input.GetAxis("Horizontal");
    //    //获取垂直输入,按向下,会获得-0.1f;按向上会获得1.0f
    //    float vertical = Input.GetAxis("Vertical");
    //    //创建一个Vector2对象positon,用来获取当前对象的位置
    //    //Vector2是一个系统类,是C#中自带的一个类(Unity中的类),Vector2 position来描述2D的位置
    //    Vector2 position = transform.position;
    //    //更改position的x坐标值,让其加上0.1
    //    position.x = position.x + 0.1f*horizontal;
    //    position.y= position.y+ 0.1f*vertical;
    //    //更新当前对象的位置到新的位置
    //    transform.position = position;
    //}
}

在加血道具和减血物体中,由于碰撞需要,需要将碰撞体组件中的Is Trigger勾上,这样玩家不仅可以通过碰撞体触发事件,还能够不被道具影响行进路线

unity扣血函数_游戏引擎_02

下面是加血道具挂接脚本

为了让加血道具只能够使用一次,当玩家并不满血,拾到加血道具时,加血道具会消失(被销毁)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HealthCollectible : MonoBehaviour
{
    //草莓加的血量
    public int amount = 1;
    //用来记录碰撞次数
    //int collideCount=0;
    //添加触发器碰撞事件,每次发生碰撞时,执行器中的代码
    private void OnTriggerEnter2D(Collider2D other)
    {
        //collideCount = collideCount + 1;
        //Debug.Log($"和当前物体发生碰撞的对象是:{other},当前是第{collideCount}次碰撞");
        
        //获取Ruby游戏对象的脚本组件对象
        RubyController rubyController = other.GetComponent<RubyController>();
        
        if (rubyController!=null)
        {
            //当获取到脚本组件对象的时候再执行下列代码,防止出现错误
            if (rubyController.health<rubyController.maxHealth)
            {
                //更改生命值
                rubyController.ChangeHealth(amount);
                //销毁当前游戏对象
                //可以让草莓被吃掉
                Destroy(gameObject);
            }
            else
            {
                Debug.Log("当前玩家满血,不需要加血");
            }
           
        }
        else
        {
            // 当未获取到对象时(出错了),则报出提示错误
            Debug.LogError("rubyController游戏组件并未获取到......");
        }
       
    }
}

减血道具与加血道具类似,将影响血量值改为负数即可

但与加血道具不同的一点是,若不控制每次减血的时间间隔(由于每次刷新都将响应减血),则在一秒内,所有血量都将清空。

所以我们需要设置一个控制器,来解决血量的瞬间减少的问题,该控制器设置在玩家的脚本身上(看上面的玩家脚本,都带有注释),实现的是,玩家走上地刺,每两秒钟间隔会扣一次血,捡到草莓时,草莓消失,玩家加血。

unity扣血函数_游戏引擎_03

 

下面是减血道具的挂接脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DamageZone : MonoBehaviour
{
    public int damageNum = -1;//减少的血量
    private void OnTriggerStay2D(Collider2D other)
    {
        RubyController rubyController = other.GetComponent<RubyController>();
        if (rubyController!=null)//当获取对象不为空时再进行血量控制函数的调用
        {
            rubyController.ChangeHealth(damageNum);
        }
    }
}

如有疑问欢迎留言或私信

谢谢!