001 游戏预览和介绍
职业选择
鼠标点击移动 旋转 缩放
药品 装备 任务NPC
状态 装备 技能 存档
代码跟原视频的有所改动,主要是主角行为逻辑
002 导入场景资源,搭建场景
3方资源:RPG NGUI StandarAssets
进去关闭自动生成
(问题)模型贴图丢失
改变Shader类型(这么多个,一个个改),然后重新拖地图。原类型Toon/Basic
(问题)地形贴图资源丢失
paint texture移除重新画
重新画的贴图很模糊,法线也不对
(问题)地图是灰色的
Terrain数据文件丢失,重新做吧,已经是官方的初始文档了
第二种可能,照明设置中。开启了雾气
后面发现第3种可能,Unity的优化,让场景在远的变这样,拉近点又恢复好了
(问题)Texture Paint不上去
地表的Texture个还是刷不上去
Unity 3d ,地形上刷不了纹理的原因
(了解)Terrain的Tree选项卡
Tree选项卡就是写入Terrain中,不像直接拖入场景中可以移动
画笔大小要大于树密度,可以体现出随机疏朗,不然后太整齐
003 给场景添加光,设置鼠标指针图片
(了解)默认鼠标
004 给场景添加水面和天空盒子
(了解)天空盒子 skyBox
005 实现镜头缓慢拉近的效果
找不到编辑/照明设置
移到window/渲染/渲染设置(渲染或照明)中‘
006 使用NGUI和白色图片给场景添加渐显效
NGUI toolbar只有文字
unity 2018.4.32f1对应的NGUI版本
NGUI Next-Gen UI v3.12.1 (Jun 29, 2018)
有个情况是我把所有的Assets都新建了个文件夹来保存,之后重新导到根目录,可以了。
Atlas图集
这里是NGUI的Button的图片的添加,图片要加入图集内,需要图集。
打开NGUI/打开/图集编辑器
(问题)新建失败
unity nGUI atlas 将文件保存在项目资源文件夹
(了解)
对比可用的图集,有多了材质,texture两个属性
(可行)新建 == 先复制再修改
对比可用的图集,有生成.mat .png .prefab文件。
所以尝试着复制这三个,再修改。(可行)
保存的位置一般是资源同文件夹
删
点x,再点Delete。删多个点多次x,Delete只需点一次
007 设计开始的界面,开始加载按钮和logo
(按钮)NRPG按钮 == Sprite + 触发器 + UIButton
触发器大小默认为0,要撑起来,跟按钮一样大
(按钮显示隐藏)
对象的添加,有说Tag的是,但觉得浪费。直接public
.SetActive大写
一开始按就显示加载游戏等的按钮,但想动画结束后再显示,开始时加计时器
{time -= Time.deltaTime;if (Input.anyKeyDown && time<=0)//因为开头有个动画,time秒后{newGameButton.SetActive(true);loadGameButton.SetActive(true);pressAnyKey.SetActive(false);}}
PlayerPrefs
PlayerPrefs是系统自带的,往里面存键值对
void OnNewGame()//开始游戏{PlayerPrefs.SetInt("LoadFrom", 0);}void OnLoadGame()//加载游戏{PlayerPrefs.SetInt("LoadFrom", 1);}
(按钮声音)AudioSource没声音
检查
音频文件(文件夹中播放看看)
重启软件
AudioSource叉出去,重新加
还有以下:
ProjectSetting(忘了要看什么,音量不为0?)
游戏Mute(关闭静音)
组件Mute(关闭静音)
组件音量(最大试试)
011 开始角色创建场景,导入模型和UI资源
导入Moedl
导入,加入角色选择的UI到RPG的图集里面(打开图集,选择UI后点击Add/Update)
NGUI按钮点击无效
将UIRoot的相机类型设为UI
NGUI 工具栏拖不出东西,示例场景很多损坏
看是实例场景1,2,7,9,10,12,13,14,15和tutorial都是坏的
(失败)重新导
场景恢复了,但是toolbar还是拖不出东西
(失败)更换NGUI版本
我的unity是2018.4.32f1
不能用的NGUI是NGUI Next-Gen UI v3.12.1
可以用的NGUI是NGUI Next-Gen UI v3.11.2
可以用的NGUI也有点不正常,样式不正常
(解决)过了一会又没了
发现只要我更新了自己生成的RPG资源,就一定出现NGUI的错,也就是两者起冲突了。
然后看着下图,有又是trim,又是replace,就全取消试试,暂时解决问题
一个文件夹一个图集,不要跨文件夹吧、(也许有这个原因)
NGUI放根目录Assets吧(很想跟其他导入的资源放一块)
NGUI的输入框和其他的并存了,PrefabTool也能拖拽
图集必备3文件,只有2个
Prefab mat 缺少png
应该从资料中找一下.png那张图拖进去。或者重新导
删除NGUI后,之前通过NGUI的图集编辑器制作的图集损坏
重新add进texture
(导入出现报错)
Shader error in ‘Transparent/Refractive’: Too many texture interpolators would be used for ForwardBase pass (9 out of max 8), try adding #pragma target 3.0 at line 41
加了确实没报错,不过没用到
Unity shader error: “Too many texture interpolators would be used for ForwardBase pass”
UI和场景的相机
分开的照,合并显示在屏幕上
3点打光
材质 standard
015 控制角色的上一个和下一个的选择
切换角色,要挂在按钮上
我想读文件的,即读取上把文件夹当作组件(但没学过,电脑里的游戏,直接改文件夹中的数据的日子啊 )
public GameObject[] characterPrefabArray;public int index=0;//看的private GameObject[] goArray;// Start is called before the first frame updatevoid Start(){if (characterPrefabArray.Length != 0){//实例 隐藏goArray = new GameObject[characterPrefabArray.Length];for (int i = 0; i < characterPrefabArray.Length; i++){goArray[i] = Instantiate(characterPrefabArray[i], transform.position, transform.rotation);goArray[i].SetActive(false);goArray[i].transform.parent = transform;}goArray[0].SetActive(true);}}public void PreCharacter(){goArray[index].SetActive(false);index = index == 0 ? (characterPrefabArray.Length - 1) : --index;goArray[index].SetActive(true);}public void NextCharacter(){goArray[index].SetActive(false);index = index == characterPrefabArray.Length - 1 ? 0 : ++index;goArray[index].SetActive(true);}
016 处理名称的输入和场景的切换
(问题)2D盒状触发器导致的NGUI的输入框(UIInput)不能点击输入
问题描述
上下,选择按钮都可以动,只有输入框不能点击
流程介绍
节A挂一个UIInput的节点,来接收输入框Label;
节点A被脚本引用,用value来取里面的字符串存在PlayerPrefs里面
错误排查
节点A是UIRoot没问题,是输入框根节点有问题(其他场景不会)。
因素:UIRoot、输入框根节点的Depth是0,Label是1,都一样
因素:碰撞器,结果是盒状触发器的问题,要选2D盒状触发器
因素:该案例中submit可以不用写
因素:挂UIInput的节点在运行后,会自动加上UI Input On GUI的脚本
public void LoadScene(){PlayerPrefs.SetString("SelectedPlayerName", characterNameInput.value);PlayerPrefs.SetInt("SelectedPlayerIndex", index);print(PlayerPrefs.GetInt("SelectedPlayerIndex"));print(PlayerPrefs.GetString("SelectedPlayerName"));SceneManager.LoadScene(2);//2是数据,要分离开,但我还没学过}
(了解) Invalid texture used for cursor - check importer settings or texture creation. Texture must be RGBA32, readable, have alphaIsTransparency enabled and have no mip chain.
我改这就消失了
Invalid texture used for cursor - check importer settings or texture creation. Texture must be RGBA3
(情况)unity保存,还有星号,在没有报错,警告的情况下
(问题)NGUI层黑色,运行后什么都没有
修改NGUI的相机剔除遮罩,选择default 或者 Everything(也是default起作用)
(了解)深度,深度里的会被照进来
018 标签管理
有了下面的文件,Tags.group “Group”,并且敲出Tags后是有提示的(Tags.p 可能就有 Tags.player 的提示)
好处是:写得快,不写错
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Tags : MonoBehaviour
{public const string group = "Group";public const string player = "Player";}
019 实现角色行走的点击效果
void Update(){if (Input.GetMouseButtonDown(0)){print("点击");Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//点生成射线RaycastHit hit;bool isCollided = Physics.Raycast(ray, out hit);//是否碰到if (isCollided && hit.collider.tag==Tags.ground){OnClickEffect(effectPrefab, hit.point);}}}void OnClickEffect(GameObject effectPrefab, Vector3 position){print("Move");Instantiate(effectPrefab, position, Quaternion.identity);}
(问题)空引用
MainCamera的标签
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition)会报错 空引用
(问题)位置
不是hit.collider.transfrom.position(会跑到世界坐标原点),而是 hit.point
020 控制主角移动的朝向
(问题)鼠标下点,达不到鼠标按着滑动时,玩家一直朝向位置的目的
视频时
鼠标下点,isMoving=true
鼠标上抬,isMoving=false
而鼠标下点到上抬的过程是,鼠标一直按着的时候,这过程isMoving=true
这样做到了下点按着,更新朝向,抬起不更新
上面做的后果是Update实例太多次,按着鼠标时计时
void Update(){if (Input.GetMouseButtonDown(0))//鼠标下点{notMouseButtonUp = true;targetPosition = positionByRay2Tag(Input.mousePosition, Tags.ground);prefabByPosition(effectPrefab, targetPosition);}else if (Input.GetMouseButtonUp(0))//鼠标上抬{notMouseButtonUp = false;}if (notMouseButtonUp)//鼠标按着{targetPosition = targetPosition = positionByRay2Tag(Input.mousePosition, Tags.ground); gameObject.transform.LookAt(targetPosition);//计时1秒实例 mouseButtonEffectTimer += Time.deltaTime;if (mouseButtonEffectTimer > mouseButtonEffectTime){mouseButtonEffectTimer = 0f;prefabByPosition(effectPrefab, targetPosition);}}}//判断 mouseDownPosition发出的射线是否撞到标签为tag的物体,是的返回hit的位置Vector3 positionByRay2Tag(Vector3 mouseDownPosition, string tag){Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//点生成射线RaycastHit hit;bool isCollided = Physics.Raycast(ray, out hit);//是否碰到if (isCollided && hit.collider.tag == Tags.ground){targetPosition = hit.point;return hit.point;}return Vector3.zero;//默认值}void prefabByPosition(GameObject prefab, Vector3 position)//在该位置实例预制体{Instantiate(prefab, position, Quaternion.identity);}
021 控制主角的移动
transform.Translate(Time.deltaTime * speed)
void Move(){float stopDistanceNearTargetPosition = 0.2f;//可以停下的距离float distance = Vector3.Distance(transform.position, targetPosition);if (targetPosition != Vector3.zero && distance > stopDistanceNearTargetPosition){transform.Translate(Vector3.forward * Time.deltaTime * speed);}}
角色控制器SimpleMove(speed)
void MoveByCharacterController(){float stopDistanceNearTargetPosition = 0.2f;//可以停下的距离float distance = Vector3.Distance(transform.position, targetPosition);if (targetPosition != Vector3.zero && distance > stopDistanceNearTargetPosition){characterController.SimpleMove(transform.forward * speed);}}
022 控制主角的移动动画的播放
void Update(){if (!MoveByMouse._instance.notMouseButtonUp){animation.CrossFade("Sword-Idle");}else if (MoveByMouse._instance.notMouseButtonUp){animation.CrossFade("Sword-Run");}}
(问题)玩家会出现头朝地跑
y是玩家的y
gameObject.transform.LookAt(new Vector3(targetPosition.x, transform.position.y, targetPosition.z) );
(问题)按着鼠标才出现run
因为是根据鼠标状态,而不是Vetor3.Distance
(了解)LateUpdate
Update设置状态
LateUpdate设置动画
(代码,了解)定义
public enum State
{Idle,Walk,Run
}
枚举变量的public会有下拉项的样式
(代码)设置状态
void MoveByCharacterController(){float stopDistanceNearTargetPosition = 0.2f;//可以停下的距离float distance = Vector3.Distance(transform.position, targetPosition);if (targetPosition != Vector3.zero && distance > stopDistanceNearTargetPosition){state = State.Run;characterController.SimpleMove(transform.forward * speed);}else{state = State.Idle;}}
(代码)根据状态设置动画
private new Animation animation;private State state = State.Idle;private MoveByMouse player;// Start is called before the first frame updatevoid Start(){animation = GetComponent<Animation>();player = GetComponent<MoveByMouse>();}// Update is called once per framevoid LateUpdate(){if (player.state==State.Idle){animation.CrossFade("Sword-Idle");}else if (player.state == State.Run){animation.CrossFade("Sword-Run");}}
023 修复bug完善主角的移动控制
(问题)点击后一直向前走,主要在崎岖地形
尤其是y值的过高,导致距离一直处于不到达的状态,该情况下玩家一直forward
(问题) 脚丫悬空
025 使用鼠标滑动控制相机视野的拉近和拉远
代码
public GameObject player;private Vector3 offset;//拉近public float scrollSpeed = 10f;//拉伸速度public float distance;//实际拉伸public float minDistance=3.2f;//最大拉伸public float maxDistance=30f;//最小拉伸// Use this for initializationvoid Start () {offset = transform.position - player.transform.position;//offset = new Vector3(0, offset.y, offset.z);//x=0,左右不偏移}// Update is called once per framevoid Update () {transform.position =player.transform.position+ offset;transform.LookAt(player.transform.position);offset = ScrollView();}Vector3 ScrollView()//相机拉伸{distance = offset.magnitude;distance += scrollSpeed * Input.GetAxis("Mouse ScrollWheel");if (distance < minDistance){distance = minDistance;}else if (distance > maxDistance){distance = maxDistance;}offset = offset.normalized * distance;return offset;}
(了解)Clamp夹紧
distance = Mathf.Clamp(distance, minDistance, maxDistance);//代替下面的if (distance < minDistance){distance = minDistance;}else if (distance > maxDistance){distance = maxDistance;}
027 控制视野的左右旋转
(了解)旋转影响相机的位置,offset发生变化
void RotateView(){ if (Input.GetMouseButtonDown(1)){isRotate = true;}if (Input.GetMouseButtonUp(1)){isRotate = false;}if (isRotate){transform.RotateAround(player.transform.position, Vector3.up, rotateSpeed*Input.GetAxis("Mouse X"));}offset = transform.position - player.transform.position;//旋转影响相机的位置,offset发生变化}
028 控制视野的上下旋转和范围限制
代码
按住鼠标右键旋转,上下角度钳制(10,80)
值的记录要在RotateAround之前
void RotateView()//相机旋转{ if (Input.GetMouseButtonDown(1)){isRotate = true;}if (Input.GetMouseButtonUp(1)){isRotate = false;}if (isRotate){//记录Vector3 originalPosition = transform.position;Quaternion originalRotation = transform.rotation;//赋值transform.RotateAround(player.transform.position, transform.up, rotateSpeed * Input.GetAxis("Mouse X")); transform.RotateAround(player.transform.position, transform.right, rotateSpeed * Input.GetAxis("Mouse Y"));transform.RotateAround(player.transform.position, transform.right, rotateSpeed * Input.GetAxis("Mouse Y"));//限制范围if (transform.eulerAngles.x < 10 || transform.eulerAngles.x > 80){print ("超范围了");transform.position = originalPosition;transform.rotation = originalRotation;} }offset = transform.position - player.transform.position;//旋转影响相机的位置,offset发生变化}
030 在场景中添加老爷爷这个NPC
(问题)模型的材质丢失,呈粉红色
该材质的类型standard
031 设计任务对话框的背景
(问题,严重)图集信息丢失,造成要重新加上去
丢失一次,尤其有按钮的,加图片很麻烦
发现是复制的场景,原来的没坏,但不清楚现在的为什么坏了
(问题)重影
有关透视
油
(问题)位置不对
场景中看transfrom看是680到150,就可以达到效果
Tween看是700到-1410才能达到想要的位置
032 任务系统-设计任务的内容
(问题)Label在unity字体下不显示
Material材质那里加一次字体,显示黑色字体,又None掉,白色,正常显示
感觉像给NGUI提示,快用字体啊
(问题)多个面板
正常只有1个(我也只有一个),现在是运行后左边有一个不动的,右边那个是Tween Position过来的
(问题)NGUI层出现Terrain的图像
太长照到后面的
调相机的远近
近最小0远最小0.01
(了解)场景中图标太大
Unity3D之NGUI基础2:使用NGUI
(了解)按钮所需的组件
NGUI的按钮 等于 Sprite + UIButton + Play Sound + 2D触发器(看相机是2D还是3D,系统自动切)
(解决)按钮点击不了
触发器大小默认为0,没调
用attackh自动铺张
(了解)GUI图层组件弃用
unity3d 2018.3.10f1不能使用GUI图层
(问题)NGUI的坐标不一致
场景中人物板从x610到x250
NGUI只显示了1/3,只有x610到x-770效果才一样
看别的视频,unity单位是米,但这里单位是像素
上面的距离是360,1380,也就是1米 == 2像素 ?
(解决)NGUI的按钮不能点击
对比了很多下,删掉新建最方便
(解决)UICamera.hoveredObject==null后点击地面,人物不移动
在unity中使用UICamera.hoveredObject==null后游戏点击地面无反应和鼠标点击穿透UI
private void MouseDownEvent(){// if (UICamera.hoveredObject != null) return;if (UICamera.isOverUI) return;print("鼠标下按:" + UICamera.hoveredObject);isMouseButtonPress= true;targetPosition = GetTargetPosition(Input.mousePosition);Instantiate(effectPrefab, targetPosition, Quaternion.identity);}
33 点击NPC弹出任务板
脚本挂NPC,我原想挂任务板,后面也该挂任务板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Quest : MonoBehaviour
{public GameObject quest;private void OnMouseOver(){if (Input.GetMouseButtonDown(0)){print("点击"); ShowQuest();}}void ShowQuest(){quest.GetComponent<TweenPosition>().PlayForward(); }public void DisableQuest(){quest.GetComponent<TweenPosition>().PlayReverse();}
}
36 鼠标指针管理系统
图片,焦点,软硬件
方法要被调用,不然…
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GameSettings : MonoBehaviour
{public Texture2D attackCursor;public Texture2D lockTargetCursor;public Texture2D normalCursor;public Texture2D npcTalkCursor;public Texture2D pickCursor;public static GameSettings _instance;private void Awake(){_instance = this;}public void SetNormalCursor(){Cursor.SetCursor(normalCursor, Vector2.zero, CursorMode.Auto );//图形,焦点}public void SetLockTargetCursor(){Cursor.SetCursor(lockTargetCursor, Vector2.zero, CursorMode.Auto);//图形,焦点}public void SetAttackCursor(){Cursor.SetCursor(attackCursor, Vector2.zero, CursorMode.Auto);//图形,焦点}public void SetNpcTalkCursor(){Cursor.SetCursor(npcTalkCursor, Vector2.zero, CursorMode.Auto);//图形,焦点}public void SetPickCursorr(){Cursor.SetCursor(pickCursor, Vector2.zero, CursorMode.Auto);//图形,焦点}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Npc : MonoBehaviour
{private void OnMouseEnter(){GameSettings._instance.SetLockTargetCursor();}private void OnMouseExit(){GameSettings._instance.SetNormalCursor();}
}
(了解)脚本有默认设置
037 开发功能面板
01 玩家点击 Bar上的按钮
02 触发了总节点上的函数去打开面板
public void OnStatusButtonClick(){StatusPannel._instance.ShowWindow();}public void OnBagButtonClick(){BagPannel._instance.ShowWindow();}public void OnEquipmentButtonClick(){EquipPannel._instance.ShowWindow();}public void OnSkillButtonClick(){SkillPannel._instance.ShowWindow();}public void OnSettingButtonClick(){SettingPannel._instance.ShowWindow();}
03 调用对应的面板的父类方法ShowWindow
public class Pannel : MonoBehaviour
{[Tooltip("父类Window的字段,不用设置,可调用而已")] public bool isShow = false;[Tooltip("关闭Pannel的按钮")] public UIButton closeButton;public void ShowWindow(){GetComponent<TweenPosition>().PlayForward();isShow = true;}public void DisableWindow(){GetComponent<TweenPosition>().PlayReverse();isShow = false;}
}
39-49 背包系统
TextAsset读取.txt
流程图
数据文本
1001,小瓶血药,icon-potion1,Potion,50,0,50,60
1002,大瓶血药,icon-potion2,Potion100,0,70,100
1003,蓝药,icon-potion3,Potion,100,60,80
2001,黄金甲,armor0-icon,Equip,0,50,0,Armor,Swordman,150,200
2002,铜甲,armor1-icon,Equip,0,39,0,Armor,Swordman,100,150
2003,神迹魔法衣,armor2-icon,Equip,0,50,0,Armor,Magician,150,200
2004,破旧魔法衣,armor3-icon,Equip,0,20,0,Armor,Magician,60,100
2005,铜鞋,icon-boot0,Equip,0,0,50,Shoe,Common,60,100
2006,神级红鞋,icon-boot0-01,Equip,0,0,70,Shoe,Common,120,150
2007,帽子,icon-helm,Equip,0,50,0,Headgear,Swordman,100,120
2008,神帽,icon-helm-01,Equip,0,70,0,Headgear,Swordman,120,200
2009,神级魔法帽,icon-helm-02,Equip,0,70,0,Headgear,Magician,120,200
2010,普通魔法帽,icon-helm-03,Equip,0,50,0,Headgear,Magician,100,120
2011,黄金戒指,icon-ring,Equip,0,50,0,Accessory,Common,50,70
2012,铜绿戒指,icon-ring-01,Equip,0,30,0,Accessory,Common,30,50
2013,盾牌,icon-shield,Equip,0,50,0,LeftHand,Common,50,70
2014,神盾,icon-shield1,Equip,0,70,0,LeftHand,Common,70,100
2015,皇族项链,icon-tailman,Equip,0,30,0,Accessory,Common,30,60
2016,火柴棍,rod-icon,Equip,40,0,0,RightHand,Magician,40,80
2017,金属棍,rod-icon02,Equip,60,0,0,RightHand,Magician,60,120
2018,神级魔法棒,rod-icon03,Equip,80,0,0,RightHand,Magician,80,200
2019,御剑,sword0-icon,Equip,40,0,0,RightHand,Swordman,40,60
2020,双手剑,sword0-icon00,Equip,60,0,0,RightHand,Swordman,60,100
2021,白帝圣剑,sword1-icon,Equip,80,0,0,RightHand,Swordman,80,150
2022,华夏第一剑,sword2-icon,Equip,100,0,0,RightHand,Swordman,150,200
(代码)模型类
没有MonoBehaviour,后面子类不能在编辑器内显示
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Item:MonoBehaviour//物品信息类
{public int id;//000public new string name;public string icon_name;public ItemType itemType;public int price_sell;public int price_buy;//5public DressType dressType;//部位public ApplyType applyType;//职业public int attack;public int defense;public int speed;public int hp;public int mp;void Start(){}
}public enum ItemType//物品的类型
{Potion,Equip,Mat,Undefined
}
(代码)TextAsset转化为List
两个方法的作用分别是
1、读TextAsset,写入Dictionary
2、读取Dictionary,返回一个上述模型类的一个对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TextAssetToDictionary: MonoBehaviour
{[Tooltip("数据文本,英文逗号分割,回车换行")]public TextAsset textAsset;[Tooltip("组件不显示,是为了让访问调用")]public Dictionary<int, Item> dictionary = new Dictionary<int, Item>();public static TextAssetToDictionary _instance;void Awake(){_instance = this;dictionary = Read(textAsset);}public Dictionary<int, Item> Read(TextAsset textAsset)//读取TextAsset,存储到Dictionary{string[] lineArray = textAsset.text.Split('\n');foreach (string line in lineArray){string[] propertyArray = line.Split(',');//英文逗号//分流Item item = new Item();item.id = int.Parse(propertyArray[0]);item.name = propertyArray[1];item.icon_name = propertyArray[2];//根据类型在具体赋值switch (propertyArray[3]){case "Potion": item.itemType = ItemType.Potion; break;case "Equip": item.itemType = ItemType.Equip; break;case "Mat": item.itemType = ItemType.Mat; break;default: item.itemType = ItemType.Undefined; break;}//药品switch (item.itemType){case ItemType.Potion://药品{item.hp = int.Parse(propertyArray[4]);item.mp = int.Parse(propertyArray[5]);item.price_sell = int.Parse(propertyArray[6]);item.price_buy = int.Parse(propertyArray[7]);}break;case ItemType.Equip://装备{item.attack = int.Parse(propertyArray[4]);item.defense = int.Parse(propertyArray[5]);item.speed = int.Parse(propertyArray[6]);switch (propertyArray[7]){case "Headgear": item.dressType = DressType.Headgear; break;case "Armor": item.dressType = DressType.Armor; break;case "LeftHand": item.dressType = DressType.LeftHand; break;case "RightHand": item.dressType = DressType.RightHand; break;case "Shoe": item.dressType = DressType.Shoe; break;case "Accessory": item.dressType = DressType.Accessory; break;default: break;}switch (propertyArray[8]){case "Swordman": item.applyType = ApplyType.Swordman; break;case "Magician": item.applyType = ApplyType.Magician; break;case "Common": item.applyType = ApplyType.Common; break;default:break;}item.price_sell = int.Parse(propertyArray[9]);item.price_buy = int.Parse(propertyArray[10]);}break;default:break;}dictionary.Add(item.id, item);}return dictionary;}public Item GetItemById(int id){dictionary.TryGetValue(id, out Item item);return item;}
}
背包
流程图
ItemGroup就是一群,一堆Item的意思,多了数量的属性;
之前想用Bag_Item,但商店里面的也是一样的属性
实例的预制体是ItemGroup,继承于Item,Item的using… Start Update方法不能删除,否则它和子类都不能挂在(还是显示)在编辑器中
(问题)首位多次生成
之前记录的NGUI的有问题,就是拖拽最前面的有时(常常会生成物品)
因为是点击生成物品。拖第一个时形成空位,所以就生成物品在首位
for (int i = 0; i < gridList.Count; i++){string itemName= itemList[itemIndex].GetComponent<UISprite>().spriteName;string goodName= gridList[i].childCount ==0 ? "" : gridList[i].GetChild(0).GetComponent<UISprite>().spriteName ;print(goodName+","+itemName);//测试bool isFind = (itemName==goodName);//新增的sprite名字在格子的子节点中是否能找到相同的if (isFind){print("相同");IncreaseGood(i);break;}
(代码)取数据,挂在BagPannel下
将字典的每一项item传给ItemGroup
void InitItemPrefabList()//读取文本,派生Item预制体,生成对象{dictionary = GetComponent<TextAssetToDictionary>().dictionary;print("3423"+dictionary.Count);//遍历字典,填充itemPrefab,加入列表for (int i = 0; i < dictionary.Count; i++){//看着文本的id来改Item item =new Item();if (i > 2)item = dictionary[2001 + i - 3];//药品//取值elseitem = dictionary[1001 + i];//装备GameObject itemPrefab = Instantiate(bag_Item);//生成itemPrefab.transform.parent = transform;//挂在总节点下,美观itemPrefab = itemPrefab.GetComponent<Bag_Item>().SetValue(item);//赋值itemPrefabList.Add(itemPrefab);//加入}}
(代码)ItemGroup
根据Item取值和UI显示,隐约觉得继承类可以用,但还没学到
继承Item的话会被Monobehavior排斥,导致无法在编辑器中使用添加。
所以还是将Item当成组件
(做到了),就是基类Item的using, start,update不能省略,不让没法拖到对象上
看到ScriptableObject,介绍单一的(视频是拖出一个,填值),暂时没学到它的价值
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ItemGroup : Item
{//比Item额外多的[Tooltip("信息提示框")] public GameObject tipGo;[Tooltip("信息提示框的文本")] private UILabel tipLabel;[Tooltip("数量的文本框")] public UILabel countLabel;[Tooltip("数量")] public int count = 0;[Tooltip("信息提示框显示时间")] public float activeTime = 0.2f;[Tooltip("信息提示框计时器")] public float timer = 0f;void Start(){}void Update(){}public void DisableTip()//信息框计时隐藏{tipGo.SetActive(false);}public void ShowTip()//显示提示框文本{tipGo.SetActive(true);string tip = "";switch (itemType){ case ItemType.Potion://药品{tip = "名称:" + name;tip += "\n类型:药品";tip += "\n效果:Hp+" + hp;tip += "\n效果:Mp+" + mp; tip += "\n售价:" +price_sell;}break;case ItemType.Equip://装备{string dressTypeStr = "";switch (dressType)//部位{case DressType.Headgear:dressTypeStr = "头部";break;case DressType.Armor:dressTypeStr = "身体";break;case DressType.LeftHand:dressTypeStr = "左手";break;case DressType.RightHand:dressTypeStr = "右手";break;case DressType.Shoe:dressTypeStr = "脚";break;case DressType.Accessory:dressTypeStr = "饰品";break; }string applyTypeStr = "";switch (applyType)//职业{case ApplyType.Swordman: applyTypeStr = "战士"; break;case ApplyType.Magician: applyTypeStr = "魔法师"; break;case ApplyType.Common: applyTypeStr = "通用"; break;}//打印tip = "名称:" + name;tip += "\n类型:装备";tip += "\n部位类型:"+ dressTypeStr;tip += "\n职业类型:"+ applyTypeStr;tip += "\n攻击:"+ attack;tip += "\n防御:"+ defense;tip += "\n速度:"+ speed;tip += "\n售价:" + price_sell;}break;default:{tip = "名称:未命名";tip += "\n类型:未定义";}break;}tipLabel.text = tip;}public void SetValue(Item item)//父类的数据赋值给子类,因为数据是父类的{id=item.id; name=item.name;icon_name=item.icon_name;itemType=item.itemType;price_sell= item.price_sell;price_buy= item.price_buy;dressType= item.dressType;applyType= item.applyType;attack= item.attack;defense= item.defense;speed = item.speed;hp= item.hp;mp= item.mp;}
}
(代码)拖拽组件
重写了UIDragAndDrop,加在物品上。
格子标签是Grid,物品预制体的标签是Good
using UnityEngine;public class MyDragDrop : UIDragDropItem
{[Tooltip("开始拖拽的物体的位置")] private Vector3 startPos = Vector3.zero;protected override void OnDragDropStart(){base.OnDragDropStart();startPos = base.transform.position;//记录开始位置,为了回滚到原来的位置}protected override void OnDragDropRelease(GameObject surface){base.OnDragDropRelease(surface);print(surface.tag);if (surface.tag == "Grid"){//transform.position = surface.transform.position;//物体放入格子里transform.parent = surface.transform;transform.localPosition = Vector3.zero;}else if (surface.tag == "Good"){//位置交换transform.position = surface.transform.position;surface.transform.position = startPos;}else//脱到不该脱的位置{transform.position = startPos;}}
}
(代码)增加物品,挂在BagPannel下
背包的总节点吧,方便做预制体
void CreateNewItem(List<Transform> gridList,List<Item> itemList)//点击生成物品的测试函数,{//1 随机添加一个物品int createNewItemId = itemList[ Random.Range(0, itemList.Count) ].id;//新建的物品的id //2 有没有相同的for (int i = 0; i < gridList.Count; i++)//找到图片名相同的grid的索引{if (gridList[i].transform.childCount == 0)//循环{AddNewItem(i, createNewItemId);//用拿到的id去对应的i实例break;}else if (gridList[i].transform.childCount > 0){int itemGroupId = gridList[i].transform.GetChild(0).GetComponent<ItemGroup>().id;//取得格子里面的物品的id,moonobehavior排斥if (itemGroupId == createNewItemId)//相同,到对应的i加加{AddExistingItem(i);break;}else//循环{if (i == gridList.Count - 1)print("满了");}}}}void AddNewItem(int index,int id)//新增{Item item= TextAssetToList._instance.GetItemById(id);GameObject go = Instantiate(itemGroupPrefab);ItemGroup itemGroup = go.GetComponent<ItemGroup>();itemGroup.SetValue(item);go.GetComponent<UISprite>().spriteName = itemGroup.icon_name;go.transform.parent = gridList[index].transform;go.transform.localPosition = Vector3.zero;go.transform.localScale = Vector3.one;itemGroupList.Add(item); }void AddExistingItem(int gridIndex)//旧增{Transform t = gridList[gridIndex].transform;//各自位置int count = int.Parse(t.GetChild(0).GetChild(0).GetComponent<UILabel>().text);//格子下的物品,物品下的Label对象t.GetChild(0).GetChild(0).GetComponent<UILabel>().text = (++count).ToString();}
(了解)UI Trigger组件
做鼠标悬浮的显示隐藏
over,out分别拖入显示隐藏信息提示框的方法
(问题)提示框中文不显示
支持中文的字体
(问题)图片过大
go.transform.localScale = Vector3.one;
(问题)The root GameObject of the opened Prefab has been moved out of the Prefab …
现在只靠拖出来改,再拖回去
The root GameObject of the opened Prefab has been moved out of the Prefab …
50-52 状态系统(属性点数的分配、应用、重置修改)
流程图
UI
代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Status : Window
{private int attack ;private int defense;private int speed;private int point;[Tooltip("数字部分的Label")] public UILabel attackLabel;[Tooltip("数字部分的Label")] public UILabel defenseLabel;[Tooltip("数字部分的Label")] public UILabel speedLabel;[Tooltip("数字部分的Label")] public UILabel pointLabel;// Start is called before the first frame updatevoid Start(){GetValue();SetLabel();}//点击了相应的加按钮public void OnAttackClick(){bool havePoint = ConsumePoint();if (!havePoint) return;attack++;SetLabel(); }public void OnDefenseClick(){bool havePoint = ConsumePoint();if (!havePoint) return;defense++;SetLabel();}public void OnSpeedClick(){bool havePoint = ConsumePoint();if (!havePoint) return;speed++;SetLabel();}//够钱就扣,返回true;不然还钱,返回falseprivate bool ConsumePoint(){point--;if (point < 0){point++;return false;} return true;}public void ResetValue ()//重置{GetValue();SetLabel();}public void SetValue()//应用修改{PlayerStatus._instance.attack=attack;PlayerStatus._instance.defense=defense;PlayerStatus._instance.speed=speed;PlayerStatus._instance.point=point;}public void GetValue()//到玩家那里获取数据{attack = PlayerStatus._instance.attack;defense = PlayerStatus._instance.defense;speed = PlayerStatus._instance.speed;point = PlayerStatus._instance.point;}public void SetLabel()//输出到状态板的Label{attackLabel.text = attack.ToString();defenseLabel.text = defense.ToString();speedLabel.text = speed.ToString();pointLabel.text = point.ToString();}}
问题 组件前面没有可选框
unity–为什么Inspector视图中脚本前面的勾选框没了
将一个父类方法的名字修改后,出现了TweenPosition丢失
背景是将 状态按钮 触发 父节点的方法 去调用 状态栏的父类方法ShowWindow
现尝试将 状态按钮 触发 父节点的方法 去调用 状态栏的父类方法ShowWindow,可以达到效果
所以问题在父节点的方法
53-55 商店系统
56-63 装备系统
视频是通过点击背包里面的装备来穿戴
想到,UI上
01 临时的Bag在左边,装备栏在右边,方便拖拽添加装备
02 界面不够显示两个面板,所以是,显示一个,隐藏一个,通过双击(右键)
需求:
01、打开装备栏点击部位,隐藏装备栏,弹出背包栏,显示玩家职业类型,该部位类型的人装备,再点击装备,实现穿戴或02、者替换,玩家属性的加减
打开背包,弹出背包栏,显示玩家职业类型,该部位类型的人装备,再点击装备,实现穿戴或者替换,玩家属性的加减
03、实现背包里面的数据和显示分离,方便显示可以装备的装备。存储的是
类
想到比Item就多了count属性,Group一群一堆。
框是做预制体用到的UI显示
流程
(重构)拆开数据表和对象表
背景是,在装备栏的部位槽点击进入背包,想背包显示的是该职业该部位属于装备的物品
想到,数据归一档,这个数据可以是所有类型的的物品表,装备类的表,药品类的表,装备老板的商品表,药品老板的商品表。
(代码)原来的
对应的,加减数量也需要更新背包,所以冗余了
void AddNewItem(int index,int id)//新增{Item item= TextAssetToList._instance.GetItemById(id);GameObject go = Instantiate(itemGroupPrefab);ItemGroup itemGroup = go.GetComponent<ItemGroup>();itemGroup.SetValue(item);go.GetComponent<UISprite>().spriteName = itemGroup.icon_name;go.transform.parent = gridList[index].transform;go.transform.localPosition = Vector3.zero;go.transform.localScale = Vector3.one;itemGroupList.Add(item); }
(代码)现在的,将显示部分拆出来复用
void AddNewItem(int id)//新增{ Item item= TextAssetToList._instance.GetItemById(id);ItemGroup itemGroup = new ItemGroup();itemGroup.SetValue(item);itemGroup.count = 1;itemGroupList.Add(itemGroup);}void DisplayItem(List<ItemGroup> itemGroupList)//拿到对应的数据表 itemGroupList,进行实例{if (itemGroupObjectList!=null){foreach (GameObject itemGroupObject in itemGroupObjectList){Destroy(itemGroupObject);}itemGroupObjectList.Clear();//不clear,list里面有很多Missing的对象}重新展览for (int i = 0; i < itemGroupList.Count; i++){GameObject go = Instantiate(itemGroupPrefab);ItemGroup itemGroup = go.GetComponent<ItemGroup>();itemGroup.SetValue(itemGroupList[i]);itemGroup.countLabel.text = itemGroup.count.ToString();go.GetComponent<UISprite>().spriteName =itemGroup.icon_name;go.transform.parent = gridList[i].transform;go.transform.localPosition = Vector3.zero;go.transform.localScale = Vector3.one;itemGroupObjectList.Add(go);}}
(问题) 在第一个格子死循环增加第一个随机出来的item
实例的代码在Display方法里面,Display裸露在Update,而不是在鼠标左键条件下。
也没有销毁之前的
void Update(){if (Input.GetKeyDown(KeyCode.Space) && _instance.isShow)//在背包打开的情况下点击{CreateNewItem(itemList);//克隆对象进背包DisplayItem(itemGroupList);} }
再次Display,没有clear以前的对象列表
void DisplayItem(List<ItemGroup> itemGroupList)//拿到对应的数据表 itemGroupList,进行实例{itemGroupObjectList.Clear();for (int i = 0; i < itemGroupList.Count; i++){GameObject go = Instantiate(itemGroupPrefab);ItemGroup itemGroup = go.GetComponent<ItemGroup>();itemGroup.SetValue(itemGroupList[i]);itemGroup.countLabel.text = itemGroup.count.ToString();go.GetComponent<UISprite>().spriteName =itemGroup.icon_name;go.transform.parent = gridList[i].transform;go.transform.localPosition = Vector3.zero;go.transform.localScale = Vector3.one;itemGroupObjectList.Add(go);}}
点击装备槽显示对应职业、部位的装备(筛选)
//从装备栏点击进来public void OnDressTypeClick(DressType dressType)//筛选出 职业类型,Item类型(装备),部位类型的物品{List<ItemGroup> equipGroupList = new List<ItemGroup>();foreach (ItemGroup itemGroup in BagPannel._instance.itemGroupList){if (itemGroup.dressType == dressType &&itemGroup.applyType == Player._instance.applyType &&itemGroup.itemType == ItemType.Equip)//找出职业,部位符合的装备{equipGroupList.Add(itemGroup);}}BagPannel._instance.DisplayItem(equipGroupList);this.DisableWindow();BagPannel._instance.ShowWindow();}
左键装备,或者替换
public void DressEquipItem(ItemGroup itemGroup){//替换操作if (itemGroup.itemType != ItemType.Equip ) return;if (itemGroup.applyType != Player._instance.applyType && itemGroup.applyType != ApplyType.Common) return;Transform dressTrans = EquipPannel._instance.DressTypeToTransform(itemGroup.dressType);if (dressTrans.childCount != 0)//替换,多了回滚动作,其他一样{//卸下UnDressEquipItem(dressTrans.GetChild(0).GetComponent<EquipItem>());}MinusExistingItem(itemGroup.id);//减减 或者 销毁移除EquipPannel._instance.DressItemGroup(itemGroup);//装备}
物品预制体写方法传参id给BagPannel,被双击动作调用
public void OnItemGroupDubleClick(){BagPannel._instance.UseItemGroup(id);}
脱下
public bool UnDressEquipItem(EquipItem equipItem){print("bag脱下");if (itemGroupList.Contains(equipItem))//有同类{AddExistingItem(equipItem.id); }if (!itemGroupList.Contains(equipItem))//无同类{if (itemGroupObjectList.Count + 1 > gridList.Count)//满了,不能卸下{return false;}AddNewItem(equipItem.id);}return true;}
}
玩家双击EquipItem,向 装备栏 传递 穿戴类型
public void UndressItemGroup(){EquipPannel._instance.UndressItemGroup(dressType);}
装备栏根据穿戴类型,销毁对应部位上的装备,回滚(加加或新增)装备到背包
public void UndressItemGroup(DressType dressType){//销毁,传idTransform equipTransform;switch (dressType){case DressType.Headgear:equipTransform = headgear;break;case DressType.Armor: equipTransform = anmor; break;case DressType.LeftHand:equipTransform = leftHand;break;case DressType.RightHand:equipTransform = rightHand;break;case DressType.Shoe:equipTransform = shoe;break;case DressType.Accessory:equipTransform = accessory;break;default:throw new System.Exception("脱下装备出错");}//销毁回滚int id = equipTransform.GetChild(0).GetComponent<ItemGroup>().id;Destroy(equipTransform.GetChild(0).gameObject);BagPannel._instance.AddExistingItem(id);}
(问题) InvalidOperationException: Collection was modified; enumeration operation may not execute.
枚举列表时修改了列表
(问题) 文本提示框错误
给本体赋值,而不是给一个接收本体的对象赋值。错误文本框显示的是预制体填的值
ItemGroup itemGroup = go.GetComponent<ItemGroup>();itemGroup.SetValue(item);//正确go.GetComponent<ItemGroup>().SetValue(item);
(现象) 设置字体的字距调整值"Miscrosoft YaHei"
拖个ttf的字体到unity,弹出这个很卡很久