3D游戏设计 Unity
一、简答题
1.GameObject 和 Assets的区别和联系
-
是游戏中实实在在的游戏项目文件夹中所需要堆放的资源。比如,var obj = Resource.Load(“Prefabs/testItem”),这个obj就是Asset。
-
GameObject是游戏中实际使用的对象(就是你会在屏幕中实际看到的),是由Asset实例化后的对象。本质上其实还是Asset的衍变,是对部分Asset的引用和复制出来的新东西,其本质还是Asset。
2.资源目录的组织结构 and 游戏对象树的层次结构
(1)资源目录组织结构
- Resources(可动态加载的资源路径)
只读文件;资源全部打包发布;压缩打包;加密;Resoureces.Load方式加载 - Editor(存放编辑器的扩展脚本。)
所有资源文件或者脚本文件都不会被打进发布包中,并且脚本也只能在编辑时使用。
工具类的脚本放在这里,或者是一些编辑时用的DLL。 - Plugins (库)
如:SDK,第三方安装包,工具代码等等 - StreamingAssets (可动态加载的资源路径)
只读文件;资源全部打包发布;不压缩打包;不加密;WWW方式加载 - Scripts (存放脚本)
主要是C#代码 - Scenes (存放场景)
(2)游戏对象树层次结构
- 游戏对象是由组件Component组成的
- 游戏对象类似于一个容器,空的,通过添加各种组件从而组成特定的游戏对象
- 摄像机,光源等等都属于游戏对象。都有自己的游戏属性。
例子:
Transform
表示物体的变换,包括位置,旋转,缩放
Mesh Filter
指定物体的外观,外观变,模型不变(如果collider不变的话)
Mesh Renderer
如何渲染这个网格
Collider
如何让这个物体表现出来应用的物理(碰撞)效果
Rigidbody刚体物理组件
自由落体
Constant Force
添加某一方向上的恒力
3.用debug语句来验证MonoBehaviour基本行为或事件触发条件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour{
void Awake() {
Debug.Log("Awake");
}
void Start(){
Debug.Log("Start");
}
void Update(){
Debug.Log("Update");
}
void FixedUpdate(){
Debug.Log("FixedUpdate");
}
void LateUpdate(){
Debug.Log("LateUpdate");
}
void OnGUI(){
Debug.Log("OnGUI");
}
void OnDisable(){
Debug.Log("OnDisable");
}
void OnEnable(){
Debug.Log("OnEnable");
}
}
#### 4.了解GameObject,Transform,Component对象 (1) - **GameObject**:游戏中的每个对象(从角色和可收集物品到光源、摄像机和特效)都是游戏对象。游戏对象本身无法执行任何操作;需要向游戏对象提供属性,不同的组件组合,然后游戏对象才能成为角色、环境或特效。
- Transform:Transform 类提供多种方式来通过脚本处理游戏对象的位置、旋转和缩放,以及与父和子游戏对象的层级关系。
-Components:组件是在游戏对象(Game Object)中的实现某些功能的集合。
(2)
-
table的对象是GameObject,第一个选择框是activeSelf 属性,第二个选择框是对象名称,第三个选择框是static属性,第四个选择框是选项卡(Tag)属性,第五个选择框是层(Layer)属性,第六个选择框是预设 (Prefabs)属性table的Transform的属性有位置(Position)、旋转(Rotation)和规模(Scale)
-
UML图
-
资源预设(perfabs)和对象克隆(clone)
- 预设有什么好处:①模板功能:你可以在任何地方复用这个模型。这也是最常用的特征。
②一变百变:当场景中有很多由预制体生成的对象时,如果想修改他们的某个属性,无需一个一个的修改,只需要改其中的一个,当Apply提交后,所有的预制体分身,都会发生改变。
③代码控制:对于非系统提供的模型,只有制作成预制体的对象,才可以使用代码动态生成。否则只能在游戏发布之前一个一个的摆好了, 这显然不能满足游戏逻辑(比较子弹,就是动态生成的)。
- 预设与对象克隆关系:两者都能快速获取相同的游戏对象,区别在于预设是和场景中对应的游戏对象相链接的,当改变预设时,场景中的游戏对象属性也随之改变,而克隆不会改变。
- 以下代码将table预制资源实例化成为游戏对象
using System.Collections; using System.Collections.Generic; using UnityEngine; public class example : MonoBehaviour { public GameObject yuzhi; void Start() { GameObject instance = (GameObject)Instantiate(yuzhi, transform.position, transform.rotation); } }
- 预设有什么好处:①模板功能:你可以在任何地方复用这个模型。这也是最常用的特征。
···
5.井字棋的实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChessGame : MonoBehaviour {
private static int you;
private static int count;
private int win;
private int[,] chessBoard = new int[3, 3];
void Start () {
Init();
}
void OnGUI() {
GUI.Box(new Rect(210, 25, 300, 300), "");
if (GUI.Button(new Rect(310, 270, 100, 30), "Restart")) Init();
if (!GameOver()) { /* 迭代扫描 */
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (chessBoard[i, j] == 0 && GUI.Button(new Rect(255 + j * 70, 50 + i * 70, 70, 70), "")) {
PutChess(i,j);
}
else if (chessBoard[i, j] == 1) GUI.Button(new Rect(255 + j * 70, 50 + i * 70, 70, 70), "O");
else if (chessBoard[i, j] == 2) GUI.Button(new Rect(255 + j * 70, 50 + i * 70, 70, 70), "X");
}
}
}
else {
if (win != 0) // 弹框告诉结果
GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nCongratulations!\n Player "+win+" has won.");
else
GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\n\nThis is a draw!");
}
}
void Init() {
you = 1;
win = 0;
count = 0;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
chessBoard[i, j] = 0;
}
void PutChess(int i,int j) {
chessBoard[i, j] = you;
you = 3 - you;
count++;
}
bool GameOver() {
for(int i = 0; i < 3; i++) { // 判断结束
if (chessBoard[i, 0] != 0
&& chessBoard[i, 0] == chessBoard[i, 1] && chessBoard[i, 0] == chessBoard[i, 2]) win = chessBoard[i, 0];
if (chessBoard[0, i] != 0
&& chessBoard[0, i] == chessBoard[1, i] && chessBoard[0, i] == chessBoard[2, i]) win = chessBoard[0, i];
}
if (chessBoard[0, 0] != 0 && chessBoard[0, 0] == chessBoard[1, 1] && chessBoard[0, 0] == chessBoard[2, 2]) win = chessBoard[0, 0];
if (chessBoard[0, 2] != 0 && chessBoard[0, 2] == chessBoard[1, 1] && chessBoard[0, 2] == chessBoard[2, 0]) win = chessBoard[0, 2];
if (count < 9 && win == 0) return false;
return true;
}
}