基于 项目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.



















