中山大学3D游戏作业2
一、简答题
1. 解释游戏对象和资源的联系和区别
首先看看官方对它们的解释:
游戏对象(GameObjects):GameObjects are fundamental objects in Unity that represent characters, props, scenery, and more. Every object in your game is a GameObject.GameObjects live in 3D environments called scenes. You can think of a scene as a game level, but it might also represent a menu, the credits at the end of the game or something else entirely.
资源(Assets):An asset is representation of any item that can be used in your game or project. An asset may come from a file created outside of Unity, such as a 3D model, an audio file, an image, or any of the other types of file that Unity supports. There are also some asset types that can be created within Unity, such as an Animator Controller, an Audio Mixer or a Render Textu。
区别:游戏对象是游戏中真实存在物体,是一个可以进行选中操作的对象,每个对象本身没法执行任何操作,它们需要人工提供属性才能发挥作用。而资源则是对游戏对象的修饰,在游戏中会用到的东西,例如图片、声音文件等。
联系:游戏对象可以被资源作为模板用来具体实例化,资源可以成为游戏对象中的某种属性,还能被多个游戏对象同时使用。
2.下载几个游戏案例,总结资源、对象组织的结构。
在github仓库上,我下载了一款类似“皇室战争”的卡牌塔防游戏,仓库地址:https://github.com/zhxhxlzt/MiniCar
下面我们对资源和对象进行分析:
可以清楚地看见,游戏对象形成树状结构,有就形成了我们所说的“对象树”。每个对象有若干个子对象,每个子对象又有若干的小子对象。
3.编写代码使用debug语句验证MonoBehaviour基本行为或事件触发条件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class simple : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("开始测试");
}
void Update()
{
Debug.Log("Updating...");
}
void Awake()
{
Debug.Log("Awaking...");
}
void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
void LateUpdate()
{
Debug.Log("LateUpdate");
}
void OnGUI()
{
Debug.Log("OnGUI");
}
void OnDisable()
{
Debug.Log("Disable");
}
void OnEnable()
{
Debug.Log("OnEnable");
}
// Update is called once per frame
/*
void Update()
{
float speed = 3;
float distance = speed * Time.deltaTime;
Vector3 pos = this.transform.localPosition;
pos.x += distance;
this.transform.localPosition = pos;
}
*/
}
4.查找脚本手册了解GameObject,Transform,Component对象。
GameObject: Unity 场景中所有实体的基类。
注意:游戏对象类中的许多变量已被删除。要访问,例如 csharp 中的游戏对象渲染器,请改用获取组件 。
Component: 附加到 GameObject 的所有内容的基本类。
注意,您的代码不会直接创建 Component,而是您编写脚本代码,然后将该脚本附加到 GameObject。 另请参阅:ScriptableObject,通过它可创建不附加到任何 GameObject 的脚本。
Transform:对象的位置、旋转和缩放。
场景中的每个对象都有一个变换。 它用于存储和操作对象的位置、旋转和缩放。 每个变换都可以有一个父级,让您能够分层应用位置、旋转和缩放。
5.资源预设与对象克隆
-
预设有什么好处?
预设可以看成游戏资源的模板。构建游戏的时候,若我们每次都直接从基础游戏对象开始构建是非常麻烦费时的,而且不易于后续修改。我们可以把基本游戏对象整合起来,形成预制,把预制当作一个游戏对象来使用。预设是相互关联的,当对预设发生更新时,之相连的所有实例也会更新。 -
预设与对象克隆有什么关系?
它们具有相似的行为。修改预设时,预设的副本也会发生变化。修改克隆对象时,其副本是独立于被克隆的对象,不会发生变化。
public GameObject table;
void Start()
{
GameObject instance = (GameObject)Instantiate(table, transform.position, transform.rotation);
}
void Update() { }
二、井字棋
1. 源代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mychess : MonoBehaviour
{
private int[,] grade = new int[3, 3];
private int xlong = 300;
private int ylong = 80;
private int turn;
private bool isEnd = false;
private bool isequal = false;
void Start()
{
init();
}
void OnGUI()
{
GUI.backgroundColor = Color.yellow;
GUI.color = Color.green;
if (GUI.Button(new Rect(25 + xlong, 170 + ylong, 100, 50), "Restart"))
{
init();
return;
}
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
{
if (grade[i, j] == 0)
{
if (GUI.Button(new Rect(i * 50 + xlong, j * 50 + ylong, 50, 50), ""))
changeturn(i, j);
}
else if (grade[i, j] == 1)
{
if (GUI.Button(new Rect(i * 50 + xlong, j * 50 + ylong, 50, 50), "O"))
changeturn(i, j);
}
else if (grade[i, j] == 2)
{
if (GUI.Button(new Rect(i * 50 + xlong, j * 50 + ylong, 50, 50), "X"))
changeturn(i, j);
}
}
GUI.color = Color.red;
if (isequal){
GUI.Label(new Rect(xlong, 160 + ylong, 200, 100), "equally,game over");
init();
}
else if (isEnd)
{
char winner;
if (turn == 2)
{
winner = 'O';
}
else winner = 'X';
GUI.Label(new Rect(xlong-100, 100 + ylong, 200, 100), winner + " win! ");
}
}
void winnerCheck(int x, int y)
{
if (grade[x, 0] == grade[x, 1] && grade[x, 1] == grade[x, 2] || grade[0, y] == grade[1, y] && grade[1, y] == grade[2, y])
{
isEnd = true;
return;
}
bool tmp = true;
for (int i = 0; i < 3; i++)
{
if (grade[i, i] != grade[x, y]) {
tmp = false;
break;
}
}
if (tmp == true)
{
isEnd = true;
return;
}
tmp = true;
for (int i = 2; i > -1; i--)
{
if (grade[2 - i, i] != grade[x, y]) tmp = false;
}
if (tmp == true)
{
isEnd = true;
return;
}
tmp = true;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; ++j)
{
if (grade[i, j] == 0)
tmp = false;
}
if (tmp)
{
isEnd = true;
isequal = true;
return;
}
}
void changeturn(int x, int y)
{
if (grade[x, y] == 0 && !isEnd)
{
grade[x, y] = turn;
winnerCheck(x, y);
if (turn == 1)
{
turn = 2;
}
else turn = 1;
}
}
void init()
{
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
{
grade[i, j] = 0;
turn = 1;
}
}
}
2. 运行效果
总结
本次作业为第一次实际编程作业,难度不大,通过上述学习可以初步掌握MonoBehaviour、预制等知识,并成功实现了第一个游戏程序“井字棋”,学会了编写start()、update()、OnGui()等函数。