3d游戏编程与设计
目录
1、简答题
解释游戏对象(object)和资源(asset)的区别和联系
游戏对象是一个实体,能够承载其他游戏资源,是资源整合的具体表现。资源包含对象,除此之外,还有材质、场景、声音、贴图、脚本等,是能被游戏使用的任何东西。
下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
config:游戏配置
event:游戏事件
font:游戏字体
gameSequence:游戏序列
movie:游戏的视频文件
sound:游戏语音
sound_jp:游戏日语语音
title:游戏目录
具体而言就是asset目录下包含了很多游戏资源,包括字体,事件,脚本,语音,视频等
编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
-
基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
-
常用事件包括 OnGUI() OnDisable() OnEnable()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
Debug.Log("Starting...");
}
void Update()
{
Debug.Log("Updating...");
}
void Awake()
{
Debug.Log("Awaking...");
}
void FixedUpdate()
{
Debug.Log("FixedUpdating...");
}
void LateUpdate()
{
Debug.Log("LateUpdating...");
}
void OnGUI()
{
Debug.Log("In OnGUI");
}
void OnDisable()
{
Debug.Log("In OnDisable");
}
void OnEnable()
{
Debug.Log("In OnEnable");
}
}
结果如下:
查找脚本手册,了解 GameObject,Transform,Component 对象
- 分别翻译官方对三个对象的描述(Description)
GameObject:统一场景中所有实体的基类。
Tansform:物体的位置、旋转和比例。场景中的每个对象都有一个变换。它用于存储和操作对象的位置、旋转和缩放。每个变换都可以有一个父级,这允许您按层次应用位置、旋转和缩放。这是层次结构窗格中显示的层次结构。
Component:所有附加到游戏对象的基类。请注意,您的代码永远不会直接创建Component。而是编写脚本代码,并将脚本附加到游戏对象。
- 描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
本题目要求是把可视化图形编程界面与 Unity API 对应起来,当你在 Inspector 面板上每一个内容,应该知道对应 API。
例如:table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
table的属性
如图,第一个是Tag,指游戏实体的标签,用于高效查找游戏实体,第一个选择框对应CompareTag()方法。第二个是Layer,对应游戏实体所在的层,unity有8个层。
Transform属性
如图,第一个是position,表示该游戏实体和原点的相对位置;第二个是rotation,是表示旋转的变量;第三个是大小,表示游戏实体的相对大小。
其他Conponent
如图,还有四个conponent:
Mesh Filter,网格过滤器从资源中获取网格并将其传递到网格渲染器以在屏幕上渲染。
Mesh Renderer:网格渲染器从网格过滤器中获取几何图形,并将其渲染到GameObject的变换组件定义的位置。
Box Collider:盒形的原始对撞机。
Material:这个类公开材质的所有属性,允许您设置它们的动画。也可以使用它来设置无法通过检查器访问的自定义着色器属性(例如矩阵)。
- 用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)
资源预设(Prefabs)与 对象克隆 (clone)
- 预设(Prefabs)有什么好处?
如果我们每次都从基础游戏对象构建游戏,这需要很多代码,而且不易于修改。我们可以把基本的游戏对象组合起来,制作成预制,以后把预制当作一个游戏对象使用。预设可以看成游戏资源的模板,而且预设是相互关联的,当对预设进行更改时,这些更改将会作用于与之相连的所有实例。
- 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
行为相似,但是只有预设有关联性,即在修改预设时,与之相关所有实例会跟着修改。克隆则不会。
- 制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadBeh : MonoBehaviour
{
public GameObject prefab;
void Start()
{
Instantiate(prefab, new Vector3(0f, 0f, 0f), Quaternion.identity);
}
}
注意要将预制的table拖入脚本的prefab框
2、 编程实践,小游戏
游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
技术限制: 仅允许使用 IMGUI 构建 UI
作业目的:
-
了解 OnGUI() 事件,提升 debug 能力
-
提升阅读 API 文档能力
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UI : MonoBehaviour
{
public Texture2D piece1;
public Texture2D piece2;
public Texture2D backgound;
private int who_play;
private int who_win;
private int[,] matrix2D;
private int[] repent;
void OnGUI()
{
GUIStyle fontStyle = new GUIStyle();
fontStyle.normal.background = null;
fontStyle.normal.textColor = new Color(1, 1, 1);
fontStyle.fontSize = 20;
GUI.Label(new Rect(400, 200, 100, 100), "");
if (GUI.Button(new Rect(400, 0, 100, 100), "restart"))
Reset();
if (who_win == 0 && GUI.Button(new Rect(400, 100, 100, 100), "repent"))
Repent();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
if (matrix2D[i, j] == 1)
GUI.Button(new Rect(100 * i, 100 * j, 100, 100), piece1);
else if (matrix2D[i, j] == 2)
GUI.Button(new Rect(100 * i, 100 * j, 100, 100), piece2);
else
{
if (GUI.Button(new Rect(100 * i, 100 * j, 100, 100), backgound))
if(who_win == 0)
{
matrix2D[i, j] = 1 + who_play % 2;
repent[0] = i; repent[1] = j;
who_win = check();
who_play++;
}
}
}
}
if (who_win != 0)
{
GUI.Label(new Rect(400, 200, 100, 100), "player"+who_win+" wins!", fontStyle);
}
else
{
GUI.Label(new Rect(400, 200, 100, 100), "Playing...", fontStyle);
}
}
void Start()
{
Reset();
}
void Reset()
{
who_play = 0;
who_win = 0;
matrix2D = new int[3, 3]
{
{0,0,0},
{0,0,0},
{0,0,0}
};
repent = new int[2] { 0, 0 };
}
void Repent()
{
who_play++;
matrix2D[repent[0], repent[1]] = 0;
}
int check()
{
for (int i = 0; i < 3; i++)
{
if (matrix2D[i, 0] == matrix2D[i, 1] && matrix2D[i, 1] == matrix2D[i, 2] && matrix2D[i, 0] != 0)
return matrix2D[i, 0];
if (matrix2D[0, i] == matrix2D[1, i] && matrix2D[1, i] == matrix2D[2, i] && matrix2D[0, i] != 0)
return matrix2D[0, i];
}
if (matrix2D[0, 0] == matrix2D[1, 1] && matrix2D[1, 1] == matrix2D[2, 2])
return matrix2D[1, 1];
if (matrix2D[0, 2] == matrix2D[1, 1] && matrix2D[1, 1] == matrix2D[2, 0])
return matrix2D[1, 1];
return 0;
}
void Update()
{
}
}
运行效果如下图
注意,需要将配置贴图资源,需要设置棋子1,棋子2和背景的贴图。
见图