游戏开发之Unity-学习(一) —— Unity基础概念和实现井字棋
一、游戏对象与资源的区别和联系:
游戏对象是指游戏模型、音频、视频、UI文本、灯光等游戏中的对象,资源包括游戏对象,脚本文件、游戏字体、场景等。
二、资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
1. 资源的目录组织结构一般是:
Asserts
| - Animations
| - MainMenu
| - UI
| - Audio
| - Music
| - SFX
| - UI
| - Data
| - Agents
| - Alignments
| - Levels
| - Documentation
| - Fonts
| - Gizmos
| - Icon
| - Materials
| - Levels
| - Particles
| - Player
| - Projectiles
| - UI
| - Units
| - Models
| - Levels
| - Player
| - Projectiles
| - Units
| - Particles
| - Prefabs
| - Textures
| - PostProcessing
| - Prefabs
| - Audio
| - Enemies
| - Health
| - Managers
| - Player
| - UI
| - Scenes
| - Levels
| - MainMenu
| - Scripts
| - Core
| - Sprites
| - Textures
| - UI
2. 对象组织的结构
对象一般有玩家、敌人、环境、摄像机和音乐等虚拟父类,这些父节点本身没有实体,但它们的子类真正包含了游戏中会出现的对象。
三、用 debug 语句来验证 MonoBehaviour基本行为或事件触发的条件
Unity 相关函数执行顺序如下图所示:
四、查找脚本手册,了解 GameObject,Transform,Component 对象
- 分别翻译官方对三个对象的描述(Description)
- GameObject :
GameObjects are the fundamental objects in Unity that represent characters, props and scenery.
GameObjects是Unity中代表人物,道具和风景的基本对象 - Transform :
The Transform component determines the Position, Rotation, and Scale of each object in the scene
Transform 组件决定场景中每个对象的位置,旋转,和缩放。 - Component :
Base class for everything attached to GameObjects.
所有附加到GameObject的基类。
- GameObject :
table实体具有tag,Layer,Static,Transform等属性,这些属性均通过GameObject类的实例调用
一个标签是可以分配给一个或多个参考字GameObjects。例如,您可以为玩家控制角色定义“玩家”标签,为非玩家控制角色定义“敌人”标签。您可以使用“可收藏”标签定义玩家可以在场景中收集的物品。
标签可以帮助您识别GameObjects以进行脚本撰写。它们确保您无需使用拖放手动将GameObjects添加到脚本的暴露属性,从而在多个GameObjects中使用相同的脚本代码时节省时间。
标签对碰撞控制脚本中的触发器非常有用; 他们需要确定玩家是否与敌人,道具或收藏品互动。
您可以使用GameObject.FindWithTag()函数将GameObject设置为查找包含所需标记的任何对象来查找GameObject。
- Transform有位置,缩放,旋转等属性,这些属性在MonoBehaviour类里使用。Table的组件包括脚本,五个cube,Transform,渲染器等
五、整理相关学习资料,编写简单代码验证以下技术的实现:
- 查找对象:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
private void Start()
{
GameObject go = GameObject.Find("/Cube");
if(null != go)
Debug.Log("Find Cube");
}
}
- 添加子对象:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
private void Start()
{
GameObject go = GameObject.Find("/Cube");
GameObject newCube = GameObject.Find("/Cube/Cube");
GameObject newCubeInstance = Instantiate(newCube);
newCubeInstance.transform.parent = go.transform;
}
}
- 遍历对象树:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
private void Start()
{
foreach (Transform child in transform)
{
child.position += Vector3.up * 1.5F;
}
}
}
- 清除所有子对象:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private void Start()
{
foreach (Transform child in transform)
{
Destroy(child.gameObject);
}
}
}
六、资源预设(Prefabs)与 对象克隆 (clone)
- 预设(Prefabs)有什么好处
预设(prefab)是一个对象的快照或模板,可以用于快速生成相同的对象,比如子弹、敌人等等。修改预设以后,通过该预设生成的对象也会发生变化 - 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系
预设与克隆都能创建出相同的对象。预设创建出的对象与源预设依然有联系,后者的更改会影响到前者。但是克隆出的对象与源对象不再有联系。 - 制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
public Transform prefab;
private void Start()
{
Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
}
}
- 尝试解释组合模式(Composite Pattern / 一种设计模式)。使用 BroadcastMessage() 方法
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript1 : MonoBehaviour {
void ApplyDamage(float damage)
{
print(damage);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private void Start()
{
gameObject.BroadcastMessage("ApplyDamage", 5.0F);
}
void ApplyDamage(float damage)
{
print(damage);
}
}
七、实现井字棋
基于Unity 2017.3.1f1 (64-bit)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
private int count;
public Texture2D iconTrue;
public Texture2D iconFalse;
private int[] flag = { 0,0,0,0,0,0,0,0,0};
private bool isEnd,iseq;
private void Start()
{
count = 0;
isEnd = false;
iseq = false;
}
void OnGUI()
{
GUI.Label(new Rect(Screen.width / 2 - 25, Screen.height / 2 - 60 - 50, 50, 25), "井字棋");
if (GUI.Button(new Rect(Screen.width / 2 - 25, Screen.height / 2 - 60-25, 50,25),"重置"))
{
for (int i = 0; i < 9; ++i)
flag[i] = 0;
count = 0;
isEnd = false;
iseq = false;
}
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
{
if(flag[i*3+j] == 0)
{
if (GUI.Button(new Rect(Screen.width/2-60+(i * 40), Screen.height/2 - 60+(j * 40), 40, 40), "")&& !isEnd)
{
flag[i * 3 + j] = (count % 2) + 1;
count++;
}
}
else if(flag[i * 3 + j] == 1)
{
GUI.Button(new Rect(Screen.width/2 - 60+ (i * 40), Screen.height/2 - 60 + (j * 40), 40, 40), iconTrue);
}
else if(flag[i * 3 + j] == 2)
{
GUI.Button(new Rect(Screen.width/2 - 60+ (i * 40), Screen.height/2 - 60 + (j * 40), 40, 40), iconFalse);
}
}
}
for (int i = 0; i < 3; ++i)
{
if (flag[i*3]!=0&&flag[i * 3] == flag[i * 3 + 1] && flag[i * 3] == flag[i * 3 + 2])
{
isEnd = true;
GUI.Label(new Rect(Screen.width / 2 - 20, Screen.height / 2 + 60, 40, 40), new GUIContent(flag[i * 3] == 1 ? iconTrue : iconFalse));
}
}
for (int j = 0; j < 3; ++j)
{
if (flag[j]!=0&&flag[j] == flag[3 + j] && flag[j] == flag[6 + j])
{
isEnd = true;
GUI.Label(new Rect(Screen.width / 2 - 20, Screen.height / 2 + 60, 40, 40), new GUIContent(flag[j] == 1 ? iconTrue : iconFalse));
}
}
if(flag[4]!=0&&((flag[0]==flag[8]&&flag[0] == flag[4])||(flag[2] == flag[6] && flag[2] == flag[4])))
{
isEnd = true;
GUI.Label(new Rect(Screen.width / 2 - 20, Screen.height / 2 + 60, 40, 40), new GUIContent(flag[4] == 1 ? iconTrue : iconFalse));
}
if (isEnd&&!iseq)
GUI.Label(new Rect(Screen.width / 2 - 20, Screen.height / 2 + 100, 40, 40), "Win!");
for(int i=0;i<9; ++i)
{
if (flag[i] == 0)
{
iseq = false;
break;
}
else
iseq = true;
}
if(iseq&&!isEnd)
{
GUI.Label(new Rect(Screen.width / 2 - 20, Screen.height / 2 + 100, 40, 40),"Draw");
}
}
}