001 Game Preview and Introduction
Career selection
Mouse click to move, rotate, zoom
Drug Equipment Quest NPC
Status Equipment Skill Archive
002 Import scene resources and build the scene
3-party resources: RPG NGUI StandarAssets
enter and close automatic generation
(Problem) Model textures are missing
Change the Shader type (so many, one by one), and then drag the map again. Prototype Toon/Basic
(Problem) Terrain texture resources are missing
The paint texture is removed and repainted.
The repainted texture is blurry and the normal is not correct.
(Problem) The map is greyed out
The Terrain data file is lost, let’s do it again, it’s already the official initial document
The second possibility is lighting settings. After turning on the fog
, I found the third possibility later. The optimization of Unity makes the scene look like this when it is far away, and it recovers when it is zoomed in.
(Problem) Texture Paint does not go up
The texture of the surface still cannot be brushed to
Unity 3d, the reason why the texture cannot be brushed on the terrain
(Learning) Terrain's Tree tab
The Tree tab is written into the Terrain, unlike directly dragging it into the scene to move it.
The size of the brush is larger than the tree density, which can reflect random sparseness, not too neat
003 Add light to the scene, set the mouse pointer picture
(Understand) Default Mouse
004 Add water surface and sky box to the scene
(Understanding) skybox skyBox
005 Realize the effect of zooming in slowly
Can't find edit/lighting settings
Move to window/rendering/render setup (rendering or lighting)'
006 Use NGUI and white pictures to add fade-in effect to the scene
NGUI toolbar has only text
The NGUI version corresponding to unity 2018.4.32f1 is
NGUI Next-Gen UI v3.12.1 (Jun 29, 2018).
In one case, I created a new folder for all Assets to save them, and then re-imported them to the root directory.
Atlas
Here is the addition of NGUI's Button pictures. To add pictures to the atlas, you need the atlas.
Open NGUI /Open/Atlas Editor
(Problem) New failed
Unity nGUI atlas saves the file in the project resource folder
(learn)
Compared with the available atlases, there are two more properties of material and texture
(feasible) new == copy first and then modify
Comparing the available atlases, there are .mat .png .prefab files generated.
So try to copy these three, and then modify. (Feasible)
The save location is generally the same folder as the resource
delete
Click x, then click Delete. Delete multiple points x multiple times, Delete only needs to be clicked once
007 Design the initial interface, start loading button and logo
(Button) NRPG Button == Sprite + Trigger + UIButton
The trigger size is 0 by default, it needs to be propped up, as big as the button
(button show hidden)
Adding objects, there is a tag, but I think it is a waste. Direct public
.SetActive uppercase
When you press it at the beginning, the button to load the game, etc. is displayed, but you want to display it after the animation is over, and add a timer at the beginning
{
time -= Time.deltaTime;
if (Input.anyKeyDown && time<=0)//因为开头有个动画,time秒后
{
newGameButton.SetActive(true);
loadGameButton.SetActive(true);
pressAnyKey.SetActive(false);
}
}
PlayerPrefs
PlayerPrefs comes with the system and stores key-value pairs in it
void OnNewGame()//开始游戏
{
PlayerPrefs.SetInt("LoadFrom", 0);
}
void OnLoadGame()//加载游戏
{
PlayerPrefs.SetInt("LoadFrom", 1);
}
(button sound) AudioSource has no sound
Check
the audio file (play it in the folder to see)
restart the software
AudioSource fork out, re-add
and the following:
ProjectSetting (forget what to watch, the volume is not 0?)
Game Mute (turn off mute)
Component Mute (close mute)
Component Volume (Try Max)
011 Start character creation scene, import model and UI resources
Import Modl
, add the UI of character selection to the RPG atlas (open the atlas, select the UI and click Add/Update)
NGUI button click not working
Set the camera type of UIRoot to UI
The NGUI toolbar cannot drag anything, and many sample scenes are damaged
Look at the example scenarios 1,2,7,9,10,12,13,14,15 and tutorial are all bad
(Failure) Reboot
The scene is restored, but the toolbar still cannot drag anything
(failure) change NGUI version
My unity is 2018.4.32f1.
The NGUI that cannot be used is NGUI Next-Gen UI v3.12.1.
The NGUI that can be used is NGUI Next-Gen UI v3.11.2
The NGUI that can be used is also a bit abnormal, and the style is not normal
(Solution) After a while it disappeared again
I found that as long as I update the RPG resources I generated, there must be a fault with NGUI, that is, there is a conflict between the two.
Then look at the picture below, there are trim and replace again, just cancel all of them and try to solve the problem temporarily
One folder and one gallery, don’t cross
folders
The input box of NGUI coexists with others, and PrefabTool can also be dragged and dropped
Atlas must have 3 files, only 2
Prefab mat missing png
You should find the .png picture from the data and drag it in. or redirect
After deleting NGUI, the atlas previously created by NGUI's atlas editor is damaged
Re-add into texture
(An error occurred when importing)
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 did not report an error, but did not use Unity shader error: “Too many texture interpolators would be us ed for ForwardBase
pass
”
Camera for UI and scene
Separate photos, merged and displayed on the screen
3 o'clock lighting
material standard
015 Control the previous and next selection of the character
To switch roles, you need to hang on the button.
I want to read the file, that is, read the folder as a component (but I haven’t learned it, the game on the computer, the days of directly changing the data in the folder)
public GameObject[] characterPrefabArray;
public int index=0;//看的
private GameObject[] goArray;
// Start is called before the first frame update
void 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 Handle name input and scene switching
(Problem) The input box (UIInput) of NGUI caused by the 2D box trigger cannot be clicked to enter
Description of the problem
The up and down and selection buttons can be moved, only the input box cannot be clicked
Process introduction
Section A hangs a UIInput node to receive the input box Label;
node A is referenced by the script, and uses value to get the string inside and store it in PlayerPrefs
Troubleshooting
Node A is UIRoot, no problem, but the root node of the input box is problematic (not in other scenarios).
Factors: UIRoot, Depth of the root node of the input box is 0, Label is 1, all the same
Factors: Collider, the result is a box trigger problem, choose a 2D box trigger
Factors: In this case, submit can be omitted
Factors: After the node linked to UIInput is running, the script of UI Input On GUI will be automatically added
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.
I changed this and it disappeared
Invalid texture used for cursor - check importer settings or texture creation. Texture must be RGBA3
(Situation) Unity saves, and there are asterisks, in the case of no error or warning
(Problem) The NGUI layer is black, and there is nothing after running
Modify NGUI's camera culling mask, choose default or Everything (default also works)
(Understanding) depth, what is in the depth will be reflected
018 Tag Management
With the following file, Tags.group "Group", and there will be a prompt after typing out Tags (Tags.p may have a Tags.player prompt). The
advantage is: write quickly and do not make mistakes
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tags : MonoBehaviour
{
public const string group = "Group";
public const string player = "Player";
}
019 Realize the click effect of character walking
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);
}
(problem) null reference
MainCamera's label
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition) will report an empty reference
(problem) location
Not hit.collider.transfrom.position (will run to the origin of the world coordinates), but hit.point
020 Control the direction of the protagonist's movement
(Problem) When the mouse is clicked down, the player is always facing the position when the mouse is pressed and slid
During the video
, the mouse clicks down, isMoving=true
, the mouse moves up, isMoving=false,
and the process from the mouse down point to the upward movement is when the mouse is pressed all the time, the process isMoving=true, when the mouse is pressed down, the
direction is updated, and the direction is updated when the mouse is lifted up
The consequence of the above is that the Update instance is too many times, and the time is counted when the mouse is pressed
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 Control the movement of the main character
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);
}
}
Character Controller 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 Control the playback of the protagonist's movement animation
void Update()
{
if (!MoveByMouse._instance.notMouseButtonUp)
{
animation.CrossFade("Sword-Idle");
}
else if (MoveByMouse._instance.notMouseButtonUp)
{
animation.CrossFade("Sword-Run");
}
}
(Problem) Players appear to run headfirst
y is the player's y
gameObject.transform.LookAt(new Vector3(targetPosition.x, transform.position.y, targetPosition.z) );
(Problem) Run appears only when the mouse is pressed
Because it is based on the mouse state, not Vetor3.Distance
(Understanding) LateUpdate
Update sets state
LateUpdate sets animation
(code, understand) definition
public enum State
{
Idle,
Walk,
Run
}
The public of the enumeration variable will have the style of the drop-down item
(code) set state
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;
}
}
(Code) animate based on state
private new Animation animation;
private State state = State.Idle;
private MoveByMouse player;
// Start is called before the first frame update
void Start()
{
animation = GetComponent<Animation>();
player = GetComponent<MoveByMouse>();
}
// Update is called once per frame
void LateUpdate()
{
if (player.state==State.Idle)
{
animation.CrossFade("Sword-Idle");
}
else if (player.state == State.Run)
{
animation.CrossFade("Sword-Run");
}
}
023 Fix bugs and improve the movement control of the protagonist
(Issue) Walk straight after clicking, mostly on rough terrain
Especially the y value is too high, resulting in the distance has not been reached, in this case the player has been forward
(problem) feet dangling
025 Use the mouse to slide to control the zooming in and out of the camera field of view
the code
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 initialization
void Start () {
offset = transform.position - player.transform.position;
//offset = new Vector3(0, offset.y, offset.z);//x=0,左右不偏移
}
// Update is called once per frame
void 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;
}
(Understanding) Clamp clamping
distance = Mathf.Clamp(distance, minDistance, maxDistance);
//代替下面的
if (distance < minDistance)
{
distance = minDistance;
}
else if (distance > maxDistance)
{
distance = maxDistance;
}
027 Control the left and right rotation of the field of view
(Understanding) Rotation affects the position of the camera, and the offset changes
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 Control the up and down rotation and range limitation of the field of view
the code
Press and hold the right mouse button to rotate,
the record of the upper and lower angle clamp (10, 80) value should be before 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 Add the NPC Grandpa to the scene
(Problem) The texture of the model is missing and it is pink
The material's type standard
031 Design task dialog background
(Problem, serious) The atlas information is lost, causing it to be added again
I lost it once, especially the one with buttons, it is very troublesome to add pictures.
I found that it was a copied scene. The original one is not broken, but I don’t know why the current one is broken.
(problem) ghosting
Perspective
Oil
(problem) wrong position
In the scene, the transfrom is 680 to 150, and the effect can be achieved.
The Tween is 700 to -1410 to achieve the desired position.
032 Mission system - Design mission content
(Problem) Label does not display under unity font
Add a font to the Material material, display a black font, and then drop None, white, and display normally.
It feels like a reminder to NGUI, use the font quickly.
(problem) multiple panels
Normally there is only one (I only have one), now after running, there is one on the left that does not move, and the one on the right is from Tween Position
(Problem) The image of Terrain appears in the NGUI layer
If it is too long to shine to the back,
adjust the distance of the camera.
Near minimum 0 far minimum 0.01
(Understanding) The icon in the scene is too large
Unity3D's NGUI Basics 2: Using NGUI
(Understanding) the components required for the button
The button of NGUI is equal to Sprite + UIButton + Play Sound + 2D trigger (see if the camera is 2D or 3D, the system will automatically switch)
(Solution) The button cannot be clicked
The trigger size defaults to 0, and
the attackh is not called to automatically stretch
(Understanding) GUI layer component deprecation
Unity3d 2018.3.10f1 cannot use GUI layers
(Problem) The coordinates of NGUI are inconsistent
The character board in the scene only shows 1/3 from x610 to x250 NGUI, and only the effect is the same from x610 to x-770
Looking at other videos, the unit of unity is meters, but here the unit is pixels.
The distance above is 360, 1380, that is, 1 meter == 2 pixels?
(Solution) The button of NGUI cannot be clicked
After comparing a lot, it is most convenient to delete and create a new one
(Solution) After UICamera.hoveredObject==null, click on the ground, the character does not move
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 Click the NPC to pop up the task board
The script hangs on the NPC, I originally wanted to hang the task board, and the task board should also be hung later
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 Mouse pointer management system
Image, focus, software and hardware
methods must be called, otherwise...
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();
}
}
(Understanding) scripts have default settings
037 Develop function panel
01 The player clicks the button on the Bar
02 Trigger the function on the master node to open the panel
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 Call the parent class method ShowWindow of the corresponding panel
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 backpack system
TextAsset read.txt
flow chart
data text
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, Baidi Holy Sword, sword1-icon, Equip, 80,0,0, RightHand, Swordman, 80,150
2022, The First Sword of China, sword2-icon, Equip, 100,0,0, RightHand, Swordman, 150,200
(code) model class
Without MonoBehaviour, subsequent subclasses cannot be displayed in the editor
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item:MonoBehaviour//物品信息类
{
public int id;//000
public new string name;
public string icon_name;
public ItemType itemType;
public int price_sell;
public int price_buy;//5
public 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
}
(Code) Convert TextAsset to List
The functions of the two methods are
1. Read TextAsset, write to Dictionary
2. Read Dictionary, and return an object of the above model class
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;
}
}
Backpack
flow chart
ItemGroup is a group, meaning a bunch of Items, with more attributes;
I wanted to use Bag_Item before, but the same attributes in the store
The prefab of the instance is ItemGroup, inherited from Item, and the using... Start Update method of Item cannot be deleted, otherwise neither it nor its subclasses can be hung (or displayed) in the editor
(Problem) First bit generated multiple times
There is a problem with the NGUI recorded before, that is, dragging the frontmost item (often generating items)
is because clicking generates items. When dragging the first one, an empty space is formed, so the generated item is at the first place
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;
}
(Code) Get data and hang it under BagPannel
Pass each item of the dictionary to 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];//药品
//取值
else
item = dictionary[1001 + i];//装备
GameObject itemPrefab = Instantiate(bag_Item);//生成
itemPrefab.transform.parent = transform;//挂在总节点下,美观
itemPrefab = itemPrefab.GetComponent<Bag_Item>().SetValue(item);//赋值
itemPrefabList.Add(itemPrefab);//加入
}
}
(Code) ItemGroup
According to the value of the Item and the UI display, I vaguely feel that the inherited class can be used, but I have not learned that if you
inherit the Item, it will be rejected by the Monobehavior, which makes it impossible to add it in the editor.
So still treat Item as a component
(I did it), that is, the using, start, and update of the base class Item cannot be omitted, so that it cannot be dragged onto the object. I saw
ScriptableObject and introduced a single one (the video is to drag one out and fill in the value), but I have not learned its value for the time being.
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;
}
}
(Code) Drag and Drop Components
UIDragAndDrop is rewritten and added to the item.
The grid label is Grid, and the item prefab's label is 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;
}
}
}
(Code) Add items and hang them under BagPannel
The main node of the backpack, which is convenient for making prefabricated bodies
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();
}
(Understanding) the UI Trigger component
The method of displaying and hiding
the over and out of the mouse hover and dragging them into the display and hide information prompt box respectively
(Problem) The prompt box is not displayed in Chinese
Support Chinese fonts
(Problem) Image is too large
go.transform.localScale = Vector3.one;
(问题)The root GameObject of the opened Prefab has been moved out of the Prefab …
Now just drag it out and change it, and then drag it back.
The root GameObject of the opened Prefab has been moved out of the Prefab …
50-52 Status system (allocation, application, reset modification of attribute points)
flow chart
UI
the code
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 update
void 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;不然还钱,返回false
private 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();
}
}
There is no optional box in front of the problem component
Unity–Why is the check box in front of the script in the Inspector view gone
? After changing the name of a parent class method, TweenPosition is missing.
The background is to trigger the parent node method of the status button to call the parent method ShowWindow of the status bar.
Now try to trigger the parent node method of the status button to call the parent method ShowWindow of the status bar, which can achieve the effect,
so the problem lies in the method of the parent node.
53-55 store system
56-63 Equipment System
The video is worn by clicking on the equipment in the backpack
Think of it, on the UI
01 the temporary Bag is on the left, and the equipment bar is on the right,
which is convenient to drag and drop to add equipment.
need:
01. Open the equipment bar, click on the part, hide the equipment bar, pop up the backpack bar, display the player's occupation type, the type of person's equipment for this part, and then click the equipment to realize wearing or
replacement
. is stored
kind
I think that there are more count attributes than Item, and there are groups of Groups.
The frame is the UI display used to make the prefab
process
(Refactoring) Disassemble data table and object table
The background is, click on the part slot in the equipment column to enter the backpack, and the backpack will display the items that belong to the equipment of this class and this part
It comes to mind that the data is grouped into one file. This data can be all types of item tables, equipment tables, medicine tables, equipment boss commodity tables, and drug boss commodity tables.
(code) original
Correspondingly, the addition and subtraction of the quantity also needs to update the backpack, so it is redundant
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);
}
(Code) Now, take out the display part and reuse it
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);
}
}
(Question) Add the first random item in the infinite loop of the first grid
The code of the example is in the Display method, and Display is exposed in Update, not under the condition of the left mouse button.
did not destroy the previous
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && _instance.isShow)//在背包打开的情况下点击
{
CreateNewItem(itemList);//克隆对象进背包
DisplayItem(itemGroupList);
}
}
Display again, without clearing the previous object list
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);
}
}
Click the equipment slot to display the equipment corresponding to the occupation and part (filter)
//从装备栏点击进来
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();
}
Left click to equip, or replace
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);//装备
}
The item prefab writing method passes the parameter id to BagPannel, which is called by the double-click action
public void OnItemGroupDubleClick()
{
BagPannel._instance.UseItemGroup(id);
}
take off
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;
}
}
The player double-clicks the EquipItem to pass the wear type to the equipment bar
public void UndressItemGroup()
{
EquipPannel._instance.UndressItemGroup(dressType);
}
In the equipment column, according to the type of wear, destroy the equipment on the corresponding part, roll back (add or add) the equipment to the backpack
public void UndressItemGroup(DressType dressType)
{
//销毁,传id
Transform 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.
A list is modified while enumerating it
(Problem) Bug in text tooltip
Assigns to the ontology, not to an object that receives the ontology. The error text box shows the value filled in by the prefab
ItemGroup itemGroup = go.GetComponent<ItemGroup>();
itemGroup.SetValue(item);
//正确
go.GetComponent<ItemGroup>().SetValue(item);
(Phenomenon) Set the kerning value of the font "Miscrosoft YaHei"
Drag a ttf font to unity, and this pops up very stuck for a long time