前言
这是专选课3D游戏编程与设计的第二次作业,包括简答题和用unity制作一个小游戏。如有错误,欢迎并感谢指正。
简答题
游戏对象(GameObjects)和资源(Assets)的区别和联系
游戏对象:指Unity中代表人物、道具或场景的基本对象是一个可以容纳各类组件(Component)以实现各类功能的容器。
资源指的是在项目中可能用到的各种资源文件,比如模型、声音文件、贴图文件等等。
区别:游戏对象是游戏运行时存在的对象,而assets时制作游戏时工作区中可以利用的资源。
联系:我们可以用资源创建游戏对象,资源可以是我们实例化具体的游戏对象的模板,也可以作为游戏对象中的某种属性,被多个游戏对象同时使用。
游戏案例分析
资源的目录组织结构:功能类似的资源被放置在同一目录下
游戏对象树的层次结构:游戏对象之间可以为父或子的关系,整体呈树状结构。
编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class intbesh : MonoBehaviour {
private void Awake()
{
Debug.Log("awake!");
}
void Start () {
Debug.Log("start!");
}
void Update () {
Debug.Log("update!");
}
private void FixedUpdate()
{
Debug.Log("fixedupdate!");
}
private void OnGUI()
{
Debug.Log("ONGUI!");
}
private void OnDisable()
{
Debug.Log("OnDisable!");
}
private void OnEnable()
{
Debug.Log("OnEnable!");
}
}
控制台因为update输出太多就不展示了,总结如下:
- Start:第一次进入游戏循环时调用
- Update:行为启用时,每一帧调用update
- Awake:当一个脚本实例被载入时
- FixedUpdate:行为启用时,每一时间片调用
- OnGUI:渲染和处理GUI事件时调用
- OnEnable:当对象变为可用或激活状态时被调用
- OnDisable:当对象变为不可用或非激活状态时调用
查找脚本手册,了解 GameObject,Transform,Component 对象
分别翻译官方对三个对象的描述(Description)
GameObject是Unity中的基本对象,代表人物,道具和游戏场景。它们本身并实现很多东西,但它们可以充当组件的容器,由此实现了真正的功能。
Transform组件决定场景中每个对象的位置,旋转和缩放比例。每个GameObject都有一个Transform。
Component是游戏中对象和行为的细节。它们是每个GameObject的功能部分。
描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
table对象的属性:name、activeSelf(GameObject的本地活动状态)、isStatic、layer(游戏对象所在的图层。)、tag(游戏对象的标签)
table的Transform的属性有:Position、Rotation、Scale
table的部件有:Mesh Filter、Mesh Renderer、Box Collider、First Beh
资源预设(Prefabs)与 对象克隆 (clone)
预设(Prefabs)有什么好处?
预设可以快速创建具有相同属性的对象,修改预设属性可以同时修改所有对应实例,提高效率
预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
对象克隆的实例之间不会相互影响,但对预设进行修改会作用到该预设所有的实例上。
制作 table 预设,写一段代码将 table 预制资源实例化成游戏对象
public class FirstBeh : MonoBehaviour {
public GameObject table;
void Awake()
{
Debug.Log("awake!");
}
void Start () {
Debug.Log("Start");
GameObject aTable = (GameObject)Instantiate(table.gameObject);
aTable.name = "newTable";
aTable.transform.position = new Vector3(0,Random.Range(0,5),0);
aTable.transform.parent = this.transform;
}
void Update () {
//Debug.Log("Init Update");
}
}
编程实践:井字棋小游戏
写一个c#脚本,挂载到摄像机上即可
脚本代码如下:
using UnityEngine;
using System.Collections;
public class TTT : MonoBehaviour {
//用二位数组存棋盘,0代表空,1代表O,2代表O
private int[,] chess = new int[3,3] {
{
0,0,0},{
0,0,0},{
0,0,0}};
//0是O的回合,1是X的回合
private int turn = 0;
private int res=0;
void Start () {
}
//OnGUI会自动刷新
void OnGUI() {
//x,y,w,h
if (GUI.Button(new Rect(310,300,100,50),"重新开始")) reset();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (chess [i,j] == 1) {
GUI.Button (new Rect (70 * i+250, 70 * j, 70, 70), "O");
Debug.Log(i+" "+j+":"+chess[i,j]);
res=check();
Debug.Log(res);
} else if (chess [i,j] == 2) {
GUI.Button (new Rect (70 * i+250, 70 * j, 70, 70), "X");
Debug.Log(i+" "+j+":"+chess[i,j]);
res=check();
Debug.Log(res);
} else {
if (GUI.Button (new Rect (70 * i+250, 70 * j, 70, 70), "")) {
if (res == 0) {
if (turn == 0) {
chess [i, j] = 1;
turn = 1;
} else {
chess [i, j] = 2;
turn = 0;
}
}
}
}
}
}
res = check();
if (res == 1) {
GUI.Label (new Rect (340, 230, 100, 50), "O赢");
} else if (res == 2) {
GUI.Label (new Rect (340, 230, 100, 50), "X赢");
} else if(res==3){
GUI.Label (new Rect (340, 230, 100, 50), "平局");
} else{
if(turn==0) GUI.Label (new Rect (335, 230, 100, 50), "O的回合");
else GUI.Label (new Rect (335, 230, 100, 50), "X的回合");
}
}
void reset() {
//重开置空
turn=0;
res=0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
chess [i,j] = 0;
}
}
turn = 0;
}
int check() {
//检查行
for (int i = 0; i < 3; i++) {
if (chess[i,0]!=0&&chess [i,0] == chess [i,1] && chess [i,1] == chess [i,2]) {
return chess [i,0];
}
}
//检查列
for (int j = 0; j < 3; j++) {
if (chess[0,j]!=0&&chess [0,j] == chess [1,j] && chess [1,j] == chess [2,j]) {
return chess [0,j];
}
}
//检查对角线
if ((chess[0,0]!=0&&chess [0, 0] == chess [1, 1] && chess [1, 1] == chess [2, 2]) ||
(chess[0,2]!=0&&chess [0, 2] == chess [1, 1] && chess [1, 1] == chess [2, 0])) {
return chess [1, 1];
}
//检查满
int count = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (chess [i, j] != 0)
count++;
}
}
if(count==9)return 3;
return 0;
}
}
效果如下