黑暗之光游戏制作

            黑暗之光RPG游戏制作

嗯,这里我将给大家介绍一个很经典的RPG类型游戏的制作,嗯,这里说一下这个是个半成品文档,,不包括敌人制作和升级系统的

1.    场景的铺设,灯光的添加和鼠标的设置

首先,我们将地图拖拽的到当前游戏场景并且保存定位start

然后我们添加一个directLight作为场景的光照,这里光照由大家挑选自己喜欢的即可

bulid&setting里有个projectSetting,在这里我们将鼠标的图标设置为GUI里的mouse_normal,这样在游戏里图标就会切换成合适的图标了

2.    添加天空盒子和水资源

这里用的是unity自带的天空盒子和水资源

1, 我们导入水资源和天空盒子

扫描二维码关注公众号,回复: 3768258 查看本文章

2, 将水面平铺整个场景,再通过调整高度让它覆盖河流

3, MainCamera里加入天空盒子并且导入刚刚引进的素材即可

3.    摄像机的缓慢移动和雾的添加

摄像机的移动很简单,设置好位置以后用transform.translate即可控制移动,当然我这里还使用了一个Mathf.Lerp的方法控制,大家选择比较合适的使用,这里雾的添加只需要在editrender Setting下的fog勾选上即可

using UnityEngine;

using System.Collections;

 

public class MovieCamera : MonoBehaviour {

    public float moveSpeed = 10;

    public float EndZ = -20;

   

    // Use this for initialization

    void Start () {

       

    }

   

    // Update is called once per frame

    void Update () {

        //float newZ= Mathf.Lerp(transform.position.z,EndZ, Time.deltaTime * moveSpeed);

        //transform.position = newVector3(transform.position.x,transform.position.y,newZ);

        if(transform.position.z<EndZ)

        transform.Translate(Vector3.forward * moveSpeed* Time.deltaTime);

    }

}

4.  给初始界面添加个UGUI的切换动画

这里我们希望开始游戏时候能做到由白色屏幕渐渐演变进游戏,因此,我们要加上这样的控制

1, 导入NGUititle两个素材包

2, 点开NGUi下的PrefabToolBar并且将其中的backGround拖到视图层

3, 切换到移动视角,添加simpleTexture将其设置为WhiteScreen并且点击snap还原图片大小

4, 保证图片能够覆盖整个游戏屏幕,添加上AlPhaTween设置延时一秒逐渐从10

5, 这样,我们渐变的效果就实现了

 

5.  UI界面的一些基础设置

因为UI搭建大多就是图片拼凑,所以这里我讲几个要点

1.    我们在NGUIopen一个Atlas并且将所需title素材拖进去做成一个图集,这样方便调用

2.    我们拖拽PressAnyKey时候可以将动画显示方式设置为Ping-Pone,这样就可以实现闪烁的效果

3.    我们需要NewGameLoadGame同时显示,因此我们在NGUI下创建一个widget并且将它们都设置为widget的子物体,添加上BoxColliderUIButton控制点击和图标的变化

6.    添加事件,当点击屏幕时候弹出newGameLoadGame

我们在pressAnyKey下添加这样的脚本

这里逻辑两步

1我们获取到buttonContiner,加上一个Bool值来判断是否点击,input中有个事件

控制当点击时候就会触发的输出

2.我们新建一个方法,通过setActive的方法可以设置显示,当然这里也要将bool值设置成true防止事件反复执行

 

using UnityEngine;

using System.Collections;

 

public class PressAnyKey : MonoBehaviour {

    private bool isAnyKeyDown = false;

    private GameObject buttonContainer;

    // Use this for initialization

    void Start () {

        buttonContainer = this.transform.parent.Find("Container").gameObject;

    }

   

    // Update is called once per frame

    void Update () {

        if (isAnyKeyDown == false)

        {

            if (Input.anyKeyDown)

            {

 

                ShowButton();

 

            }

        }

    }

    void ShowButton()

    {

        buttonContainer.SetActive(true);

        this.gameObject.SetActive(false);

        isAnyKeyDown = true;

 

 

 

    }

}

7.  添加背景声音和按键声音1

MainCamera上添加auidoSource组件,在newGameloadGmae上添加UIPlay并且指定声音,即可添加上游戏声效了.

8.  创建角色选择场景

这里就单纯是一些Ui的堆砌,没什么好说的,因为角色选择和游戏场景是一样的,因此我们只要复制上个场景即可

9.    实现角色的选择功能

将两个角色剑士和魔法师做成prefab,然后我们用脚本来控制它们的生成

1.    创建一个GameObject命名为CharacterController,并且将它的位置设置到召唤盘上

2.    书写脚本

我们用prefabs数组来存放模型,Controller来进行控制

1.    我们在strat里进行初始化并且将prefabs里的模型赋值给控制器

2.    创建一个方法来控制模型的显示和隐藏

3.    书写两个方法来控制按钮点击后的事件,当前显示的模型由characterIndex决定

4.    将物体赋值给两个按钮的点击,然后选择相对应的方法

3.   using UnityEngine;

4.   using System.Collections;

5.    

6.   public class CharacterCreation : MonoBehaviour {

7.       public GameObject[] characterPrefabs;

8.       private GameObject[] characterController;

9.       private int characterIndex = 0;

10.     private int length = 0;

11.     // Use this for initialization

12.     void Start()

13.     {

14.         length = characterPrefabs.Length;

15.         characterController = new GameObject[length];

16.         for (int i = 0; i < length; i++)

17.         {

18.             characterController[i] = GameObject.Instantiate(characterPrefabs[i],transform.position, transform.rotation) as GameObject;//在当前未知

19.  

20.         }

21.         CharacterShow();

22.  

23.     }

24. // Update is called once per frame

25.     void CharacterShow()

26.     {

27.         characterController[characterIndex].SetActive(true);

28.         for (int i = 0; i < length; i++)

29.         {

30.             if (i != characterIndex)

31.             {

32.                 characterController[i].SetActive(false);

33.             }

34.  

35.         }

36.     }

37.  

38.     public void NextChooseButton()

39.     {

40.         characterIndex++;

41.         characterIndex %= length;//这样可以自我实现循环

42.         CharacterShow();

43.  

44.  

45.     }

46.    public  void PreChooseButton()

47.     {

48.         characterIndex--;

49.         if (characterIndex == -1)

50.         {

51.             characterIndex = length - 1;

52.         }

53.         CharacterShow();

54.  

55.  

56.     }

57.  

58. }

10. 处理名字和选择角色的存储

这里就是获取到主角设置的信息和输入的主角名,并且进行存储,方便以后调用

这里获取到UI组件,然后通过setIntsetString来存储角色信息

public UIInput nameInput;

    public void OnOkButtonClick()

    {

        PlayerPrefs.SetInt("characterInt", characterIndex);//存储选择德角色

        PlayerPrefs.SetString("nameInput", nameInput.value);//存储角色德名字

 

 

 

    }

11.  制作鼠标点击后的特效

这里判断鼠标点击的位置我们采用的是射线检测的方法

   首先是camera下有一个点击目标位置会发射一条射线的方法

1.    我们保存这条射线

2.    RayCastHIt来保存碰撞的信息

3.    boolIsCollider来判断是否碰撞到地面,用的是Physics下的RayCast方法

4.    我们创建一个方法来实例化特效,实例化的位置就是鼠标点击的位置

using UnityEngine;

using System.Collections;

 

public class CharacterDir : MonoBehaviour {

    //这个是控制实例化点击出现点击特效的

    public GameObject EffectPref;

    // Use this for initialization

    void Start () {

   

    }

   

    // Update is called once per frame

    void Update () {

        //我们检测用到的是碰撞检测

        if (Input.GetMouseButtonDown(0))

        {

            //当鼠标左键按下时

            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//这里获取到鼠标点击位置的射线

            RaycastHit hitinfo;//保存的是碰撞信息

            bool isCollider = Physics.Raycast(ray, out hitinfo);//用来判断是否碰撞

            if (isCollider && hitinfo.collider.tag == Tags.ground)

            {

                ShowEffect(hitinfo.point);//在射线碰撞到的位置实例化

            }

        }

      

    }

    void ShowEffect(Vector3 showPosition)

    {

        showPosition = new Vector3(showPosition.x, showPosition.y + 0.1f, showPosition.z);

        GameObject.Instantiate(EffectPref, showPosition, Quaternion.identity);//实例化目标

 

    }

}

12.  控制主角的朝向

这里我们首先要判断主角是否移动,我们判断移动的方法是鼠标是否点下来设置主角朝向的truefalse,

1.    我们将射线碰撞的位置设置给targetPos

2.    我们用transform.lookAt改变主角朝向,但是我们不改变y

3.    在点击和isMoving两种方法里调用playerLookAt方法

using UnityEngine;

using System.Collections;

 

public class CharacterDir : MonoBehaviour {

    //这个是控制实例化点击出现点击特效的

    public GameObject EffectPref;

    private bool isMoving=false;

    private Vector3 targetPos=Vector3.zero;

    // Use this for initialization

    void Start () {

   

    }

   

    // Update is called once per frame

    void Update () {

        //我们检测用到的是碰撞检测

        if (Input.GetMouseButtonDown(0))

        {

            //当鼠标左键按下时

            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//这里获取到鼠标点击位置的射线

            RaycastHit hitInfo;//保存的是碰撞信息

            bool isCollider = Physics.Raycast(ray, out hitInfo);//用来判断是否碰撞

            if (isCollider && hitInfo.collider.tag == Tags.ground)

            {

 

                ShowEffect(hitInfo.point);//在射线碰撞到的位置实例化

                isMoving = true;

                PlayerDir(hitInfo.point);

 

            }

 

 

        }

        if (Input.GetMouseButtonUp(0))

        {

            isMoving = false;

 

        }

        if (isMoving)

        {

            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//这里获取到鼠标点击位置的射线

            RaycastHit hitInfo;//保存的是碰撞信息

            bool isCollider = Physics.Raycast(ray, out hitInfo);//用来判断是否碰撞

            if (isCollider && hitInfo.collider.tag == Tags.ground)

            {

                isMoving = true;

 

            }

            PlayerDir(hitInfo.point);

 

 

        }

      

    }

    void ShowEffect(Vector3 showPosition)

    {

        showPosition = new Vector3(showPosition.x, showPosition.y + 0.1f, showPosition.z);

        GameObject.Instantiate(EffectPref, showPosition, Quaternion.identity);//实例化目标

 

    }

 

    //控制主角的朝向

    void PlayerDir(Vector3 hitPos)

    {

        targetPos = hitPos;

        targetPos = new Vector3(targetPos.x, transform.position.y, targetPos.z);//我们控制的是xz的变化,y不变

        transform.LookAt(targetPos);

    }

   

}

13.  控制主角的移动

这里我们希望主角移动到鼠标的目标位置,因此我们新建一个脚本叫playerMove来管理主角移动

1.    我们要获取playerDir里的tarPos并且给魔法师添加CharacterController来控制移动

2.    我们计算两者间的距离,通过CharacterController下的SimpleMove来控制移动

using UnityEngine;

using System.Collections;

 

public class CharacterMove : MonoBehaviour {

    private CharacterDir charDir;

    public float speed = 1;

    private CharacterController controller;

    // Use this for initialization

    void Start () {

        charDir = this.GetComponent<CharacterDir>();

        controller = this.GetComponent<CharacterController>();

    }

   

    // Update is called once per frame

    void Update () {

 

        float distance = Vector3.Distance(charDir.targetPos, transform.position);

        if (distance >0.1f)

        {

           controller.SimpleMove(transform.forward * speed);

        }

 

    }

}

14.  控制移动动画的播放

我们移动的时候肯定不能是平移的,因此我们要用动画来控制角色的移动

1.    我们新建一个脚本叫PlayerAnimation

2.    我们修改PlayerMove,给它添加一个动画状态,在不同状态时候调用不同动画

3.    Animation下有一个crossFade的方法可以通过获取动画的名字来播放动画,这里我们获取到playerMove下的状态,在不同状态下播放相应的动画即可实现效果

public enum PlayerState

{

    Idle,

    Move

}

void Update () {

 

        float distance = Vector3.Distance(charDir.targetPos, transform.position);

        if (distance >0.1f)

        {

           controller.SimpleMove(transform.forward * speed);

            state = PlayerState.Move;

        }

        else

        {

            state = PlayerState.Idle;

        }

 

    }

}

4.  修改Animation脚本

5.  using UnityEngine;

6.  using System.Collections;

7.   

8.  public class CharacterAnimation : MonoBehaviour {

9.      private CharacterMove charMove;

10. // Use this for initialization

11. void Start () {

12.         charMove = this.GetComponent<CharacterMove>();

13. }

14.

15. // Update is called once per frame

16. void LateUpdate () {

17.  

18.         if (charMove.state == PlayerState.Move)

19.         {

20.             PlayAnim("Run");

21.         }else if (charMove.state == PlayerState.Idle)

22.         {

23.             PlayAnim("Idle");

24.         }

25.  

26.  

27.  

28.  

29. }

30.     void PlayAnim(string animName)

31.     {

32.         animation.CrossFade(animName);

33.  

34.     }

35. }

15.  完善主角的移动

1之前的移动有一个bug,就是当我们控制移动的时候,会导致鼠标停止点击的时候,人物还会持续往那个方向移动,这是因为playerMove中当我们修改方向时,动画的播放判断会一直因为大于01而一直播放移动动画,因此我们在脚本里加入isMoving,状态改变时分为trueflase

3.    我们将isMoving设置给dir,当判断鼠标松开且不再移动时,我们会判断此时是否正在走,如果在走,就会实时更新朝向

16.  实现摄像机的跟随

1.    我们新建一个followPlayer的脚本,挂在摄像机下

2.    我们持有一下playerposition

3.    我们让摄像机看向主角并且计算一下当前摄像机和主角的位置偏差

4.    update里实时保持两者的offset

5.  using UnityEngine;

6.  using System.Collections;

7.   

8.  public class camerMove : MonoBehaviour {

9.      private Transform player;

10.     // Use this for initialization

11.     //我们通过计算偏差来实现照相机的跟随

12.     private Vector3 offset;

13. void Start () {

14.         player = GameObject.FindGameObjectWithTag(Tags.player).transform;

15.         transform.LookAt(player.position);

16.         offset = transform.position -player.position;

17. }

18.

19. // Update is called once per frame

20. void Update () {

21.         transform.position = offset +player.position;//保持偏移的大小

22. }

23. }

17.  鼠标滚轮实现镜头的拉近和拉远

  这里我们用input,getAxis即可获得鼠标是否按下滚轮,这里返回是个-11的值,这样我们就可以通过返回值决定镜头与主角间的距离,然后再把距离重新赋值给两者偏移即可

18.   void ScrollView()

19.     {

20.         //Input.GetAxis("Mouse ScrollWheel")获得是一个负值到正值的变换,我们获取到滚轮的变化,在当前偏移上做出改变即可实现镜头拉远和拉近

21.          distance = offset.magnitude;    

22.             distance += Input.GetAxis("MouseScrollWheel") *scrollSpeed;

23.            offset = offset.normalized *distance;

24.         

25.  

26.      }

18.鼠标右键控制镜头的旋转

我们判断鼠标右键是否按下来决定是否旋转,而旋转用的是Transfom.RotateAround这个方法,我们获取到鼠标在x轴的偏移,向左为负,向右为正数,这样来决定我们旋转的角度是正还是负,然后我们设置完成后要重新设置主角朝向和镜头朝向一致

    void RotateCamera()

    {

        //用鼠标右键控制视野旋转

        if (Input.GetMouseButtonDown(1)){

            isRotating = true;

 

        }

        if (Input.GetMouseButtonUp(1))

        {

            isRotating = false;

        }

        if (isRotating)

        {

           transform.RotateAround(player.position, Vector3.up, rotateSpeed*Input.GetAxis("Mouse X"));

 

 

        }

        offset = transform.position -player.position;//这里当摄像机发生旋转时,偏移也会发生改变,我们要重新设置偏移

 

    }

}

19.控制视野的上下旋转并且控制它的范围

1.我们要摄像机的上下旋转需要摄像机围绕自身的右方进行上下旋转,获得的是鼠标在y轴的移动

transform.RotateAround(player.position,transform.right, rotateSpeed * Input.GetAxis("Mouse Y")

2.我们要控制旋转的范围,每次旋转前保存当前位置,如果x轴上的偏移超出我们的设置范围,我们则将位置设置成最后一次能正常移动范围的位置

void RotateCamera()

    {

        //用鼠标右键控制视野旋转

        if (Input.GetMouseButtonDown(1)){

            isRotating = true;

 

        }

        if (Input.GetMouseButtonUp(1))

        {

            isRotating = false;

        }

        if (isRotating)

        {

            Vector3 originalPos = transform.position;

            Quaternion originalRotation = transform.rotation;

           transform.RotateAround(player.position, player.up, rotateSpeed*Input.GetAxis("Mouse X"));

           transform.RotateAround(player.position, transform.right, rotateSpeed * Input.GetAxis("Mouse Y"));//围绕角色的右边进行旋转

            float x = transform.eulerAngles.x;

            if (x < 10 || x > 80)

            {

                transform.position =originalPos;

                transform.rotation =originalRotation;

            }

          

 

        }

        offset = transform.position -player.position;//这里当摄像机发生旋转时,偏移也会发生改变,我们要重新设置偏移

 

    }

}

20,设计任务的界面

导入menu素材,添加上boxColliderTweenPosion,设置好出现的动画,即可完成任务栏的创建,这里主要是一些UI的堆砌,没啥讲的,就是有一点,当我们移动时候,不想在任务出现时接着移动,在判断鼠标左键点击移动的条件上再加一个判断UICamera.hoverObject==null

21.对话框的显示和隐藏

这里讲一下逻辑

1.    获取到TweenPosition这个动画组件

2.    书写控制Quest显示的方法,就是将quest设置为true并且播放显示动画

3.    OnMouseOver中进行判断和调用显示方法

4.    添加关闭按钮,添加点击事件closeQuest,实现方法就是动画倒放,使其移出屏幕

using UnityEngine;

using System.Collections;

 

public class BarNpc : MonoBehaviour {

    public TweenPosition tween;

    void OnMouseOver()//当鼠标在这个collider上时,就会触发这个方法

    {

        if (Input.GetMouseButtonDown(0))

        {

            setQuestAwake();

        }

 

 

    }

    void setQuestAwake()

    {

        tween.gameObject.SetActive(true);

        tween.PlayForward();

 

    }

    //处理点击事件

    void HideQuest()

    {

        tween.PlayReverse();//动画倒放

    }

   public void OnCloseClick()

    {

        HideQuest();

    }

}

22.处理任务面板以及各个按钮的点击

这里就是要处理各个按钮之间的逻辑,我们希望达到的效果有

1.  点击accept,显示的是接手后的任务信息

2.  点击cancel关闭任务面板

3.  点击accept显示ok按钮,处理提交任务

因此我们

1先封装两个方法,一个是显示任务信息,一个是显示任务进度信息

2.两个方法分别设置各个按钮的状态,因此我们要引用各个按钮,并且还要获得label组件来修改它的text

3.我么书写各个按钮的点击处理事件,然后注册到相应的按钮点击反应上,逻辑如上

4.然后我们定义一个Bool值,通过bool值判断此时应该执行哪个面板

using UnityEngine;

using System.Collections;

 

public class BarNpc : MonoBehaviour {

    public TweenPosition tween;

    public bool isTask = false;

    public int killCount = 0;

    public UILabel desLabel;

    public GameObject acceptBtn;

    public GameObject cancelBtn;

    public GameObject okBtn;

    void OnMouseOver()//当鼠标在这个collider上时,就会触发这个方法

    {

        if (Input.GetMouseButtonDown(0))

        {

           

            if (isTask)

            {

                ShowTaskProgess();

            }

            else

            {

                ShowTaskDes();

            }

            setQuestAwake();

        }

    }

    void setQuestAwake()

    {

        tween.gameObject.SetActive(true);

        tween.PlayForward();

 

    }

    void ShowTaskDes()

    {

        desLabel.text = "任务\n杀死10只野狼\n\n奖励:\n获得1000金币";

        acceptBtn.SetActive(true);

        cancelBtn.SetActive(true);

        okBtn.SetActive(false);

        isTask = true;//表示接受了任务

    }

    void ShowTaskProgess()

    {

        desLabel.text = "任务\n你已经杀死了" + killCount + "/10只野狼\n\n奖励:\n获得1000金币";

        acceptBtn.SetActive(false);

        cancelBtn.SetActive(false);

        okBtn.SetActive(true);

    }

    //处理点击事件

    void HideQuest()

    {

        tween.PlayReverse();//动画倒放

    }

   public void OnCloseClick()

    {

        HideQuest();

    }

    public void OnAcceptClick()

    {

        ShowTaskProgess();

    }

    public void OnCancelClick()

    {

        HideQuest();

        isTask = false;

    }

    public void OnOkClick()

    {

        HideQuest();

       

    }

}

23.处理一下接受任务系统和人物状态得更新

这里我们希望实现的效果是点击ok成功提交任务并且人物状态栏得金币数量更新

因此我们要这么做

1.    characterState里创建一个方法来处理获得金币事件

2.  using UnityEngine;

3.  using System.Collections;

4.   

5.  public class CharacterState1 : MonoBehaviour {

6.   

7.      public int coin = 100;

8.      public int hp = 100;

9.      public int mp = 100;

10.     public int grade = 1;

11.     public void GetCoin(int count)

12.     {

13.         coin += count;

14.     }

15. }

2.BarNpc那里处理点击事件,获取到PlayerState后,同步进行更新

  public void OnOkClick()

    {

        if (killCount >= 10)

        {

            state.GetCoin(1000);

            killCount = 0;

            ShowTaskDes();

        }

        else

        {

            HideQuest();

        }

        

       

}

24.处理点击人物后鼠标指针的变化

这里我们要写两个脚本,第一个是一个共有类,我叫它CursorMannager,是管理各种鼠标指针的,一个是Npc脚本,处理各种Npc相关事件的

1.    CursorSetting中我们是通过Cursor.setCursor,获得到点击的位置,设置鼠标的状态和对于的图片,创造了两个方法来处理不同情况,并且我们将这个方法封装成单例模式

 

using UnityEngine;

using System.Collections;

 

public class CurosorSetting : MonoBehaviour {

    public static CurosorSetting _instance;

    public Texture2D cursor_Attack;

    public Texture2D cursor_LockTarget;

    public Texture2D cursorNormal;

    public Texture2D Npc_talk;

    public Texture2D Pick_up;

    private Vector2 hotSpot = Vector2.zero;

    private CursorMode mode = CursorMode.Auto;//鼠标自适应选择软件或者硬件

    void Start()

    {

        _instance = this;

    }

    public void SetCursorNormal()

    {

        Cursor.SetCursor(cursorNormal, hotSpot, mode);

 

    }

    public void SetCursorNpc()

    {

        Cursor.SetCursor(Npc_talk, hotSpot, mode);

    }

   

}

2.  我们创建一个Npc脚本并且让BarNpc继承自Npc

其中创建了两个方法处理鼠标进入和离开时后鼠标指针的状态

3.  using UnityEngine;

4.  using System.Collections;

5.   

6.  public class Npc : MonoBehaviour {

7.      void OnMouseEnter()

8.      {

9.   

10.         CurosorSetting._instance.SetCursorNpc();

11.  

12.     }

13.     void OnMouseExit()

14.     {

15.         CurosorSetting._instance.SetCursorNormal();

16.     }

17.  

18. }

25. 设置功能面板

 

这就是Ui的一些摆放,我们create InvisableWidegt来放置这些按钮,这里注意的就是把Ancor设置成向右对其,使其与屏幕自适应

26,创建物品清单

我们在Asserts下创建一个文本

我们先创建一个药品的清单

27,创建物品信息的管理类

我们将在这个类里解析我们的文本信息,并且将它们存放到字典里

1.    我们定义一个枚举类型来存放物品类型

2.    我们定义一个叫做ObjectsInfo的来存放物品的相关信息

3.    我们定义一个ReadInfo来解析我们的文本信息,首先我们用text.Spilt(“\n”)来分隔语句,通过换行符,然后将这些语句存入数组

4.    然后我们定义一个新的数组,通过逗号进行分隔存入数组,再用对应类型的数据进行保存

5.    我们得到的分隔数据都通过id依次存储到字典里,这样可以方便查找,用到了ObjectsinfoDic.add

6.    我们可以在Awake里测试我们得到了几组数据,输出结果应该是3

using UnityEngine;

using System.Collections;

usingSystem.Collections.Generic;

 

public class ObjectInfo : MonoBehaviour {

    public static ObjectInfo _instance;

    public TextAsset objectInfoText;

    private Dictionary<int, Objectsinfo> objectInfoDic = new Dictionary<int,Objectsinfo>();

    // Use this for initialization

    void Awake()

    {

        _instance = this;

        ReadInfo();

        print(objectInfoDic.Keys.Count);

    }

    public Objectsinfo GetObjcetsinfoById(int id)

    {

        Objectsinfo info=null;

        objectInfoDic.TryGetValue(id, out info);

        return info;

    }

     void ReadInfo()

    {

        string text = objectInfoText.text;

        string[] strArray=text.Split('\n'); //通过换行符进行拆分

        foreach(string str in strArray)

        {

            string[] proArray = str.Split(',');//根据逗号拆分各个属性存在数组里

            Objectsinfo info = new Objectsinfo();

            int id = int.Parse(proArray[0]);

          

            string name = proArray[1];

            string icon_name = proArray[2];

            string str_type = proArray[3];

            ObjectType type = ObjectType.Drug;

           

            switch (str_type)

            {

                case "Drug":

                    type = ObjectType.Drug;

                    break;

                case "Equip":

                    type = ObjectType.Equip;

                    break;

                case "Mat":

                    type = ObjectType.Mat;

                    break;

            }

            info.id = id; info.name = name;info.icon_name = icon_name; info.type = type;

            if (type == ObjectType.Drug)

            {

                int hp = int.Parse(proArray[4]);

                int mp = int.Parse(proArray[5]);

                int price_sell = int.Parse(proArray[6]);

                int price_buy = int.Parse(proArray[7]);

                info.hp = hp;

                info.mp = mp;

                info.price_buy = price_buy;

                info.price_sell = price_sell;

            }

            objectInfoDic.Add(id, info);//添加到字典,idkey,可以很方便查找到

        }

 

    }

}

public enum ObjectType

{

    Drug,

    Equip,

    Mat

}

public class Objectsinfo

{

    public int id;

    public string name;

    public string icon_name;//这个存储的是图集中的名称

    public ObjectType type;

    public int hp;

    public int mp;

    public int price_sell;

    public int price_buy;

 

}

26.  创建背包的UI并且管理背包下的物品

1.    我们给背包添加TweenPosition来控制它的显示和隐藏

2.    我们给背包下的所有方格添加了InvertoryGrid并且创建一个列表存储方便管理,然后我们在视图下对列表进行赋值

3.    我们定义一个Uiabel来控制金币数量的变化

using UnityEngine;

using System.Collections;

usingSystem.Collections.Generic;

 

public class Invertory : MonoBehaviour {

    private TweenPosition tween;

    public static Invertory _instance;

    public List<InvertoryItemGrid> itemGridList = new List<InvertoryItemGrid>();

    public UILabel coinLabel;

    // Use this for initialization

    void Start () {

        tween = this.GetComponent<TweenPosition>();

        _instance = this;

    }

   

    // Update is called once per frame

    void Update () {

   

    }

    public void PlayTween()

    {

        tween.PlayForward();

    }

    public void HideTween()

    {

        tween.PlayReverse();

    }

}

27.  实现背包的拾取功能

这里我们做的是模拟背包拾取的功能,也就是按下x后物品会被拾取

1.首先我们在uodate里更改,也就是按下x,会调用Getid方法,随机实例化一个物品出来

void Update () {

        if (Input.GetKeyDown(KeyCode.X))

        {

 

            GetId(Random.Range(1001, 1004));//随机数不包括最大值,我们取到10011003

        }

}

2.创建GetId方法

1.  我们定义了一个list,这里存放了InvertoryItemGrid,这里存放了所有的方格,我们的墓地就是遍历所有的方格并且判断它当前的状态

2.  我们遍历后如果存在该物品的话,就将grid设置为该temp,并且根据Grid是否为空判断该物品是否存在,如果不为空的话,我们将num+1就行了,这里调用了一下ItemGrid下的NumPlus方法

3.  如果不存在该物品,我们就要将物品设置到新的方格, temp.id=0的时候,这时候我们将temp设置给grid,然后再跳出循环。然后我们判断当grid!=null,我们就要通过ItemGrid里的setid来更新id,调用NGUI下的方法来实例化物品并且将物品位置设置到正中间

public List<InvertoryItemGrid> itemGridList = new List<InvertoryItemGrid>();

   public void GetId(int id)

    {

        //第一步是查找在所有的物品中,是否存在该物品

        //第二步,如果存在,就num+1

        //如果不存在,就查找空的方格,并且将新创建的Invertory_item放到该空格中

        InvertoryItemGrid grid = null;

        //遍历所有的网格,判断网格中是否有物品

        foreach(InvertoryItemGrid temp in itemGridList)

        {

            if (temp.id == id)

            {

                grid = temp;

                break;

            }

        }

        if (grid != null)

        {

            grid.PlusNum();

        }

        else

        {

            foreach(InvertoryItemGrid temp in itemGridList)

            {

                if (temp.id == 0)

                {

                    grid = temp;

                    break;

                }

            }

            if (grid != null)

            {

                GameObject itemGo=NGUITools.AddChild(grid.gameObject, invertoryItem);

                itemGo.transform.localPosition= Vector3.zero;//物品设置到格子的正中间

                itemGo.GetComponent<UISprite>().depth = 8;

                grid.SetId(id);

            }

 

        }

}

3.这里附上InvertoryItemGrid脚本,这个是管理网格的脚本

using UnityEngine;

using System.Collections;

 

public class InvertoryItemGrid : UIDragDropContainer {

    private UILabel numLabel;

    public int id = 0;

    private int num = 0;

   private Objectsinfo info = null;

    void Start()

    {

        numLabel = this.GetComponentInChildren<UILabel>();

    }

    //外部调用该方法来更新显示

    public void SetId(int id,int num=1)

    {

        this.id = id;

        info = ObjectInfo._instance.GetObjcetsinfoById(id);

        InvertoryItem item = this.GetComponentInChildren<InvertoryItem>();

        item.SetIcon_name(info.icon_name);

        numLabel.enabled = true;//这里更新不能使用gamobject,setActive,因为当我们取消勾选的时候,getCompoentInChildren方法根本不会被调用

        this.num = num;

        numLabel.text = num.ToString();

    }

    //这个方法是用来情况物品栏信息的,比如你使用了该物品,就会重置信息

    public void clearInfo()

    {

        id = 0;

        info = null;

        num = 0;

        numLabel.enabled = false;

    }

    public void PlusNum(int num=1)

    {

        this.num += num;

        numLabel.text = this.num.ToString();//在文本中显示需要将数字转换成字符串

    }

}

28. 控制物品的拖拽功能

在这里我们要处理的拖拽有三种情况

1.  拖拽到自身的方格

2.  拖拽到空的方格

3.  将两个方格内的物品进行交换位置

所以逻辑如下:

1.  拖拽到自身方格,我们什么都不需要做

2.  拖拽到空的方格,我们要获取到原先位置的信息,再获取到新位置的的方格,通过setId方法将老方格的信息设置到新方格里,再清空老的方格

3.  将两个方格的物品进行交换位置,这里需要先获取到两个方格的物品信息,再通过setId进行设置,实现交换

4.  最后,所有的操作都需要重置位置信息

29. using UnityEngine;

30. using System.Collections;

31.  

32. public class InvertoryItem : UIDragDropItem {

33.     private UISprite sprite;

34.     void Awake()

35.     {

36.         sprite = this.GetComponent<UISprite>();

37.     }

38.     protected override void OnDragDropRelease(GameObject surface)

39.     {

40.         base.OnDragDropRelease(surface);//这里是鼠标发出一个射线检测,当碰撞到第一个collider时候,就将surface设置成为那个碰撞到的物体

41.         //在这里我们处理鼠标拖拽物品可能遇到的三种情况

42.     

43.         if (surface!= null)

44.         {

45.             if (surface.tag == Tags.Invertory_itemGrid)

46.             {

47.                 //当我们将物品拖拽到一个空的物品栏下面时,有两种情况,第一时拖放到自己的格子里,第二是放在一个新的格子下

48.                 if (surface == this.transform.parent.gameObject)

49.                 {

50.                     

51.                     

52.                 }

53.                 else

54.                 {                  

55.                     InvertoryItemGrid oldParent = this.transform.parent.GetComponent<InvertoryItemGrid>();

56.                     this.transform.parent = surface.transform;//修改目标位置为当前触碰到的位置

57.                     

58.                     //然后我们要将物品信息也移动,重新设置

59.                     InvertoryItemGrid newParent = surface.GetComponent<InvertoryItemGrid>();

60.                     newParent.SetId(oldParent.id,oldParent.num);

61.                     oldParent.clearInfo();//清空老的物品栏

62.                    

63.                 }

64.                 

65.             }

66.             else if (surface.tag == Tags.Invertory_item)

67.             {

68.                 //这是移动到其他物品上时候的处理,交换两者的位置

69.                 InvertoryItemGrid grid1 = this.transform.parent.GetComponent<InvertoryItemGrid>();

70.                 InvertoryItemGrid grid2 = surface.transform.parent.GetComponent<InvertoryItemGrid>();

71.                 int id1 = grid1.id;int num1 = grid1.num;

72.                 grid1.SetId(grid2.id,grid2.num);

73.                 grid2.SetId(id1, num1);

74.  

75.  

76.             }      

77.         }

78.         ResetPos();

79.     }

80.     void ResetPos()

81.     {

82.         transform.localPosition = Vector3.zero;

83.     }

84.     public void SetId(int id)

85.     {

86.         Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(id);

87.         //这是是要根据id显示物品

88.         sprite.spriteName = info.icon_name;//更新物品

89.     }

90.     public void SetIcon_name(string icon_name)

91.     {

92.         sprite.spriteName = icon_name;

93.     }

94. }

29.实现背包的显示和隐藏

我们在背包里通过bool值控制显示和隐藏,然后统一写一个方法在Onfunction里调用里的OnButtonClick方法里调用,这样,就可以实现背包的显示和隐藏了

    public bool isShow = false;

    void PlayTween()

    {

        isShow = true;

      

        tween.PlayForward();

    }

     void HideTween()

    {

        isShow = false;

        tween.PlayReverse();

    }

   

    public void OnTransformState()

    {

        if (isShow == false)

        {

            PlayTween();

        }

        else if(isShow==true)

        {

            HideTween();

        }

 

 

    }

}

30.实现物品信息的显示

1.  首先我们创建一个sprite叫做ItemDes,并且在它下面创建一个laber,调整好它的大小并且让文字居左对齐

2.  我们给这个sprite添加个脚本叫做InvertoryDes

  脚本实现两个功能1.从物品信息类那里获取到物品的相关信息,根据对应的物品

3.   show方法里我们调用根据获得物品信息方法,依据相应的类型显示对应的文本

4.  我们使用UI摄像机里有个将局部坐标转换成世界坐标的方法设置好显示信息在物品上

5.  我们添加一个计时器,来控制当鼠标不在物品上面时使物品信息隐藏,我们每次调用show方法,就将计时器设置为0.1,然后离开时就会进行时间减少,当时间到0以下时,就会取消显示

 

 

6.  using UnityEngine;

7.  using System.Collections;

8.   

9.  public class InvertoryDes : MonoBehaviour {

10.  

11.     public static InvertoryDes _instance;

12.     private UILabel label;

13.     private float timmer = 0;

14.     void Awake()

15.     {

16.         _instance = this;

17.         label = this.GetComponentInChildren<UILabel>();

18.         this.gameObject.SetActive(false);

19.  

20.     }

21.     void Update()

22.     {

23.         //每次调用show方法后,离开时就进行计算

24.         timmer-= Time.deltaTime;

25.         if (timmer <= 0)

26.         {

27.             this.gameObject.SetActive(false);

28.         }

29.     }

30.     //在这里我,我们要根据我们获得的物品id来获得物品描述信息

31.     public void Show(int id)

32.     {

33.         this.gameObject.SetActive(true);

34.         timmer = 0.1f;

35.        transform.position=UICamera.currentCamera.ScreenToWorldPoint(Input.mousePosition);

36.         Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(id);

37.         string des = "";

38.         switch (info.type)

39.         {

40.             case ObjectType.Drug:

41.                 des = GetDrugdes(info);

42.                 break;

43.         }

44.         label.text = des;

45.  

46.     }

47.     //我们通过这个方法来获得物品信息

48.     string GetDrugdes(Objectsinfo info)

49.     {

50.         string str = "";

51.         str+= "名称:" + info.name + "\n";

52.         str += "+Hp" + info.hp + "\n";

53.         str += "+MP" + info.mp + "\n";

54.         str += "sellMoney" + info.price_sell + "\n";

55.         return str;

56.  

57.     }

58.        

59. }

60.  

然后我们修改InvertoryItem

首先我们在prefab下添加这样两个组件,来判断鼠标是否移动到上面

    public void OnHoverEnter()

    {

        isHover = true;

       

       

    }

    public void OnHoverExit()

    {

        isHover = false;

       

    }

添加好方法后,我们在这里根据Id调用对应的物品信息显示

   void Update()

    {

        if (isHover)

        {

            InvertoryDes._instance.Show(id);

 

        }

    }

31.创建用户信息面板

拼接好UI后,我们添加一个脚本保存主角信息

using UnityEngine;

using System.Collections;

 

public class CharacterState1 : MonoBehaviour {

 

    public int coin = 100;

    public int hp = 100;

    public int mp = 100;

    public int grade = 1;

    public int arrack = 20;

    public int attack_plus = 0;

    public int def = 0;

    public int def_plus = 0;

    public int speed = 20;

    public int speed_plus = 0;

    public int point_remain = 0;

    public void GetCoin(int count)

    {

        coin += count;

    }

}

32.实现状态面板的更新显示

1.  我们要获取到组件的信息

2.  我们定义一个UpdateState方法来获取玩家状态信息然后更新显示

3.  我们给三个按钮注册三个方法来控制加点

4.  using UnityEngine;

using System.Collections;

 

public class Status : MonoBehaviour {

    private TweenPosition tween;

    private bool isShow = false;

    public static Status _instance;

    public UILabel attackLabel;

    public UILabel defLabel;

    public UILabel speedLabel;

    public UILabel remainLabel;

    public UILabel summaryLabel;

    public GameObject attackBtn;

    public GameObject defBtn;

    public GameObject speedBtn;

    private CharacterState1 ps;

    // Use this for initialization

    void Start () {

        _instance = this;

        tween = this.GetComponent<TweenPosition>();

        ps = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<CharacterState1>();

    }

   

    // Update is called once per frame

    void Update () {

   

    }

    public void TransformState()

    {

        if (isShow == false)

        {

            tween.PlayForward();

            UpdateState();

            isShow = true;

        }

        else

        {

            tween.PlayReverse();

            isShow = false;

 

 

 

 

        }

    }

    public void UpdateState()

    {

        attackLabel.text=ps.attack+"+"+ps.attack_plus;

        defLabel.text = ps.def+"+"+ps.def_plus;

        speedLabel.text = ps.speed + "+" + ps.speed_plus;

        remainLabel.text =ps.point_remain.ToString();

        summaryLabel.text = "伤害:" + (ps.attack +ps.attack_plus) +

            "  " + "防御:  " + (ps.def + ps.def_plus) +

            "  " + "速度:  " + (ps.speed + ps.speed_plus);

        if (ps.point_remain > 0)

        {

            attackBtn.gameObject.SetActive(true);

            defBtn.gameObject.SetActive(true);

           speedBtn.gameObject.SetActive(true);

        }

        else

        {

            attackBtn.gameObject.SetActive(false);

            defBtn.gameObject.SetActive(false);

            speedBtn.gameObject.SetActive(false);

        }

 

    }

    public void OnAttackBtnClick()

    {

        bool success = ps.GetPoint();

        if (success)

        {

            ps.attack_plus++;

            UpdateState();//更新显示

        }

    }

    public void OnDefBtnClick()

    {

        bool success = ps.GetPoint();

        if (success)

        {

            ps.def_plus++;

            UpdateState();//更新显示

        }

    }

    public void OnSpeedBtnClick()

    {

        bool success = ps.GetPoint();

        if (success)

        {

            ps.speed_plus++;

            UpdateState();//更新显示

        }

    }

 

}

 

2.修改玩家状态信息,定义一个GetPoint方法,来判断是否可以进行点数加减

    public bool GetPoint(int point = 1)

    {

        //判断是否加可以加点数

        point_remain -= point;

        if (point_remain > 0)

        {

            return true;

        }

        else

        {

            return false;

        }

 

 

}

33.更新药品商店的购买功能

这里我们要实现点击各个按钮实现购买的功能

1. 我们要注册各个按钮的点击事件,并且获取到物品列表中的一些UI组件

2. 当我们点击各个buy按钮时候,会显示出下面的购买框进行购买,这里我们进行对比看玩家金额是否可以购买对应的数量,所以首先我们要计算出你购买的count和物品价格,这里要获得ObjectsInfo中的物品信息,然后在Invertory里我们写一个判断是否可以购买的bool方法

   public bool buyPower(int count)

    {

        //判断是否可以进行交易行为

        if (coinCount > count)

        {

            coinCount-= count;

            coinLabel.text =coinCount.ToString();//更新显示

            return true;

        }

        else

        {

            return false;

        } 

    }

3.然后我们根据Invertory中的SetId方法,设置点击后更新背包内的物品信息

using UnityEngine;

using System.Collections;

 

public class ShopDrug : MonoBehaviour {

    public static ShopDrug _instance;

    private TweenPosition tween;

    public bool isShow = false;

    private UIInput numberInput;

    private GameObject numberDialog;

    public int Buy_id = 0;

   

    // Use this for initialization

    void Awake () {

        tween = this.GetComponent<TweenPosition>();

        _instance = this;

        numberInput = transform.Find("NumberDialog/NumberInput").GetComponent<UIInput>();

        numberDialog = this.transform.Find("NumberDialog").gameObject;

        numberDialog.SetActive(false);

       

    }

    public void TransformState()

    {

        if (isShow == false)

        {

            tween.PlayForward();

            isShow = true;

        }

        else if(isShow==true)

        {

            tween.PlayReverse();

            isShow = false;

        }

 

    }

    public void OnCloseClick()

    {

        TransformState();

    }

    public void OnButton1001Click()

    {

        Buy(1001);

    }

    public void OnButton1002Click()

    {

        Buy(1002);

    }

    public void OnButton1003Click()

    {

        Buy(1003);

    }

    public void OnButtonOkClick()

    {

        int count = int.Parse(numberInput.value);

        Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(Buy_id);//获取物品信息

        int price_total = info.price_buy * count;

        bool success = Invertory._instance.buyPower(price_total);

        if (success)

        {

            if(count>0)

            Invertory._instance.GetId(Buy_id, count);

        }

    }

    public void Buy(int id)

    {

        Buy_id = id;

        ShowDialog();

    }

    public void ShowDialog()

    {

        numberDialog.SetActive(true);

        numberInput.value = "0";

    }

}

36.创建装备栏并且添加物品信息的读取

首先我们在物品信息类里添加装备信息

public enum DressType

{

    Headgear,

    Armor,

    Right_Hand,

    Left_Hand,

    Shoe,

    Accessory

 

}

public enum ApplicationType

{

    Magician,

    Swordman,

    Common

}

public enum ObjectType

{

    Drug,

    Equip,

    Mat

}

public class Objectsinfo

{

    public int id;

    public string name;

    public string icon_name;//这个存储的是图集中的名称

    public ObjectType type;

    public int hp;

    public int mp;

    public int price_sell;

    public int price_buy;

 

    public int attack;

    public int def;

    public int speed;

    public DressType dressType;

    public ApplicationType applicationType;

3. 修改物品信息文件

4. Equipment里取到各种物品信息

public static EquipmentUI _instance;

    private TweenPosition tween;

    private bool isShow = false;

    private GameObject headGear;

    private GameObject armor;

    private GameObject left_Hand;

    private GameObject right_Hand;

    private GameObject shoe;

    private GameObject accessory;

    void Awake()

    {

        _instance = this;

        tween = this.GetComponent<TweenPosition>();

        headGear = transform.Find("Headgear").gameObject;

        armor = transform.Find("Aromr").gameObject;

        left_Hand = transform.Find("Left_Hand").gameObject;

        right_Hand = transform.Find("Right_Hand").gameObject;

        shoe = transform.Find("Shoe").gameObject;

        accessory = transform.Find("Accessory").gameObject;

    }  

5. 在物品信息类里实现读取

else if (type == ObjectType.Equip)

            {

                int attack = int.Parse(proArray[4]);

                int def = int.Parse(proArray[5]);

                int speed = int.Parse(proArray[6]);

                int sell_price = int.Parse(proArray[9]);

                int buy_price = int.Parse(proArray[10]);

                string str_dresstype = proArray[7];

                switch (str_dresstype)

                {

                    case "Headgear":

                        info.dressType = DressType.Headgear;

                        break;

                    case "Armor":

                        info.dressType = DressType.Armor;

                        break;

                    case "Right_Hand":

                        info.dressType = DressType.Right_Hand;

                        break;

                    case "Left_Hand":

                        info.dressType = DressType.Left_Hand;

                        break;

                    case "Shoe":

                        info.dressType = DressType.Shoe;

                        break;

                    case "Accessory":

                        info.dressType = DressType.Accessory;

                        break;

                }

                string str_apptype = proArray[8];

                switch (str_apptype)

                {

                    case "Magician":

                        info.applicationType = ApplicationType.Magician;

                        break;

                    case "SwordMan":

                        info.applicationType = ApplicationType.Swordman;

                        break;

                    case "Common":

                        info.applicationType = ApplicationType.Common;

                        break;

                }

                   

                      

 

 

 

6.             }

37.  显示物品信息

这里我们只需要修改一下InvertoryDes即可

我们添加一个方法来获得物品信息类里的各种属性

string GetEquipDes(Objectsinfo info)

    {

        string str = "";

        str += "名称:" + info.name + "\n";

        switch (info.dressType)

        {

            case DressType.Headgear:

                str += "穿戴类型:头盔\n";

                break;

            case DressType.Armor:

                str += "穿戴类型:盔甲\n";

                break;

            case DressType.Right_Hand:

                str += "穿戴类型:右手武器\n";

                break;

            case DressType.Left_Hand:

                str += "穿戴类型:左手武器\n";

                break;

            case DressType.Shoe:

                str += "穿戴类型:鞋子\n";

                break;

            case DressType.Accessory:

                str += "穿戴类型:饰品\n";

                break;

        }

        switch (info.applicationType)

        {

            case ApplicationType.Common:

                str += "通用类型\n";

                break;

            case ApplicationType.Magician:

                str += "魔法师类型\n";

                break;

            case ApplicationType.Swordman:

                str += "剑士类型\n";

                break;

        }

        str += "sellMoney" + info.price_sell + "\n";

        str += " buyPrice" + info.price_buy + "\n";

        return str;

}

2.然后再在show方法里进行调用即可

  //在这里我,我们要根据我们获得的物品id来获得物品描述信息

    public void Show(int id)

    {

        this.gameObject.SetActive(true);

        timmer = 0.1f;

       transform.position=UICamera.currentCamera.ScreenToWorldPoint(Input.mousePosition);

        Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(id);

        string des = "";

        switch (info.type)

        {

            case ObjectType.Drug:

                des = GetDrugdes(info);

                break;

            case ObjectType.Equip:

                des = GetEquipDes(info);

                break;

        }

        label.text = des;

 

    }

38.实现物品的穿戴

在这里我们将实现物品的穿戴,接下来我将讲述一下逻辑

1.    我们在IvertoryItem里有一个isHover来判断鼠标是否在格子上,我们通过这个方法来判断穿戴哪个物品,而我们将使用右键来穿戴上对应的物品

2.    我们在EquipItemUI中书写一个Dress方法,来判断是否可以进行穿戴,并且处理穿戴事件

(1)    我们通过id来获取到我们穿戴的是什么物品,所以我们先要根据Id获取到物品信息

(2)    我们先处理三种无法穿戴的事件,当然在这里我们要给PlayerStates里添加一个主角类型的数组并且在EquipmentUi中获取到这个主角类型数组

1.    穿戴物品不是装备,返回fasle

2.    人物是魔法师穿戴剑士装备,返回false

3.    人物是剑士穿戴魔法师装备,返回false

(3)    接下来处理穿戴成功的情况,首先,我们需要定义一个parent,来使得物品正确实例化到对应的位置,我们根据物品的穿戴类型将parent设置成各种类型的位置

3这时候我们要在EquipmentItem下添加euqipmentItem脚本,处理实例化物品的方法,这里我们只需要修改贴图即可,因此我们在setinfo里将spriteName修改成icon_name即可,当然,我们要先根据id获得到物品信息才对

 

4.我们回到dress方法,这时候穿戴成功有两种可能,

(1)    即穿戴的位置有物品,有物品我们就调用EquipmentItem中的setInfo方法更新贴图即可,然后还要用Invertory中的getId方法将该物品重新放回背包内

(2)    穿戴的位置没物品,这时候我们要减少该物品栏的物品,使用Ngui下的Addchild方法来更新物品栏的显示

4.    我们在InvertoryItem里处理穿戴方法,这里我们要调用grid下的一个减少数量的方法,当可以正常进行穿戴时,我们要更新背包信息并且正常穿戴

5.    我们要在ItemGrid下书写一个减少数量的方法来处理物品信息的更新,如果数量为0则销毁该物品并且清空信息栏,如果不为0则更新显示将数量减少1

6.  public bool MinusItem(int num=1)

7.      {

8.          if (this.num >= num)

9.          {

10.             this.num -= num;

11.             numLabel.text = this.num.ToString();

12.             if (this.num == 0)

13.             {

14.                 clearInfo();//清空物品栏信息

15.                 GameObject.Destroy(this.GetComponentInChildren<InvertoryItem>().gameObject);//销毁物品

16.             }

17.             return true;

18.         }

19.         else

20.         {

21.             return false;

22.         }

23.      }

void Update()

    {

        if (isHover)

        {

            InvertoryDes._instance.Show(id);

            if (Input.GetMouseButtonDown(1))

            {

                //处理穿戴功能

                bool success = EquipmentUI._instance.Dress(id);//判断是否穿戴成功

                if (success)

                {

                   transform.parent.GetComponent<InvertoryItemGrid>().MinusItem();

                }

            }

        }

1.        }

 

        public void SetId(int id)

    {

        this.id = id;

        Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(id);

        SetInfo(info);

    }

    public void SetInfo(Objectsinfo info)

    {

        this.id = info.id;

        sprite.spriteName = info.icon_name;

    }

}

public bool Dress(int id)

    {

        Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(id);

       

        if (info.type !=ObjectType.Equip)

        {

            //如果穿戴类型不对,则无法穿戴

            return false;

        }

        if (ps.heroType == HeroType.Magician)

        {

            //类型不匹配无法穿戴

            if (info.applicationType == ApplicationType.Swordman)

            {

                return false;

            }

        }

        if (ps.heroType == HeroType.SwordMan)

        {

            //类型不匹配无法穿戴

            if (info.applicationType == ApplicationType.Magician)

            {

                return false;

            }

        }

        GameObject parent = null;

        switch (info.dressType)

        {

            case DressType.Headgear:

                parent = headGear;

                break;

            case DressType.Armor:

                parent = armor;

                break;

            case DressType.LeftHand:

                parent = left_Hand;

                break;

            case DressType.RightHand:

                parent = right_Hand;

                break;

            case DressType.Shoe:

                parent = shoe;

                break;

            case DressType.Accessory:

                parent = accessory;

                break;

 

        }

        EquipmentItem item = parent.GetComponentInChildren<EquipmentItem>();

        if (item != null)

        {

            //穿戴同样类型的装备,我们不仅要更新显示,还要将卸下来的物品放进背包

            item.SetInfo(info);

            Invertory._instance.GetId(item.id);

           

        }

        else

        {

           GameObject itemGo= NGUITools.AddChild(parent, equipmentItem);

            itemGo.transform.localPosition = Vector3.zero;

            itemGo.GetComponent<EquipmentItem>().SetInfo(info);

        }

        return true;

1.        }

39.实现物品的卸下

这里我们只需要处理一下EquipmentItem下的脚本即可

1.  我们给物品添加上BoxCollider

2.  调用NGUI下的OnHover方法判断鼠标是否在物品上并且更新isHover

3.  Update里更新,当鼠标在它上面并且点击鼠标右键的时候,就会调用InverTory中的GetID方法将物品放入背包,再销毁物品,就可以实现卸下物品的功能了

 

40. public class EquipmentItem : MonoBehaviour

41. {

42.     private UISprite sprite;

43.     public int id;

44.     private bool isHover = false;

45.     void Awake()

46.     {

47.         sprite = GetComponent<UISprite>();

48.     }

49.     void Update()

50.     {

51.         if (isHover)

52.         {

53.             if (Input.GetMouseButtonDown(1))

54.             {

55.                 Invertory._instance.GetId(id);//将自己放到背包里

56.                 Destroy(this.gameObject);

57.             }

58.         }

59.     }

60.     public void SetId(int id)

61.     {

62.         this.id = id;

63.         Objectsinfo info = ObjectInfo._instance.GetObjcetsinfoById(id);

64.         SetInfo(info);

65.     }

66.     public void SetInfo(Objectsinfo info)

67.     {

68.         this.id = info.id;

69.         sprite.spriteName = info.icon_name;

70.     }

71.     //鼠标移上或者移出会触发该方法

72.     public void OnHover(bool isOver)

73.     {

74.         isHover = isOver;

75.     }

76.  }

40.实现装备更换对于人物属性的更新

1.我们定义三个属性

    public int attack;

    public int def;

public int speed;

  

2.    定义一个更新属性的方法,我们通过获取这些装备的属性值,再加在我们预设的装备提供属性上,这样人物信息就可以通过获取这三个装备属性进行更新了

3.  public void UpdateProperty()

4.      {

5.          //用来更新角色属性

6.          this.attack = 0;

7.          this.def = 0;

8.          this.speed = 0;

9.          EquipmentItem headgearItem =headGear.GetComponentInChildren<EquipmentItem>();

10.         PlusProperty(headgearItem);

11.         EquipmentItem armorItem = armor.GetComponentInChildren<EquipmentItem>();

12.         PlusProperty(armorItem);

13.         EquipmentItem lefhandItem = left_Hand.GetComponentInChildren<EquipmentItem>();

14.         PlusProperty(lefhandItem);

15.         EquipmentItem righthandItem =right_Hand.GetComponentInChildren<EquipmentItem>();

16.         PlusProperty(righthandItem);

17.         EquipmentItem shoeItem = shoe.GetComponentInChildren<EquipmentItem>();

18.         PlusProperty(shoeItem);

19.         EquipmentItem accessoryItem =accessory.GetComponentInChildren<EquipmentItem>();

20.         PlusProperty(accessoryItem);

21.  

22.     }

23.     public void PlusProperty(EquipmentItem item)

24.     {

25.         if (item != null)

26.         {

27.             Objectsinfo equipInfo = ObjectInfo._instance.GetObjcetsinfoById(item.id);

28.             this.attack += equipInfo.attack;

29.             this.def = equipInfo.def;

30.             this.speed = equipInfo.speed;

31.         }

32.     }

33. }

4.  我们在EquipItem里调用我们的脱下装备方法

根据物品的id来设置和销毁并且更新信息

public void takeOff(int id,GameObject go)

    {

        Invertory._instance.GetId(id);//将自己放到背包里

        Destroy(go);

        UpdateProperty();

        //更新脱下后的信息

1.      }

41. 关于技能系统中信息的录入

这里我们要制作的是技能系统,首先我们要录入技能信息,然后存储技能的相关属性

using UnityEngine;

using System.Collections;

usingSystem.Collections.Generic;

 

public class SkillsInfo : MonoBehaviour

{

    public TextAsset skillsInfo;

    public static SkillsInfo _instance;

    private Dictionary<int, SkillInfo> skillinfoDict = new Dictionary<int, SkillInfo>();

    // Use this for initialization

    void Start()

    {

        _instance = this;

        InitSkillInfoDic();

    }

 

    // Update is called once per frame

    void Update()

    {

 

    }

    void InitSkillInfoDic()

    {

 

    }

}

public enum ApplicableRole

{

    //这些是角色类型

    Magician,

    SwordMan

}

//作用属性

public enum ApplicableType

{

    Passive,

    Buff,

    SingleTarget,

    MultiTarget

}

//jineng1

public enum ApplicableProperty

{

    Attack,

    Def,

    Speed,

    AttackSpeed,

    Hp,

    Mp

}

public enum ReleaseType

{

    Self,

    Enum,

    Position

}

public class SkillInfo

{

    public int id;

    public string name;

    public string icon_name;

    public string des;

    public ApplicableType applyType;

    public ApplicableProperty applyProperty;

    public ReleaseType releaseType;

    public int applyValue;

    public int  applyTime;

    public int mp;

    public int coldTime;

    public ApplicableRole applyRole;

    public int level;

    public float distance;

}

42.获取技能文本信息并且封装方便外部进行调用

这里和之前的背包系统差不多,就不多赘述了,就是分属性,得到数组后存入对应的位置,然后封装成单例模式方便在外部进行调用

public SkillInfo GetSkillInfoById(int id)

    {

        SkillInfo info = null;

        skillinfoDict.TryGetValue(id, out info);

        return info;

    }

    void InitSkillInfoDic()

    {

        string text = skillsInfoText.text;

        string[] skillInfoArray = text.Split('\n');//通过换行符区分技能列表数组

        foreach(string skillInfoStr in skillInfoArray)

        {

            string[] pa = skillInfoStr.Split(',');//技能的各个属性通过逗号区分

            SkillInfo info = new SkillInfo();

            info.id = int.Parse(pa[0]);

            info.name = pa[1];

            info.icon_name = pa[2];

            info.des = pa[3];

            string str_applyType = pa[4];

            switch (str_applyType)

            {

                case "Passive":

                    info.applyType = ApplicableType.Passive;

                    break;

                case "Buff":

                    info.applyType = ApplicableType.Buff;

                    break;

                case "SingleTarget":

                    info.applyType = ApplicableType.SingleTarget;

                    break;

                case "MultiTarget":

                    info.applyType = ApplicableType.MultiTarget;

                    break;

 

            }

            string str_applyProerty = pa[5];

            switch (str_applyProerty)

            {

                case "Attcak":

                    info.applyProperty = ApplicableProperty.Attack;

                    break;

                case "Def":

                    info.applyProperty = ApplicableProperty.Def;

                    break;

                case "Attcak_Speed":

                    info.applyProperty = ApplicableProperty.AttackSpeed;

                    break;

                case "Hp":

                    info.applyProperty = ApplicableProperty.Hp;

                    break;

                case "Mp":

                    info.applyProperty = ApplicableProperty.Mp;

                    break;

                case "Speed":

                    info.applyProperty = ApplicableProperty.Speed;

                    break;

            }

            info.applyValue = int.Parse(pa[6]);

            info.applyTime = int.Parse(pa[7]);

            info.mp = int.Parse(pa[8]);

            info.coldTime = int.Parse(pa[9]);

            switch (pa[10])

            {

                case "SwordMan":

                    info.applyRole = ApplicableRole.SwordMan;

                    break;

                case "Magician":

                    info.applyRole = ApplicableRole.Magician;

                    break;

            }

            info.level = int.Parse(pa[11]);

            switch (pa[12])

            {

                case "Self":

                    info.releaseType = ReleaseType.Self;

                    break;

                case "Position":

                    info.releaseType = ReleaseType.Position;

                    break;

                case "Enem":

                    info.releaseType = ReleaseType.Enem;

                    break;

 

 

            }

            info.distance = float.Parse(pa[13]);

            skillinfoDict.Add(info.id, info);

        }

       

    }

}

43.制作好技能栏

在这里我们要制作一个技能列表,实现滚动条,这里没什么操作的地方,就是添加一个grid来管理排序,然后添加一个ScrollViewboxCollider来控制滚动,添加一个ScrollBar来作为滚动条,要注意当滚动条不显示时修改depth

44.自动根据职业添加技能条

这里,我们要实现的是动态添加技能条,首先我们要在SkillUI下进行更改

 这里讲一下步骤

1.    创建两个数组存放魔法师技能id编号和战士技能id编号

2.    我们要获得PlayerStates中角色的状态决定显示哪个角色的技能

3.    foreach遍历数组并且动态添加到Grid下实现自动排序

4.    然后我们调用SkillItem中的setId方法来更新技能的显示

using UnityEngine;

using System.Collections;

 

public class SkillUi : MonoBehaviour

{

    public static SkillUi _instance;

    private TweenPosition tween;

    private bool isShow = false;

    //存储魔法师和剑士的技能id

    public int[] magicianSkilllid;

    public int[] swordmanSkillid;

    public UIGrid grid;

    public GameObject skillItem;

    private CharacterState1 ps;

    // Use this for initialization

    void Awake()

    {

        _instance = this;

        tween = GetComponent<TweenPosition>();

        ps = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<CharacterState1>();

    }

 

    // Update is called once per frame

    void Update()

    {

 

    }

    void Start()

    {

        int[] idList = null;

        //根据英雄类型显示对应技能图标

        switch (ps.heroType)

        {

            case HeroType.Magician:

                idList = magicianSkilllid;

                break;

            case HeroType.SwordMan:

                idList = swordmanSkillid;

                break;

        }

         foreach(int id in idList)

        {

           GameObject itemGo= NGUITools.AddChild(grid.gameObject,skillItem);

            grid.AddChild(itemGo.transform);

            itemGo.GetComponent<SkillItem>().SetId(id);//根据id更新显示

        }

 

 

 

    }

    public void TransformState()

    {

        if (isShow == false)

        {

            tween.PlayForward();

            isShow = true;

        }

        else

        {

            if (isShow == true)

            {

                tween.PlayReverse();

                isShow = false;

            }

        }

    }

 

}

这里是skillItem的脚本,就是获取item的各种信息,然后方便外部进行修改

using UnityEngine;

using System.Collections;

 

public class SkillItem : MonoBehaviour {

    private int id;

    private SkillInfo info;

    private UISprite icon_name_sprite;

    private UILabel nameLabel;

    private UILabel applyTypeLabel;

    private UILabel desLabel;

    private UILabel mpLabel;

    void InitProperty()

    {

        icon_name_sprite = transform.Find("Icon_name").GetComponent<UISprite>();

        nameLabel = transform.Find("Property/Name/name").GetComponent<UILabel>();

        applyTypeLabel = transform.Find("Property/ApplyType/applyType").GetComponent<UILabel>();

        desLabel = transform.Find("Property/Des_bg/des").GetComponent<UILabel>();

        mpLabel = transform.Find("Property/Mp_bg/mp").GetComponent<UILabel>();

    }

    //外部调用显示图标

    public void SetId(int id)

    {

        InitProperty();

        this.id = id;

        info = SkillsInfo._instance.GetSkillInfoById(id);

        icon_name_sprite.spriteName =info.icon_name;

        nameLabel.text = info.name;

        switch (applyTypeLabel.text)

        {

            case "Passive":

                applyTypeLabel.text = "增益";

                break;

            case "Buff":

                applyTypeLabel.text = "增强";

                break;

            case "SingleTarget":

                applyTypeLabel.text = "单体目标";

                break;

            case "MultiaTarget":

                applyTypeLabel.text = "群体目标";

                break;

        }

        desLabel.text = info.des;

        mpLabel.text = info.mp + "MP";

 

 

 

 

    }

}

45.关于技能根据等级显示

这里我们需要的是当等级改变时候,技能会相应的进行解锁

1.  skillItem这个prefab下添加一个skillMask并且由它决定是否可以使用技能

2.  然后我们在skillItem下添加一个UpdateLevel来根据等级更新显示

    public void UpdateLevel(int grade)

    {

        if (info.level <= grade)

        {

            icon_mask.SetActive(false);

            icon_name_sprite.GetComponent<SkillIcon>().enabled=true;

        }

        else

        {

            icon_mask.SetActive(true);

            icon_name_sprite.GetComponent<SkillIcon>().enabled = false;

        }

}

3.  我们在skillUi中获得主角当前等级,并且根据等级来更新显示

这里我们获取到技能列表,并且根据技能的level判断是否显示

 

    public void UpdateShow()

    {

        //我们要根据人物等级来更新显示

        SkillItem[] items = GetComponentsInChildren<SkillItem>();//获取所有的SkillItem

        foreach(SkillItem item in items)

        {

            item.UpdateLevel(ps.grade);

        }

 

 

    }

4我们在transformState中调用,即每次使用的时候更新显示

  public void TransformState()

    {

        if (isShow == false)

        {

            UpdateShow();

            tween.PlayForward();

            isShow = true;

        }

        else

        {

            if (isShow == true)

            {

                tween.PlayReverse();

                isShow = false;

               

            }

        }

46.人物头像的制作

1.我们将Magican添加一个分级Player

2.我们给Magician添加一个camera调整位置,使它只渲染我们的主角,它会生成一个动态texture,我们新建一个texture来存放它

3我们添加一个shader和一个mask用来渲染角色的背景

4.  UiRoot下我们添加一个SimpleTexture并且将它添加过去

5.  这样我们的任务头像就做完了

猜你喜欢

转载自blog.csdn.net/qq_36574586/article/details/77770950