概要:类吸血鬼实战(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);
}
/*...*/
}