zoukankan      html  css  js  c++  java
  • Unity3D 学习手记

      注:本实例开发环境为Unity 5.3.4,开发语言为C#

      这周的任务是用UGUI实现NGUI的一个效果:

      http://www.tasharen.com/ngui/exampleX.html

    实现效果:

    1. 格子是什么?其实是个按钮!

    项目分级:

    顶层:InventoryMenu空对象,下属InventoryMenuCam - UI摄像机,MenuManager - 管理类,ICanvas - UI画布

    ICanvas下属:角色3D模型(从商店下载),Window - 控制Equip和Backpack面板

    Equip: 下属三个格子,分别对应头部,上身和足部三种类别的盔甲

    Backpack:下属九个格子,可以放任意类别的盔甲

    Grid:实际上是个按钮 - OnClick()上挂载UIManager.mouseClickHandler(GameObject),对象上还挂在了一个Grid的MonoBehavior脚本,里面只有一个公共值 - GridNumber

    设置Grid Number对应自身的格子编号。

    设置OnClick传递自身对象为参数。

    (对每个格子进行如上操作 - 我觉得会有更好的解决办法?)

    那这时每当按到这个格子的时候就会调用一次UIManager的mouseClickHandler()方法,这是会将自身对象作为一个参数发送给UIManager。

    mouseClickHandler()里为不同情况下的点击处理做了定义:

    public void mouseClickHandler(GameObject gridObject) {
            int gridNumber = gridObject.GetComponent<Grid>().gridNumber;//0 - 2 is the equipment grid number
            if (gridNumber >= 0 && gridNumber <= 2) {
                if (im.isEquipmentGridOcupied (gridNumber)) {
                    if (mouseInventType == 0) {
                        int equipmentType = im.getEquipmentInventory (gridNumber);
                        toggleImageFromGridToMouse (gridObject);
                        mouseInventType = equipmentType;
                    }
                } else {
                    //Grid 0 for head gear, 1 for chest gear, 2 for foot gear
                    if (mouseInventType == 1 && gridNumber == 0) {
                        im.putInventoryonEqupment (gridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    } else if (mouseInventType == 2 && gridNumber == 1) {
                        im.putInventoryonEqupment (gridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    } else if (mouseInventType == 3 && gridNumber == 2) {
                        im.putInventoryonEqupment (gridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    }
    
                }
            }
            //3 - 11 is the backpack grid number
            else if (gridNumber >= 3 && gridNumber <= 11) {
                int backPackGridNumber = gridNumber - 3;
                Debug.Log (backPackGridNumber + im.isBackpackGridOccupied(backPackGridNumber).ToString() + mouseInventType);
                if (im.isBackpackGridOccupied (backPackGridNumber)) {
                    if (mouseInventType == 0) {
                        int inventoryType = im.getBackPackInventory (backPackGridNumber);
                        toggleImageFromGridToMouse (gridObject);
                        mouseInventType = inventoryType;
                    } 
                } else {
                    if (mouseInventType != 0) {
                        im.putBackPackInventory (backPackGridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    }
                }
            }
        }

    2. 界面逻辑和游戏逻辑的分离:UIManager和InventoryManager

    你已经注意到了,界面里面我没有对Grid细分为EquipmentGrid和BackpackGrid。这是考虑到从界面的角度来看,他们其实是同一种对象。

    我另外实现了单实例对象InventoryManager,专门负责物品逻辑的管理:

    如果要从外部来启动这个菜单,应该由UIManager来发起初始化界面,再调用InventoryManager的Init方法初始化逻辑。这里为了简便在UIManager中把初始化的物品列表设为公共。

    一些初期设定:

     

    3. 杂项

    界面随鼠标移动的实现方法,别忘了在人像上也挂载喔!

    using UnityEngine;
    
    public class TiltWindow : MonoBehaviour
    {
        public Vector2 range = new Vector2(5f, 3f);
    
        Transform mTrans;
        Quaternion mStart;
        Vector2 mRot = Vector2.zero;
    
        void Start ()
        {
            mTrans = transform;
            mStart = mTrans.localRotation;
        }
    
        void Update ()
        {
            Vector3 pos = Input.mousePosition;
    
            float halfWidth = Screen.width * 0.5f;
            float halfHeight = Screen.height * 0.5f;
            float x = Mathf.Clamp((pos.x - halfWidth) / halfWidth, -1f, 1f);
            float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f);
            mRot = Vector2.Lerp(mRot, new Vector2(x, y), Time.deltaTime * 5f);
    
            mTrans.localRotation = mStart * Quaternion.Euler(-mRot.y * range.y, -mRot.x * range.x, 0f);
        }
    }

    图像随鼠标移动的方法:

    新建一个对象,ItenOnMouse,里面有个Image组件。让这个组件无时无刻跟着鼠标走就行了。需要的时候enable,不需要的时候disable。

    当然,由于在Canvas里用的是RectTransform,我们也必须用RectTransform,LocalPoint相关的方法来处理:

        void Update() {
    
            Vector2 mousePosWorld;
    
            RectTransformUtility.ScreenPointToLocalPointInRectangle (ICanvas.transform as RectTransform, Input.mousePosition, UICamera.GetComponent<Camera>(), out mousePosWorld);
    
            ImageOnMouseObj.transform.position = ICanvas.transform.TransformPoint (mousePosWorld);
    
        }

    怎么防止ImageOnMouseObj挡着鼠标按按钮?

    将Raycast Target的勾去掉。

    按钮的状态:

    为按钮加载动画控制器Button

    这些Trigger,对应着控制器中的Trigger名字

    控制器设计:

    Highlighted 上的动作:

    HoverEnter,挂在在Highlighted

    HoverExit,挂载在Normal

    Loop Time的勾都去掉

    Button的Navigation属性勾去掉

    完整代码:

    UIManager:

    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;
    
    public class UIManager : MonoBehaviour {
    
        public int[] equipmentList = {1, 2, 3};
        public int[] backPackInvnetoryList = { 1, 2, 3, 0, 0, 0, 0, 0, 0 };
    
        public GameObject UICamera;
        public GameObject ICanvas;
    
        InventoryManager im = InventoryManager.getInstance();
    
        //following Invent Type convension
        int mouseInventType = 0;
        public GameObject ImageOnMouseObj;
        Image ImageOnMouse;
    
        public Sprite defaultSprite;
    
        void Start() {
    
            ImageOnMouse = ImageOnMouseObj.GetComponent<Image>();
            ImageOnMouseObj.SetActive (false);
    
            im.init (equipmentList, backPackInvnetoryList);
        }
    
        void Update() {
    
            Vector2 mousePosWorld;
    
            RectTransformUtility.ScreenPointToLocalPointInRectangle (ICanvas.transform as RectTransform, Input.mousePosition, UICamera.GetComponent<Camera>(), out mousePosWorld);
    
            ImageOnMouseObj.transform.position = ICanvas.transform.TransformPoint (mousePosWorld);
    
        }
    
        public void mouseClickHandler(GameObject gridObject) {
            int gridNumber = gridObject.GetComponent<Grid>().gridNumber;
    
            //0 - 2 is the equipment grid number
            if (gridNumber >= 0 && gridNumber <= 2) {
                if (im.isEquipmentGridOcupied (gridNumber)) {
                    if (mouseInventType == 0) {
                        int equipmentType = im.getEquipmentInventory (gridNumber);
                        toggleImageFromGridToMouse (gridObject);
                        mouseInventType = equipmentType;
                    }
                } else {
                    //Grid 0 for head gear, 1 for chest gear, 2 for foot gear
                    if (mouseInventType == 1 && gridNumber == 0) {
                        im.putInventoryonEqupment (gridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    } else if (mouseInventType == 2 && gridNumber == 1) {
                        im.putInventoryonEqupment (gridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    } else if (mouseInventType == 3 && gridNumber == 2) {
                        im.putInventoryonEqupment (gridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    }
    
                }
            }
            //3 - 11 is the backpack grid number
            else if (gridNumber >= 3 && gridNumber <= 11) {
                int backPackGridNumber = gridNumber - 3;
                Debug.Log (backPackGridNumber + im.isBackpackGridOccupied(backPackGridNumber).ToString() + mouseInventType);
                if (im.isBackpackGridOccupied (backPackGridNumber)) {
                    if (mouseInventType == 0) {
                        int inventoryType = im.getBackPackInventory (backPackGridNumber);
                        toggleImageFromGridToMouse (gridObject);
                        mouseInventType = inventoryType;
                    } 
                } else {
                    if (mouseInventType != 0) {
                        im.putBackPackInventory (backPackGridNumber, mouseInventType);
                        toggleImageFromMouseToGrid (gridObject);
                        mouseInventType = 0;
                    }
                }
            }
        }
    
    
        void toggleImageFromGridToMouse(GameObject grid){
            Debug.Log (grid.name);
            Image ri_g = grid.GetComponent<Image>();
            ImageOnMouse.sprite = ri_g.sprite;
            ri_g.sprite = defaultSprite;
    
            Color color = ri_g.color;
            color.a = 0.78f;
            ri_g.color = color;
    
            Debug.Log (ri_g.color);
    
            ImageOnMouseObj.SetActive (true);
    
        }
    
        void toggleImageFromMouseToGrid(GameObject grid){
            ImageOnMouseObj.SetActive (false);
            Image ri_g = grid.GetComponent<Image>();
    
            Color color = ri_g.color;
            color.a = 1f;
            ri_g.color = color;
    
            ri_g.sprite = ImageOnMouse.sprite;
            ImageOnMouse.sprite = defaultSprite;
    
        }
            
    }

    InventoryManager:

    using UnityEngine;
    using System.Collections;
    
    public class InventoryManager : System.Object {
    
        private static InventoryManager _instance;
    
        public static InventoryManager getInstance() {
            if (_instance == null) {
                _instance = new InventoryManager ();
            }
            return _instance;
        }
    
        int[] equipment;
        int[] backpack;
    
        public void init(int[] equipped, int[] backPackInventory){
            equipment = equipped;
            backpack = backPackInventory;
        }
    
        public bool isEquipmentGridOcupied (int equipmentGridNumber){
            if (equipmentGridNumber <= 2 && equipmentGridNumber >= 0) {
                if (equipment [equipmentGridNumber] != 0) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    
        public bool isBackpackGridOccupied (int inventoryGridNumber){
            //print_item ();
            if (backpack [inventoryGridNumber] != 0) {
                return true;
            } else {
                return false;
            }
        }
    
        public int getBackPackInventory(int backPackGridNumber){
            if (backPackGridNumber <= 8 && backPackGridNumber >= 0) {
                int inventoryType = backpack [backPackGridNumber];
                backpack [backPackGridNumber] = 0;
                //print_item ();
                return inventoryType;
            } else {
                return -1;
            }
        }
    
        public bool putBackPackInventory(int backPackGridNumber, int putInventoryType){
            if (backPackGridNumber <= 8 && backPackGridNumber >= 0) {
                backpack [backPackGridNumber] = putInventoryType;
                //print_item ();
                return true;
            } else {
                return false;
            }
        }
    
        public int getEquipmentInventory(int equipmentGridNumber){
            if (equipmentGridNumber <= 2 && equipmentGridNumber >= 0) {
                int equipmentInventoryType = equipment [equipmentGridNumber];
                equipment [equipmentGridNumber] = 0;
                //print_item ();
                return equipmentInventoryType;
            } else {
                return -1;
            }
        }
    
        public bool putInventoryonEqupment(int equipmentGridNumber, int inventoryType){
            //print_item ();
            if (equipmentGridNumber <= 2 && equipmentGridNumber >= 0) {
                equipment [equipmentGridNumber] = inventoryType;
                //print_item ();
                return true;
            } else {
                return false;
            }
        }
    
        void print_item(){
            Debug.Log ("Equipement: ");
            for (int i = 0; i < 3; i++) {
                Debug.Log (equipment[i] + " ");
            }
            Debug.Log ("Backpack: ");
            for (int i = 0; i < 9; i++) {
                Debug.Log (backpack[i] + " ");
            }
        }
    }

    Grid:

    using UnityEngine;
    using System.Collections;
    
    public class Grid : MonoBehaviour {
    
        public int gridNumber = 0;
    
    }

    TiltWindow:

    using UnityEngine;
    
    public class TiltWindow : MonoBehaviour
    {
        public Vector2 range = new Vector2(5f, 3f);
    
        Transform mTrans;
        Quaternion mStart;
        Vector2 mRot = Vector2.zero;
    
        void Start ()
        {
            mTrans = transform;
            mStart = mTrans.localRotation;
        }
    
        void Update ()
        {
            Vector3 pos = Input.mousePosition;
    
            float halfWidth = Screen.width * 0.5f;
            float halfHeight = Screen.height * 0.5f;
            float x = Mathf.Clamp((pos.x - halfWidth) / halfWidth, -1f, 1f);
            float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f);
            mRot = Vector2.Lerp(mRot, new Vector2(x, y), Time.deltaTime * 5f);
    
            mTrans.localRotation = mStart * Quaternion.Euler(-mRot.y * range.y, -mRot.x * range.x, 0f);
        }
    }
  • 相关阅读:
    [原]Linux ssh远程连接断开问题处理办法
    【网摘】CURL常用命令
    【树莓派】在树莓派中进行截图
    【树莓派】树莓派移动网络连接(配置4G网卡)
    【树莓派】基于TinyProxy搭建HTTP代理服务器
    【树莓派】制作树莓派所使用的img镜像(二)
    【树莓派】制作树莓派所使用的img镜像(一)
    macaca运行报错之chrome-driver问题处理,关闭 Chrome 的自动更新
    Git使用
    Longest Consecutive Sequence leetcode java
  • 原文地址:https://www.cnblogs.com/wangsta/p/5516470.html
Copyright © 2011-2022 走看看