花1.png

类吸血鬼实战(3):击中反馈、界面UI、物品数据管理

概要:类吸血鬼实战(3):击中反馈、界面UI、物品数据管理

第九课:击中反馈

击中后增加白闪效果

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    /*...*/
    void FixedUpdate()
    {
        if (!isLive || animator.GetCurrentAnimatorStateInfo(0).IsName("Hit")) return;
        Vector2 dirVec = target.position - rigidbody.position;
        Vector2 nextVec = dirVec.normalized * speed * Time.fixedDeltaTime;
        rigidbody.MovePosition(rigidbody.position + nextVec);
        rigidbody.velocity = Vector2.zero;
    }
    /*...*/
    void OnTriggerEnter2D(Collider2D collider)
    {
        /*...*/
        if (health > 0)
        {
            animator.SetTrigger("Hit");
        }
        else
        {
            Dead();
        }
    }
}

增加怪物击退

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    /*...*/
    WaitForFixedUpdate wait;
    void Awake()
    {
        /*...*/
        wait = new WaitForFixedUpdate();
    }
     /*...*/
    void OnTriggerEnter2D(Collider2D collider)
    {
        if (!collider.CompareTag("Bullet")) return;
        health -= collider.GetComponent<Bullet>().damage;
        StartCoroutine("KnockBack");
        if (health > 0)
        {
            animator.SetTrigger("Hit");
        }
        else
        {
            Dead();
        }
    }
    IEnumerator KnockBack()
    {
        yield return wait;
        Vector3 playerPos = GameManager.instance.player.transform.position;
        Vector3 dirVec = transform.position - playerPos;
        rigidbody.AddForce(dirVec.normalized * 3, ForceMode2D.Impulse);
    }
     /*...*/
}

死亡动画执行

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    /*...*/
    void OnTriggerEnter2D(Collider2D collider)
    {
        /*...*/
        if (health > 0)
        {
            animator.SetTrigger("Hit");
        }
        else
        {
            isLive = false;
            collider2D.enabled = false;
            rigidbody.simulated = false;
            spriteRenderer.sortingOrder = 1;
            animator.SetBool("Dead", true);
        }
    }
    /*...*/
}

动画帧执行函数

升级逻辑

level、kill、exp变量控制、增加自定义控制台title

GameManger脚本

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

public class GameManager : MonoBehaviour
{
    public static GameManager instance;
    [Header("# 游戏控制")]
    public float gameTime;
    public float maxGameTime = 2 * 10f;

    [Header("# 游戏信息")]
    public int level;
    public int kill;
    public int exp;
    public int[] nextExp = { 3, 5, 10, 100, 150, 210, 280, 360, 450, 600 };
    [Header("# 游戏组件")]
    public Player player;
    public PoolManager pool;
    /*...*/
    public void GetExp()
    {
        exp++;
        if (exp == nextExp[level])
        {
            level++;
            exp = 0;
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    /*...*/
    void OnTriggerEnter2D(Collider2D collider)
    {
        if (!collider.CompareTag("Bullet") || !isLive) return;
        health -= collider.GetComponent<Bullet>().damage;
        StartCoroutine("KnockBack");
        if (health > 0)
        {
            animator.SetTrigger("Hit");
        }
        else
        {
            isLive = false;
            collider2D.enabled = false;
            rigidbody.simulated = false;
            spriteRenderer.sortingOrder = 1;
            animator.SetBool("Dead", true);
            GameManager.instance.kill++;
            GameManager.instance.GetExp();
        }
    }
    /*...*/
}

第十课:界面UI

创建canvas画板、调整比例

创建HUD脚本

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

public class HUD : MonoBehaviour
{
    public enum InfoType { Exp, Level, Kill, Time, Health }
    public InfoType type;

    Text myText;
    Slider mySlider;

    void Awake()
    {
        myText = GetComponent<Text>();
        mySlider = GetComponent<Slider>();
    }

    void LateUpdate()
    {
        switch (type)
        {
            case InfoType.Exp:
                float curExp = GameManager.instance.exp;
                float maxExp = GameManager.instance.nextExp[GameManager.instance.level];
                mySlider.value = curExp / maxExp;
                break;
            case InfoType.Level:

                break;
            case InfoType.Kill:

                break;
            case InfoType.Time:

                break;
            case InfoType.Health:

                break;
        }
    }
}

血条UI、敌人UI、GameManger增加health变量

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

public class HUD : MonoBehaviour
{
    void LateUpdate()
    {
        switch (type)
        {
            case InfoType.Exp:
                float curExp = GameManager.instance.exp;
                float maxExp = GameManager.instance.nextExp[GameManager.instance.level];
                mySlider.value = curExp / maxExp;
                break;
            case InfoType.Level:
                myText.text = string.Format("Lv.{0:F0}", GameManager.instance.level);
                break;
            case InfoType.Kill:
                myText.text = string.Format("{0:F0}", GameManager.instance.kill);
                break;
            case InfoType.Time:

                break;
            case InfoType.Health:

                break;
        }
    }
}

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

public class GameManager : MonoBehaviour
{
    /*...*/
    public int health;
    public int maxHealth = 100;
    /*...*/
    void Awake()
    {
        instance = this;
    }
    void Start()
    {
        health = maxHealth;
    }
    /*...*/
}

C#输出格式介绍

增加Follow脚本矫正角色血条位置

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

public class Follow : MonoBehaviour
{
    RectTransform rect;
    // Start is called before the first frame update
    void Awake()
    {
        rect.GetComponent<RectTransform>();
    }
    void FixedUpdate()
    {
        rect.position = Camera.main.WorldToScreenPoint(GameManager.instance.player.transform.position);
    }
}

第十一课:创建ItemData物品数据管理

使用ScriptebleObject快速创建物品脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Item", menuName = "ScriptableObject/ItemData")]
public class ItemData : ScriptableObject
{
    public enum ItemType { Melee, Range, Glove, Shoe, Heal }
    [Header("# 主要数据")]
    public ItemType itemType;
    public int itemId;
    public string itemName;
    public string itemDesc;
    public Sprite itemIcon;
    [Header("# 升级数据")]
    public float baseDamage;
    public int baseCount;
    public float[] damages;
    public int[] cpunts;
    [Header("# 武器")]
    public GameObject projectile;
}

创建武器UI、与Item脚本

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class Item : MonoBehaviour
{
    public ItemData data;
    public int level;
    public Weapon weapon;

    Image icon;
    Text TextLevel;
    void Awake()
    {
        icon = GetComponentsInChildren<Image>()[1];
        icon.sprite = data.itemIcon;
        Text[] texts = GetComponentsInChildren<Text>();
        TextLevel = texts[0];
    }
    void LateUpdate()
    {
        TextLevel.text = "Lv." + (level + 1);
    }
    public void OnClick()
    {
        switch (data.itemType)
        {
            case ItemData.ItemType.Melee:
            case ItemData.ItemType.Range:
                if (level == 0)
                {
                    GameObject newWeapon = new GameObject();
                    weapon = newWeapon.AddComponent<Weapon>();
                    weapon.Init(data);
                }
                break;
            case ItemData.ItemType.Glove:
                break;
            case ItemData.ItemType.Shoe:
                break;
            case ItemData.ItemType.Heal:
                break;

        }
        level++;
        if (level == data.damages.Length)
        {
            GetComponent<Button>().interactable = false;
        }
    }
}

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

public class Weapon : MonoBehaviour
{
    /*...*/
    void Awake()
    {
        player = GameManager.instance.player;
    }
    /*...*/
    public void Init(ItemData data)
    {
        // Basie Set
        name = "Weapon" + data.itemId;
        transform.parent = player.transform;
        transform.localPosition = Vector3.zero;

        // Property Set
        id = data.itemId;
        damage = data.baseDamage;
        count = data.baseCount;

        for (int index = 0; index < GameManager.instance.pool.prefabs.Length; index++)
        {
            if (data.projectile == GameManager.instance.pool.prefabs[index])
            {
                prefabId = index;
                break;
            }
        }
        /*...*/
    }
    /*...*/
}

武器创建与升级脚本逻辑:Weapon、Item

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class Item : MonoBehaviour
{
    /*...*/
    public void OnClick()
    {
        switch (data.itemType)
        {
            /*...*/
                if (level == 0)
                {
                   /*...*/
                }
                else
                {
                    float nextDamage = data.baseDamage;
                    int nextCount = 0;
                    nextDamage += data.baseDamage * data.damages[level];
                    nextCount += data.counts[level];
                    weapon.LevelUp(nextDamage, nextCount);
                }
               /*...*/

        }
        /*...*/
    }
}

攻速、移动变更脚本:Gear

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

public class Gear : MonoBehaviour
{
    public ItemData.ItemType type;
    public float rate;
    public void Init(ItemData data)
    {
        // Basic Set
        name = "Gear" + data.itemId;
        transform.parent = GameManager.instance.player.transform;
        transform.localPosition = Vector3.zero;
        // Property Set
        type = data.itemType;
        rate = data.damages[0];
        ApplyGear();
    }
    public void LevelUp(float rate)
    {
        this.rate = rate;
        ApplyGear();
    }
    void ApplyGear()
    {
        switch (type)
        {
            case ItemData.ItemType.Glove:
                RateUp();
                break;
            case ItemData.ItemType.Shoe:
                SpeedUp();
                break;
        }
    }
    void RateUp()
    {
        Weapon[] weapons = transform.parent.GetComponentsInChildren<Weapon>();
        foreach (Weapon weapon in weapons)
        {
            switch (weapon.id)
            {
                case 0:
                    weapon.speed = 150 + (150 * rate);
                    break;
                default:
                    weapon.speed = 0.5f * (1f - rate);
                    break;
            }
        }
    }
    void SpeedUp()
    {
        float speed = 3;
        GameManager.instance.player.speed = speed + speed * rate;
    }
}

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class Item : MonoBehaviour
{
   
    /*...*/
    public Gear gear;
    public void OnClick()
    {
        switch (data.itemType)
        {
            case ItemData.ItemType.Melee:
            case ItemData.ItemType.Range:
                /*...*/
                level++;
                break;
            case ItemData.ItemType.Glove:
            case ItemData.ItemType.Shoe:
                if (level == 0)
                {
                    GameObject newGear = new GameObject();
                    gear = newGear.AddComponent<Gear>();
                    gear.Init(data);
                }
                else
                {
                    float nextRate = data.damages[level];
                    gear.LevelUp(nextRate);
                }
                level++;
                break;
            case ItemData.ItemType.Heal:
                GameManager.instance.health = GameManager.instance.maxHealth;
                break;

        }
        /*...*/
    }
}

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

public class Weapon : MonoBehaviour
{
     /*...*/
    public void LevelUp(float damage, int count)
    {
         /*...*/
        player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
    }
    public void Init(ItemData data)
    {
        /*...*/
        player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
    }
     /*...*/
}

Created By @Seeyou | 稀有博客