【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/
UI部分暂时完结!!!
本章节优化了UI中物品描述的显示效果,技能描述的显示效果
并且可以批量化更改文本描述
主要通过更改继承实现
UI_ToolTip.cs
以下脚本都不同程度改变了继承
脚本功能概述
- 提示框位置动态调整: 根据鼠标位置动态调整提示框的位置,避免提示框超出屏幕边界。
- 字体大小调整: 根据提示框内文本的长度动态调整字体大小,以适配长文本。
方法 1: AdjustPosition()
-
功能:
动态调整提示框位置,避免提示框超出屏幕边界。 - 关键逻辑:
mousePosition.x > xLimit
:
如果鼠标靠近屏幕右侧,提示框会向左偏移(-xOffset
);否则向右偏移(+xOffset
)。mousePosition.y > yLimit
:
如果鼠标靠近屏幕顶部,提示框会向下偏移(-yOffset
);否则向上偏移(+yOffset
)。transform.position
:
更新提示框的位置为鼠标位置加偏移量的坐标。
方法 2: AdjustFontSize(TextMeshProUGUI _text)
- 功能:
根据文本长度动态调整字体大小,防止长文本溢出。 - 关键逻辑:
- 如果文本长度大于12个字符,字体大小缩小至80%。
- 使用
TextMeshProUGUI
(Unity的高级文本组件)处理文本渲染,支持复杂的文本特效。
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;//2024.11.22
//szq
public class UI_ToolTip : MonoBehaviour
{[SerializeField] private float xLimit=960;[SerializeField] private float yLimit=540;[SerializeField] private float xOffset = 150;[SerializeField] private float yOffset = 150;public virtual void AdjustPosition(){Vector2 mousePosition = Input.mousePosition;float newXoffset = 0;float newYoffset = 0;if (mousePosition.x > xLimit)newXoffset = -xOffset;elsenewXoffset = xOffset;//鼠标靠近屏幕右侧时,提示框向左偏移;否则向右偏移if (mousePosition.y > yLimit)newYoffset = -yOffset;elsenewYoffset = yOffset;//鼠标靠近屏幕顶部时,提示框向下偏移;否则向上偏移transform.position = new Vector2(mousePosition.x + newXoffset, mousePosition.y + newYoffset);//更新提示框位置为鼠标位置偏移后的点}public void AdjustFontSize(TextMeshProUGUI _text)//根据文本长度调整字体大小{if(_text.text.Length > 12 )_text.fontSize = _text.fontSize * .8f;}
}
UI_SkillToolTip.cs
using TMPro;
using UnityEngine;public class UI_SkillToolTip : UI_ToolTip
{[SerializeField] private TextMeshProUGUI skillText;//显示技能描述的文本组件[SerializeField] private TextMeshProUGUI skillName;[SerializeField] private TextMeshProUGUI skillCost;[SerializeField] private float defaultNameFontSize;public void ShowToolTip(string _skillDescprtion, string _skillName,int _price)//显示工具提示{skillName.text = _skillName;skillText.text = _skillDescprtion;skillCost.text = "Cost: " + _price;AdjustPosition();AdjustFontSize(skillName);gameObject.SetActive(true);}public virtual void HideToolTip() //隐藏工具提示{skillName.fontSize = defaultNameFontSize;gameObject.SetActive(false);}
}
UI_ItemTooltip.cs
using TMPro;
using UnityEngine;//2024年11月14日
public class UI_ItemTooltip : UI_ToolTip
{[SerializeField] private TextMeshProUGUI itemNameText; // 名称显示文本[SerializeField] private TextMeshProUGUI itemTypeText; // 类型显示文本[SerializeField] private TextMeshProUGUI itemDescription;// 描述显示文本[SerializeField] private int defaultFontSize=32;public void ShowToolTIp(ItemData_Equipment item)//于显示工具提示,当玩家鼠标悬停在物品上时调用{if (item == null)return;itemNameText.text = item.itemName;itemTypeText.text = item.equipmentType.ToString();itemDescription.text = item.GetDescription();AdjustFontSize(itemNameText);AdjustPosition();gameObject.SetActive(true);}public void HideToolTip()//该方法用于隐藏工具提示,当玩家离开物品时调用{itemNameText.fontSize = defaultFontSize;gameObject.SetActive(false);}
}
UI_ItemSlot.cs
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;//物品数量的UI,放在ItemSlot上
// p105添加了Grad Layout Group,自动排列public class UI_ItemSlot : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler//实现接口
{[SerializeField] protected Image itemImage;// 物品图标[SerializeField] protected TextMeshProUGUI itemText;// 显示堆叠数量的文本protected UI ui;public InventoryItem item;// 当前物品槽中所显示的物品protected virtual void Start(){ui = GetComponentInParent<UI>();//获取UI组件}public void UpdataSlot(InventoryItem _newitem)//更新物品槽{item = _newitem;// 传入的新物品itemImage.color = Color.white;//获取了物品,itemslot透明变成白色,变得可见if (item != null)//列表中的物体不是空的{itemImage.sprite = item.data.icon;//获得图标if (item.stackSize > 1){itemText.text = item.stackSize.ToString();//显示堆叠数量}else{itemText.text = "";//不显示数量}}}public void CleanUpSlot()清空物品槽{item = null;// 将物品槽内物品设为空itemImage.sprite = null;// 清除物品图标itemImage.color = Color.clear;// 让物品槽变得不可见itemText.text = ""; // 清空堆叠数量的显示}public virtual void OnPointerDown(PointerEventData eventData)//拾取之后点击物品,改成virtual之后可以被子类重写{if (item == null)//如果物品槽为空return;if (Input.GetKey(KeyCode.LeftControl)){Inventory.instance.RemoveItem(item.data);//移除物品return;}if (item.data.itemType == ItemType.Equipment)// 如果点击的物品是装备类型Inventory.instance.EquipItem(item.data);//装备物品ui.itemToolTip.HideToolTip();//隐藏物品详情}public void OnPointerEnter(PointerEventData eventData){if(item == null)return;ui.itemToolTip.ShowToolTIp(item.data as ItemData_Equipment);//显示物品详情}public void OnPointerExit(PointerEventData eventData){if (item == null)return;ui.itemToolTip.HideToolTip();//隐藏物品详情}
}
ItemData_Equipment.cs
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;//2024年11月1日
public enum EquipmentType
{Weapon,Armor,Amulet,//护身符Flask//药水瓶
}[CreateAssetMenu(fileName = "New Item Data", menuName = "Data/Equipment")]//因为继承了ItemData,所以在资源管理器中创建新的Item,创建的物品自带这个脚本public class ItemData_Equipment : ItemData
{public EquipmentType equipmentType;[Header("独特效果")]public float itemCoolDown;//物品冷却时间public ItemEffect[] itemEffects;//可以添加物品的效果[Header("主属性")]public int strength;//力量,1点增加1攻击力和%1爆伤public int agility;//敏捷,1点增加1%闪避和%1暴击率public int intelligence;//智力,1点增加1法术强度和%1魔抗public int vitality;//活力,1点增加3生命值[Header("攻击属性")]public int damage;public int critChance;//暴击率public int critPower;//暴击伤害,默认%150[Header("防守属性")]public int maxHealth;public int armor;//护甲public int evasion;//闪避public int magicResistance;//魔抗[Header("魔法属性")]public int fireDamage;public int iceDamage;public int lightningDamage;[Header("制作需求")]//Craft requirementspublic List<InventoryItem> craftingMaterials;private int descriptionLength;public void Effect(Transform _enemyPositon)//执行物品效果{foreach (var item in itemEffects){item.ExcuteEffect(_enemyPositon);}}public void AddModifiers(){PlayerStats playerStats = PlayerManager.instance.player.GetComponent<PlayerStats>();playerStats.strength.AddModifier(strength);playerStats.agility.AddModifier(agility);playerStats.intelligence.AddModifier(intelligence);playerStats.vitality.AddModifier(vitality);playerStats.damage.AddModifier(damage);playerStats.critChance.AddModifier(critChance);playerStats.critPower.AddModifier(critPower);playerStats.maxHealth.AddModifier(maxHealth);playerStats.armor.AddModifier(armor);playerStats.evasion.AddModifier(evasion);playerStats.magicResistance.AddModifier(magicResistance);playerStats.fireDamage.AddModifier(fireDamage);playerStats.iceDamage.AddModifier(iceDamage);playerStats.lightingDamage.AddModifier(lightningDamage);}public void RemoveModifiers(){PlayerStats playerStats = PlayerManager.instance.player.GetComponent<PlayerStats>();playerStats.strength.RemoveModifier(strength);playerStats.agility.RemoveModifier(agility);playerStats.intelligence.RemoveModifier(intelligence);playerStats.vitality.RemoveModifier(vitality);playerStats.damage.RemoveModifier(damage);playerStats.critChance.RemoveModifier(critChance);playerStats.critPower.RemoveModifier(critPower);playerStats.maxHealth.RemoveModifier(maxHealth);playerStats.armor.RemoveModifier(armor);playerStats.evasion.RemoveModifier(evasion);playerStats.magicResistance.RemoveModifier(magicResistance);playerStats.fireDamage.RemoveModifier(fireDamage);playerStats.iceDamage.RemoveModifier(iceDamage);playerStats.lightingDamage.RemoveModifier(lightningDamage);}public override string GetDescription(){sb.Length = 0;//确保每次调用时是从头开始descriptionLength = 0;//重置描述的属性数量AddItemDescription(strength, "力量");AddItemDescription(agility, "敏捷");AddItemDescription(intelligence, "智力");AddItemDescription(vitality, "活力");AddItemDescription(damage, "伤害");AddItemDescription(critChance, "暴击率");AddItemDescription(critPower, "暴击伤害");AddItemDescription(maxHealth, "生命值");AddItemDescription(armor, "护甲");AddItemDescription(evasion, "闪避");AddItemDescription(magicResistance, "魔抗");AddItemDescription(fireDamage, "火焰伤害");AddItemDescription(iceDamage, "冰霜伤害");AddItemDescription(lightningDamage, "闪电伤害");for(int i = 0; i < itemEffects.Length; i++)//遍历物品效果{if (itemEffects[i].effectDescription.Length>0){sb.AppendLine();sb.Append("唯一:" + itemEffects[i].effectDescription);descriptionLength++;}}if (descriptionLength < 5)//确保最终返回的描述文本至少有 5 行内容{for (int i = 0; i < 5 - descriptionLength; i++){sb.AppendLine();sb.Append("");//空行}}return sb.ToString();//返回描述文本}private void AddItemDescription(int _value, string _name){if (_value != 0)//判断该属性没有实际值{if (sb.Length > 0)sb.AppendLine();//换行if (_value > 0)//sb.Append(_name+";"+_value);sb.Append("+ " + _value + " " + _name);//添加属性描述descriptionLength++;//每成功添加一个属性}}
}