基于 项目02《游戏-07-开发》Unity3D ,
本次任务做物品相互与详情的功能,
首先要做 点击相应,
接下来用接口实现点击相应事件,具体到代码中,我们找到需要响应鼠标事件的对象,
双击PackageCell.cs脚本修改代码:添加鼠标响应接口,
三个接口分别对鼠标的点击,进入,退出事件,
Alt + Enter 实现这三个接口,
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class PackageCell : MonoBehaviour,IPointerClickHandler,IPointerEnterHandler,IPointerExitHandler{
Transform UIIcon;
Transform UIHead;
Transform UINew;
Transform UISelect;
Transform UILevel;
Transform UIStars;
Transform UIDeleteSelect;
//动态数据
PackageLocalItem packageLocalData;
//静态数据
PackageTableItem packageTableItem;
//父物体也就是PackagePanel本身
PackagePanel uiParent;
void Awake(){
InitUIName();
}
void InitUIName(){
UIIcon = transform.Find("Top/Icon");
UIHead = transform.Find("Top/Head");
UINew = transform.Find("Top/New");
UILevel = transform.Find("Bottom/LevelText");
UIStars = transform.Find("Bottom/Stars");
UISelect = transform.Find("Select");
UIDeleteSelect = transform.Find("DeleteSelect");
UIDeleteSelect.gameObject.SetActive(false);
}
//刷新
public void Refresh(PackageLocalItem packageLocalData, PackagePanel uiParent){
//数据初始化
this.packageLocalData = packageLocalData;
this.packageTableItem = MainGame.Instance.GetPackageItemById(packageLocalData.id);
this.uiParent = uiParent;
//等级信息
UILevel.GetComponent<Text>().text = "Lv." + this.packageLocalData.level.ToString();
//是否是新获得?
UINew.gameObject.SetActive(this.packageLocalData.isNew);
Debug.Log("ImagePath: " + this.packageTableItem.imagePath);
//物品的图片
Texture2D t = (Texture2D)Resources.Load(this.packageTableItem.imagePath);
if (t != null){
Sprite temp = Sprite.Create(t, new Rect(0, 0, t.width, t.height), new Vector2(0, 0));
// 继续处理 Sprite 对象
UIIcon.GetComponent<Image>().sprite = temp;
}
else{
// 处理纹理加载失败的情况
Debug.LogError("Failed to load texture.");
}
//刷新星级
RefreshStars();
}
//刷新星级
public void RefreshStars(){
for (int i = 0; i < UIStars.childCount; i++){
Transform star = UIStars.GetChild(i);
if (this.packageTableItem.star > i)
star.gameObject.SetActive(true);
else
star.gameObject.SetActive(false);
}
}
public void OnPointerClick(PointerEventData eventData){
Debug.Log($"OnPointerClick {eventData.ToString()}");
}
public void OnPointerEnter(PointerEventData eventData){
Debug.Log($"OnPointerEnter {eventData.ToString()}");
}
public void OnPointerExit(PointerEventData eventData){
Debug.Log($"OnPointerExit {eventData.ToString()}");
}
}
回到unity编辑器中,
运行项目当我们鼠标悬停在武器Icon上就会有输出显示,
下一步是处理点击事件具体响应逻辑,
当鼠标点击物品时,右侧的详情界面会根据物品的信息进行刷新,
DetailPanel是PackagePanel下的子物体,也是我们要处理的对象,我们要对DetailPanel详情界面进行更新,
所以我们在Scripts脚本文件夹中添加一个脚本PackageDetail.cs用来更新详情界面DetailPanel对象,
然后将PackageDetail.cs脚本绑定在DetailPanel对象身上,
类似于上集的PackageCell逻辑,我们可以把DetailPanel也当作一个独立的对象进行处理,
双击PackagDetail.cs脚本修改代码:
using UnityEngine;
using UnityEngine.UI;
public class PackageDetail : MonoBehaviour{
Transform UIStars;
Transform UIDescription;
Transform UIIcon;
Transform UITitle;
Transform UILevelText;
Transform UISkillDescription;
PackageLocalItem packageLocalData;
PackageTableItem packageTableItem;
PackagePanel uiParent;
void Awake(){
InitUIName();
Test();
}
void Test() {
Refresh(MainGame.Instance.GetPackageLocalData()[1], null);
}
void InitUIName(){
UIStars = transform.Find("Center/Stars");
UIDescription = transform.Find("Center/Description");
UIIcon = transform.Find("Center/Icon");
UITitle = transform.Find("Top/Title");
UILevelText = transform.Find("Bottom/LevelPnl/LevelText");
UISkillDescription = transform.Find("Bottom/Description");
}
public void Refresh(PackageLocalItem packageLocalData, PackagePanel uiParent) {
//初始化:动态数据,静态数据,父物品逻辑
this.packageLocalData = packageLocalData;
this.packageTableItem = MainGame.Instance.GetPackageItemById(packageLocalData.id);
this.uiParent = uiParent;
//等级
UILevelText.GetComponent<Text>().text = string.Format($"Lv.{this.packageLocalData.level.ToString()}");
//简短描述
UIDescription.GetComponent<Text>().text = this.packageTableItem.description;
//详细描述
UISkillDescription.GetComponent<Text>().text = this.packageTableItem.skillDescription;
//物品名称
UITitle.GetComponent<Text>().name = this.packageTableItem.name;
//图片加载
Texture2D t = (Texture2D)Resources.Load(this.packageTableItem.imagePath);
Sprite temp = Sprite.Create(t, new Rect(0, 0, t.width, t.height), new Vector2(0, 0));
UIIcon.GetComponent<Image>().sprite = temp;
//星级处理
RefreshStars();
}
public void RefreshStars(){
for (int i = 0; i < UIStars.childCount; i++) {
Transform star = UIStars.GetChild(i);
if(this.packageTableItem.star > i)
star.gameObject.SetActive(true);
else
star.gameObject.SetActive(false);
}
}
}
回到unity编辑器中,运行项目可见详情页面被替换成
测试方法的第二张图片,
下一步要做的事情是当点击某个物品时,详情界面会根据鼠标点击的物品进行展示,
打开PackagePanel.cs脚本修改代码: 这是背包的主题逻辑部分
当前选中的物品总要被记录,把记录的地方放在PackagePanel中,
using UnityEngine;
using UnityEngine.UI;
public class PackagePanel : BasePanel{
Transform UIMenu;
Transform UIMenuWeapon;
Transform UIMenuFood;
Transform UITabName;
Transform UICloseBtn;
Transform UICenter;
Transform UIScrollView;
Transform UIDetailPanel;
Transform UILeftBtn;
Transform UIRightBtn;
Transform UIDeletePanel;
Transform UIDeleteBackBtn;
Transform UIDeleteInfoText;
Transform UIDeleteConfirmBtn;
Transform UIBottomMenus;
Transform UIDeleteBtn;
Transform UIDetailBtn;
//添加
public GameObject PackageUIItemPrefab;
//添加 表示当前选中的物品时哪一个uid
string _chooseUid;
public string ChooseUid {
get { return _chooseUid; }
set {
_chooseUid = value;
RefreshDetail();
}
}
void RefreshDetail() {
//找到uid对应的动态数据
PackageLocalItem localItem = MainGame.Instance.GetPackageLocalItemByUId(ChooseUid);
//刷新详情界面
UIDetailPanel.GetComponent<PackageDetail>().Refresh(localItem, this);
}
override protected void Awake(){
base.Awake();
InitUI();
}
//添加1
void Start(){
RefreshUI();
}
//添加1
void RefreshUI(){
RefreshScroll();
}
//添加1
void RefreshScroll(){
//清理滚动容器中原本的物品
RectTransform scrollContent = UIScrollView.GetComponent<ScrollRect>().content;
for (int i = 0; i < scrollContent.childCount; i++)
Destroy(scrollContent.GetChild(i).gameObject);
//获取本地数据的方法拿到自己身上背包数据 并且根据背包数据初始化滚动容器
foreach (PackageLocalItem localData in MainGame.Instance.GetSortPackageLocalData()){
Transform PackageUIItem = Instantiate(PackageUIItemPrefab.transform, scrollContent) as Transform;
PackageCell packageCell = PackageUIItem.GetComponent<PackageCell>();
//添加2
packageCell.Refresh(localData, this);
}
}
void InitUI(){
InitUIName();
InitClick();
}
void InitUIName(){
UIMenu = transform.Find("TopCenter/Menu");
UIMenuWeapon = transform.Find("TopCenter/Menus/Weapon");
UIMenuFood = transform.Find("TopCenter/Menus/Food");
UITabName = transform.Find("LeftTop/TabName");
UICloseBtn = transform.Find("RightTop/Close");
UICenter = transform.Find("Center");
UIScrollView = transform.Find("Center/Scroll View");
UIDetailPanel = transform.Find("Center/DetailPanel");
UILeftBtn = transform.Find("Left/Button");
UIRightBtn = transform.Find("Right/Button");
UIDeletePanel = transform.Find("Bottom/DeletePanel");
UIDeleteBackBtn = transform.Find("Bottom/DeletePanel/Back");
UIDeleteInfoText = transform.Find("Bottom/DeletePanel/InfoText");
UIDeleteConfirmBtn = transform.Find("Bottom/DeletePanel/ConfirmBtn");
UIBottomMenus = transform.Find("Bottom/BottomMenus");
UIDeleteBtn = transform.Find("Bottom/BottomMenus/DeleteBtn");
UIDetailBtn = transform.Find("Bottom/BottomMenus/DetailBtn");
UIDeletePanel.gameObject.SetActive(false);
UIBottomMenus.gameObject.SetActive(true);
}
void InitClick(){
UIMenuWeapon.GetComponent<Button>().onClick.AddListener(OnClickWeapon);
UIMenuFood.GetComponent<Button>().onClick.AddListener(OnClickFood);
UICloseBtn.GetComponent<Button>().onClick.AddListener(OnClickClose);
UILeftBtn.GetComponent<Button>().onClick.AddListener(OnClickLeft);
UIRightBtn.GetComponent<Button>().onClick.AddListener(OnClickRight);
UIDeleteBackBtn.GetComponent<Button>().onClick.AddListener(OnDeleteBack);
UIDeleteConfirmBtn.GetComponent<Button>().onClick.AddListener(OnDeleteConfirm);
UIDeleteBtn.GetComponent<Button>().onClick.AddListener(OnDelete);
UIDetailBtn.GetComponent<Button>().onClick.AddListener(OnDetail);
}
void OnDetail(){
print(">>>>>>> OnDetail()");
}
void OnDelete(){
print(">>>>>>> OnDelete()");
}
void OnDeleteConfirm(){
print(">>>>>>> OnDeleteConfirm()");
}
void OnDeleteBack(){
print(">>>>>>> OnDeleteBack()");
}
void OnClickRight(){
print(">>>>>>> OnClickRight()");
}
void OnClickLeft(){
print(">>>>>>> OnClickLeft()");
}
void OnClickWeapon(){
print(">>>>>>> OnClickWeapon()");
}
void OnClickFood(){
print(">>>>>>> OnClickFood()");
}
void OnClickClose(){
ClosePanel();
}
}
因为物品的逻辑是写在PackageCell.cs脚本中,
那么找到PackageCell点击的回调方法,
也就是OnPointerClick()方法,
修改PackageCell.cs脚本:
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class PackageCell : MonoBehaviour,IPointerClickHandler,IPointerEnterHandler,IPointerExitHandler{
Transform UIIcon;
Transform UIHead;
Transform UINew;
Transform UISelect;
Transform UILevel;
Transform UIStars;
Transform UIDeleteSelect;
//动态数据
PackageLocalItem packageLocalData;
//静态数据
PackageTableItem packageTableItem;
//父物体也就是PackagePanel本身
PackagePanel uiParent;
void Awake(){
InitUIName();
}
void InitUIName(){
UIIcon = transform.Find("Top/Icon");
UIHead = transform.Find("Top/Head");
UINew = transform.Find("Top/New");
UILevel = transform.Find("Bottom/LevelText");
UIStars = transform.Find("Bottom/Stars");
UISelect = transform.Find("Select");
UIDeleteSelect = transform.Find("DeleteSelect");
UIDeleteSelect.gameObject.SetActive(false);
}
//刷新
public void Refresh(PackageLocalItem packageLocalData, PackagePanel uiParent){
//数据初始化
this.packageLocalData = packageLocalData;
this.packageTableItem = MainGame.Instance.GetPackageItemById(packageLocalData.id);
this.uiParent = uiParent;
//等级信息
UILevel.GetComponent<Text>().text = "Lv." + this.packageLocalData.level.ToString();
//是否是新获得?
UINew.gameObject.SetActive(this.packageLocalData.isNew);
Debug.Log("ImagePath: " + this.packageTableItem.imagePath);
//物品的图片
Texture2D t = (Texture2D)Resources.Load(this.packageTableItem.imagePath);
if (t != null){
Sprite temp = Sprite.Create(t, new Rect(0, 0, t.width, t.height), new Vector2(0, 0));
// 继续处理 Sprite 对象
UIIcon.GetComponent<Image>().sprite = temp;
}
else{
// 处理纹理加载失败的情况
Debug.LogError("Failed to load texture.");
}
//刷新星级
RefreshStars();
}
//刷新星级
public void RefreshStars(){
for (int i = 0; i < UIStars.childCount; i++){
Transform star = UIStars.GetChild(i);
if (this.packageTableItem.star > i)
star.gameObject.SetActive(true);
else
star.gameObject.SetActive(false);
}
}
public void OnPointerClick(PointerEventData eventData){
if (this.uiParent.ChooseUid == this.packageLocalData.uid)
return;
//根据点击设置最新的uid 进而刷新详情界面
this.uiParent.ChooseUid = this.packageLocalData.uid;
}
public void OnPointerEnter(PointerEventData eventData){
Debug.Log($"OnPointerEnter {eventData.ToString()}");
}
public void OnPointerExit(PointerEventData eventData){
Debug.Log($"OnPointerExit {eventData.ToString()}");
}
}
回到unity编辑器中运行项目,点开背包点击物品查看详情页面的更新,
已实现点击背包物品更换详情页面,
下一步实现UI动画点击效果动画,
首先在ACs动画控制器文件包中创建一个UI文件夹准备放UI动画,
在UI文件夹中创建两个PackageAC背包控制器,
其中PackageAC1代表鼠标掠过的动画控制器,PackageAC2代表鼠标选中的动画控制器,
在PackageItem预制体空间下创建两个空物体,
设置尺寸,
设置子物体Image为拉伸模式
重命名Image为Image1,并设置比例为1.1
再创建Image2,同样设置比例为1.2,拉伸模式
同样添加选中图片,
接下来在ACs的UI文件夹中创建动画Animation,命名为PackageSelectAni
在这个文件夹再创建两个动画,分别对应 鼠标进入物品 和 退出物品 的效果,
下一步绑定组件Animator,将PackageAC1拖拽给 选中对象,
打开PackageAC1动画控制器,将PackageSelectAni动画拖拽在动画控制器中,
创建一个空状态并连线,
然后添加Trigger类型的变量,
接着双击打开Animation这个窗口,
选中设置谁的动画,
同样添加Image2的color,
点击左上角的红点即可进入录制模式,点击播放修改两个image的d颜色为0,再次点击结束录制即可,
同样方法绑定鼠标点击对象组件Animator并拖拽PackageAC2,
双击PackageAC2进入动画控制器,并拖拽其余两个动画,
还是把默认条件设置为空状态,
然后创建两个转换变量In 和 Out,用来设置切换鼠标进入与鼠标退出,
对于MouseOverAni这个对象添加一个Image,并设置大小,拉伸模式
我们先将SelectAni隐藏,
还是添加一个color,
1.点击录制,
2.拖动动画线到中间,设置color d 为 0,
3.调试:
4.结束录制,
同样手法配置PackageMouseOut动画,
提醒:In的动画color透明度变化是 0 - 1 - 0,而Out的动画color透明度变化是 1 - 0,
Select的动画为 0.5 - 1-0.5 - 0,总之最后透明度均为0,
动画控制器设置完成,
下一步修改PackageCell.cs脚本:
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class PackageCell : MonoBehaviour,IPointerClickHandler,IPointerEnterHandler,IPointerExitHandler{
Transform UIIcon;
Transform UIHead;
Transform UINew;
Transform UISelect;
Transform UILevel;
Transform UIStars;
Transform UIDeleteSelect;
//添加
Transform UISelectAni;
Transform UIMouseOverAni;
//动态数据
PackageLocalItem packageLocalData;
//静态数据
PackageTableItem packageTableItem;
//父物体也就是PackagePanel本身
PackagePanel uiParent;
void Awake(){
InitUIName();
}
void InitUIName(){
UIIcon = transform.Find("Top/Icon");
UIHead = transform.Find("Top/Head");
UINew = transform.Find("Top/New");
UILevel = transform.Find("Bottom/LevelText");
UIStars = transform.Find("Bottom/Stars");
UISelect = transform.Find("Select");
UIDeleteSelect = transform.Find("DeleteSelect");
//添加
UIMouseOverAni = transform.Find("MouseOverAni");
UISelectAni = transform.Find("SelectAni");
UIDeleteSelect.gameObject.SetActive(false);
//添加
UIMouseOverAni.gameObject.SetActive(false);
UISelectAni.gameObject.SetActive(false);
}
//刷新
public void Refresh(PackageLocalItem packageLocalData, PackagePanel uiParent){
//数据初始化
this.packageLocalData = packageLocalData;
this.packageTableItem = MainGame.Instance.GetPackageItemById(packageLocalData.id);
this.uiParent = uiParent;
//等级信息
UILevel.GetComponent<Text>().text = "Lv." + this.packageLocalData.level.ToString();
//是否是新获得?
UINew.gameObject.SetActive(this.packageLocalData.isNew);
Debug.Log("ImagePath: " + this.packageTableItem.imagePath);
//物品的图片
Texture2D t = (Texture2D)Resources.Load(this.packageTableItem.imagePath);
if (t != null){
Sprite temp = Sprite.Create(t, new Rect(0, 0, t.width, t.height), new Vector2(0, 0));
// 继续处理 Sprite 对象
UIIcon.GetComponent<Image>().sprite = temp;
}
else{
// 处理纹理加载失败的情况
Debug.LogError("Failed to load texture.");
}
//刷新星级
RefreshStars();
}
//刷新星级
public void RefreshStars(){
for (int i = 0; i < UIStars.childCount; i++){
Transform star = UIStars.GetChild(i);
if (this.packageTableItem.star > i)
star.gameObject.SetActive(true);
else
star.gameObject.SetActive(false);
}
}
public void OnPointerClick(PointerEventData eventData){
if (this.uiParent.ChooseUid == this.packageLocalData.uid)
return;
//根据点击设置最新的uid 进而刷新详情界面
this.uiParent.ChooseUid = this.packageLocalData.uid;
UISelectAni.gameObject.SetActive(true);
UISelectAni.GetComponent<Animator>().SetTrigger("In");
}
public void OnPointerEnter(PointerEventData eventData){
UIMouseOverAni.gameObject.SetActive(true);
UIMouseOverAni.GetComponent<Animator>().SetTrigger("In");
}
public void OnPointerExit(PointerEventData eventData){
Debug.Log($"OnPointerExit {eventData.ToString()}");
}
}
最后这个操作可以确保我们的子物品不会影响我们点触事件的判断,
运行项目即可实现,
鼠标滑动效果,
鼠标点击效果,
点击右上角×退出键即可退出面板,
End.