一、创建尖刺预制体

1. 在prefabs文件夹新建一个尖刺预制体,并添加到场景面板上

unity自带的角色在哪_unity自带的角色在哪

2. 为尖刺预制体添加Box Collider 2D组件,设置碰撞体积,设置属性IsTrigger为true

unity自带的角色在哪_c#_02

3. 在Scripts文件夹新建一个Spine脚本,并添加到尖刺预制体上

unity自带的角色在哪_unity_03

二、编辑Ruby脚本

        详情见:【Unity2D:C#Script】为角色添加回血效果 

using Cinemachine.Utility;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEditor.Rendering;
using UnityEngine;

public class Ruby : MonoBehaviour {

    public int maxHealthPoint = 100;
    public int healthPoint;
    private int speed = 5;
    // 创建rb2d对象
    private Rigidbody2D rb2d;

    void Start() {
        // 设置游戏的帧率为60帧
        Application.targetFrameRate = 60;
        healthPoint = maxHealthPoint;
        // 用rb2d接收Rigidbody组件
        rb2d = GetComponent<Rigidbody2D>();
    }

    void Update() {
        // 创建float型Horizontal变量和Vertical变量,用来接受键盘输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        // 创建一个二维变量position来存储Rigidbody2D组件中的坐标
        Vector2 position = transform.position;

        // 控制Ruby移动
        position.x += horizontal * speed * Time.deltaTime;
        position.y += vertical * speed * Time.deltaTime;

        /*transform.position = position;*/
        rb2d.MovePosition(position);
    }

    public void changeHealthPoint(int value) {
        healthPoint = Mathf.Clamp(healthPoint+value, 0, maxHealthPoint);
        Debug.Log("HP:" + healthPoint + " / " + maxHealthPoint);
    }

}

三、编辑Spine脚本

1. 仿照上一章的内容,Spine脚本代码为:

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

public class Spine : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision) {
        Ruby ruby = collision.GetComponent<Ruby>();
        if(ruby != null) {
            if(ruby.healthPoint < ruby.maxHealthPoint) {
                ruby.changeHealthPoint(-40);
                Destroy(gameObject);
            }
        }
    }
}

2. 因为尖刺不是消耗品,和Ruby发生碰撞后不会消失,因此可以删除Destory()方法。同时无论Ruby是否满血,碰到尖刺都会损失生命值,因此也可以删掉判断Ruby是否满血的if条件语句

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

public class Spine : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision) {
        Ruby ruby = collision.GetComponent<Ruby>();
        if(ruby != null) {
            ruby.changeHealthPoint(-40);
        }
    }
}

3. 测试后发现,只有当Ruby进入尖刺时才会损失生命值,而我们想要的效果是只要Ruby在尖刺范围内就持续掉血。此时,需要将OnTriggerEnter2D()方法替换为OnTriggerStay2D()方法。与此同时,还需要将Ruby的Rigidbody 2D组件的SleepMode属性设置为Never Sleep,否则当Ruby不移动时将无法出发碰撞检测

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

public class Spine : MonoBehaviour
{
    private void OnTriggerStay2D(Collider2D collision) {
        Ruby ruby = collision.GetComponent<Ruby>();
        if(ruby != null) {
            ruby.changeHealthPoint(-40);
        }
    }
}

 

unity自带的角色在哪_unity自带的角色在哪_04

四、为主角添加无敌时间 

1. 修改后,Ruby虽然可以在尖刺范围内持续掉血,可是Ruby的血量在一瞬间就减到了0,是因为OnTriggerStay2D()方法每帧都执行一次,相当于每秒执行60次。因此我们需要给Ruby脚本添加无敌时间。首先添加三个变量:整型常量InvincibleTime(用const关键字来创建常量),是无敌状态的持续时间;浮点型变量invinibleTimer,作为计算无敌时间冷却的计时器;布尔变量isInvinible,表示现在是否处于无敌状态

using Cinemachine.Utility;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEditor.Rendering;
using UnityEngine;

public class Ruby : MonoBehaviour {

    // Ruby基础属性
    public int maxHealthPoint = 100;
    public int healthPoint;
    private int speed = 5;
    // 无敌时间
    public const int InvincibleTime = 2;
    public double invinibleTimer;
    public bool isInvinible;
    // 创建rb2d对象
    private Rigidbody2D rb2d;

    void Start() {
        // 设置游戏的帧率为60帧
        Application.targetFrameRate = 60;
        healthPoint = maxHealthPoint;
        // 用rb2d接收Rigidbody组件
        rb2d = GetComponent<Rigidbody2D>();
    }

    void Update() {
        // 创建float型Horizontal变量和Vertical变量,用来接受键盘输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        // 创建一个二维变量position来存储Rigidbody2D组件中的坐标
        Vector2 position = transform.position;

        // 控制Ruby移动
        position.x += horizontal * speed * Time.deltaTime;
        position.y += vertical * speed * Time.deltaTime;

        rb2d.MovePosition(position);
    }

    public void changeHealthPoint(int value) {
        healthPoint = Mathf.Clamp(healthPoint+value, 0, maxHealthPoint);
        Debug.Log("HP:" + healthPoint + " / " + maxHealthPoint);
    }

}

2. 在Start()方法中初始化变量invinibleTimer和isInvinible;在Update()方法中判断isInvinible是否为true,若为true,invinibleTimer将每秒减少1,当invinibleTimer减到小于0时,说明无敌状态已经结束,设置isInvinible的值为false

using Cinemachine.Utility;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEditor.Rendering;
using UnityEngine;

public class Ruby : MonoBehaviour {

    // Ruby基础属性
    public int maxHealthPoint = 100;
    public int healthPoint;
    private int speed = 5;
    // 无敌时间
    public const int InvincibleTime = 2;
    public double invinibleTimer;
    public bool isInvinible;
    // 创建rb2d对象
    private Rigidbody2D rb2d;

    void Start() {
        // 设置游戏的帧率为60帧
        Application.targetFrameRate = 60;
        // 用rb2d接收Rigidbody组件
        rb2d = GetComponent<Rigidbody2D>();
        // 初始化变量
        healthPoint = maxHealthPoint;
        invinibleTimer = 0;
    }

    void Update() {
        // 创建float型Horizontal变量和Vertical变量,用来接受键盘输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        // 创建一个二维变量position来存储Rigidbody2D组件中的坐标
        Vector2 position = transform.position;

        // 控制Ruby移动
        position.x += horizontal * speed * Time.deltaTime;
        position.y += vertical * speed * Time.deltaTime;
        rb2d.MovePosition(position);

        // 无敌时间计时器
        if(isInvinible == true) {
            invinibleTimer -= Time.deltaTime;
            if(invinibleTimer < 0) {
                isInvinible = false;
            }
        }
    }

    public void changeHealthPoint(int value) {
        healthPoint = Mathf.Clamp(healthPoint+value, 0, maxHealthPoint);
        Debug.Log("HP:" + healthPoint + " / " + maxHealthPoint);
    }

}

        注:Time.deltaTime等于每帧的秒数,每秒调用的次数(等于帧数)*  每帧的秒数=1秒,因此invinibleTimer -= Time.deltaTime的含义就是invinibleTimer的值每秒减少1

3. 打开Spine脚本,给减少生命值的语句加一层if条件语句,同时设置invinibleTimer和invinibleTimer的值

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

public class Spine : MonoBehaviour
{
    private void OnTriggerStay2D(Collider2D collision) {
        Ruby ruby = collision.GetComponent<Ruby>();
        if(ruby != null) {
            if(ruby.isInvinible == false) {
                ruby.changeHealthPoint(-40);
                ruby.invinibleTimer = 2;
                ruby.isInvinible = true;
            }
        }
    }
}

        进入Unity,可以看到Ruby的无敌效果已经制作完成,本章完。