简答题
1、 解释游戏对象(GameObjects)和资源(Assets)的区别与联系。
- 游戏对象(GameObject)是Unity 场景中所有实体的基类。
- 资源(Asset)表示 Unity 项目中用来创建游戏或应用的任何项。资源可以代表项目中的视觉或音频元素,例如 3D 模型、纹理、精灵、音效或音乐。资源还可以表示更抽象的项目,例如任何用途的颜色渐变、动画遮罩或任意文本或数字数据。
资源可能来自 Unity 外部创建的文件,例如 3D 模型、音频文件、图像。还可以在 Unity 编辑器中创建一些资源类型,例如 ProBuilder 网格 (ProBuilder Mesh)、Animator Controller、混音器 (Audio Mixer) 或渲染纹理 (Render Texture)。
区别与联系: 游戏对象是游戏场景中动态存在的实例,而资源以静态文件形式存在于项目中。游戏对象可以从资源派生而来,并可以持有对资源的引用。
2、下载游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
参考自该3D滚球游戏github开源案例:https://github.com/AlphaaeStudio/RollABall
资源目录组织:
├─Materials # 材质
├─Prefabs # 预设
├─Scenes # 场景
├─Scripts # 精灵(2D图形)
├─StreamingAssets 流式资源
└─TextMesh Pro
├─Documentation # 文档
├─Fonts # 字体
├─Resources # 资源文件
│ ├─Fonts & Materials # 字体和材质
│ ├─Sprite Assets # 精灵资源
│ └─Style Sheets # 风格
├─Shaders # 着色器
└─Sprites # 精灵
游戏对象树层次结构:
3、编写一个代码,使用debug语句来验证MonoBehaviour基本行为或事件触发的条件
- 基本行为包括Awake() Start() Update() FixedUpdate() LateUpdate()
- 常用事件包括OnGuI() OnDisable() OnEnable()
创建C#脚本文件:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("Start");
}
// Update is called once per frame
void Update()
{
Debug.Log("Update");
}
private void Awake()
{
Debug.Log("Awake");
}
private void FixedUpdate()
{
Debug.Log("Fixedupdate");
}
private void OnGUI()
{
Debug.Log("ONGUI");
}
private void OnDisable()
{
Debug.Log("OnDisable");
}
private void OnEnable()
{
Debug.Log("OnEnable");
}
}
将其拖入任意一个游戏对象的组件中,运行游戏,观察控制台输出的日志信息:
4、 查找脚本手册,了解GameObject,Transform,Component 对象
分别翻译官方对三个对象的描述(Description)
- GameObject是Unity 场景中所有实体的基类。
- Transform是描述游戏对象的位置、旋转和缩放的组件。场景中的每个游戏对象都有一个Transform。 它用于存储和操作对象的位置、旋转和缩放。 每个Transform都可以有一个父级,能够用于分层应用位置、旋转和缩放。
- Component是附加到 GameObject 的所有内容的基本类。
描述下图中 table对象(实体)的属性、table的Transform的属性、 table 的部件
activeSelf: 第一个复选框,表示是否启用
Transform:位置、旋转以及放缩组件
Component:附加在游戏对象上的组件
Script:脚本组件
用UML图描述三者的关系(请使用UMLet 14.1.1 stand-alone版本出图)
资源预设(Prefabs)与对象克隆(clone)
预设是可用于将相同属性设置跨多个组件、资源或项目设置窗口保存和应用的资源。您还可以使用预设在预设管理器中指定新组件的默认设置和资源的默认导入设置。 预设管理器支持您添加到 Unity 编辑器的任何导入器、组件或脚本化对象。
- 预设(Prefabs)有什么好处?
可以将游戏对象保存为prefabs资源,方便地派生和引用。
- 预设与对象克隆(clone or copy or Instantiate of Unity Object)关系?。制作table 预制,写一段代码将 table 预制资源实例化成游戏对象
预设派生出的游戏对象持有对预设的引用,此时对预设的修改会影响所有派生对象的缺省值。而游戏对象克隆后产生的对象是独立的对象。
创建以下脚本拖入任意游戏对象中:
public class NewBehaviourScript : MonoBehaviour
{
public GameObject table;
// Start is called before the first frame update
void Start()
{
Debug.Log("Start");
Instantiate<GameObject>(table as GameObject, new Vector3(0,0,0), new Quaternion(0,0,0,0));
}
}
并将table预制对象拖入table变量赋值,随后运行游戏,观察到桌子成功生成:
实践:简单计算器
利用GUI和GUILayout实现简单的计算器,支持整数的加减乘运算,以及清空、退格操作。
代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Calculator : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
private long now = 0;
private long res = 0;
private void button(int i)
{
if (GUILayout.Button(Convert.ToString(i), GUILayout.Height(80)))
{
now *= 10;
now += i;
}
}
void OnGUI()
{
GUI.Box(new Rect(0, 0, 800, 600), "计算器");
GUI.TextField(new Rect(10, 25, 780, 50), Convert.ToString(now) + '\n' + res);
GUILayout.BeginArea(new Rect(10, 100, 780, 80));
GUILayout.BeginHorizontal();
button(7);
button(8);
button(9);
GUILayout.EndHorizontal();
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(10, 100 + 90, 780, 80));
GUILayout.BeginHorizontal();
button(4);
button(5);
button(6);
GUILayout.EndHorizontal();
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(10, 100 + 90 * 2, 780, 80));
GUILayout.BeginHorizontal();
button(1);
button(2);
button(3);
GUILayout.EndHorizontal();
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(10, 100 + 90 * 3, 780, 80));
GUILayout.BeginHorizontal();
button(0);
if (GUILayout.Button("C", GUILayout.Height(80)))
{
now = 0;
}
if(GUILayout.Button("<-", GUILayout.Height(80)))
{
now /= 10;
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(10, 100 + 90 * 4, 780, 80));
GUILayout.BeginHorizontal();
if (GUILayout.Button("+", GUILayout.Height(80)))
{
res += now;
now = 0;
}
if (GUILayout.Button("-", GUILayout.Height(80)))
{
res -= now;
now = 0;
}
if (GUILayout.Button("*", GUILayout.Height(80)))
{
res *= now;
now = 0;
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
// Update is called once per frame
void Update()
{
}
}