Unity3d课后练习(二)


1. 简答题

· 解释游戏对象(GameObjects) 和 资源(Assets)的区别与联系。

游戏对象(GameObject)是Unity场景里面所有实体的基类.,可以用来创建对象实例,使用者可以在Inspector界面调整对象实例的属性。对象实例可以直接出现在场景中,可以按照一定的层次结构组织起来。对象是组件(Component)的容器。

资源(Assets就是我们在Unity项目中可以直接使用的文件,包括图像、视频、脚本文件、预制文件等,它们会按照文件类型放到不同的文件夹,通过文件夹的形式来组织。资源的存在不依赖于Unity项目。

二者的区别:游戏对象是游戏中的概念,依赖于Unity项目;而大部分游戏资源是来自外部的文件,仅作为游戏对象的组成部分(比如模型、动画、音乐等)。
二者的联系:对象可以保存为资源,资源可以用来创建对象,一个资源可以创建多个对象。


· 下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
在Asset Store中,下载免费3D游戏案例Nature Starter Kit 2:
在这里插入图片描述

资源的根目录下,有Animations、Editor、Materials、Nature、Scene、Standard Assets、Textures七个目录以及info文件;Point light、Terrain、Trees等游戏对象是处于同一层次的,而Trees又有多个子对象,包括多种tree和bush。
总结:资源是按照文件夹的形式来组织的,根目录一般是各种类型的资源目录以及说明文件,各资源目录下则是该类型的资源文件。游戏对象树由对象之间的父子关系构成的,父亲对象作为根节点,孩子对象作为子节点。


· 编写一个代码,使用debug语句来验证 MonoBehaviour 基本行为或事件触发的条件。
其中,基本行为包括Awake() Start() Update() FixedUpdate() LateUpdate()
基本事件包括OnGUI() OnDisable() OnEnable()

根据官方文档,上述基本行为或事件的触发条件为:
Awake() 在脚本实例被加载时即被调用
Start() 仅在Update函数第一次被调用前调用
Update() 每一帧触发一次
FixedUpdate() 在自设定的帧频下,每一帧触发一次
LateUpdate() 当Behaviour是enabled的情况下,在所有Update函数调用后被调用
OnGUI() 当渲染和处理GUI事件时被调用
OnDisable() 当行为变得无效的时候被调用
OnEnable() 当对象启用并激活的时候被调用

回到SampleScene项目中,新建3D对象Cube,并给它添加C#脚本,代码如下:

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");  
  }
}

运行结果如下:


在这里插入图片描述


· 查找脚本手册,了解GameObject,Transform,Component对象
(1) 分别翻译官方对三个对象的描述(Description)
GameObject:

The GameObject is the most important concept in the Unity Editor.
Every object in your game is a GameObject, from characters and collectible items to lights, cameras
and special effects. However, a GameObject can’t do anything on its own; you need to give it properties before it can become a character, an environment, or a special effect.
You can think of a GameObject as an empty cooking pot, and components as different ingredients that make up the recipe of your game.

GameObject是Unity Editor中最重要的概念。
游戏中的每个对象都是GameObject,从角色和收藏品到灯光,相机和特效。
 但是,GameObject本身无法做任何事情; 您需要先赋予它属性才能成为一个角色,一个环境或一个特殊的效果。
您可以将GameObject视为一个空的烹饪锅,并将组件视为构成游戏配方的不同成分。

Transform

The Transform is used to store a GameObject’s position, rotation, scale and parenting state and is thus very important. A GameObject will always have a Transform component attached - it is not possible to remove a Transform or to create a GameObject without one.

Transform用于存储GameObject的位置,旋转,缩放和父亲状态,因此非常重要。 
GameObject将始终附加一个Transform组件 - 
无法删除该组件或创建没有该组件的GameObject。

Component

Components are the nuts & bolts of objects and behaviors in a game. They are the functional pieces of every GameObject.
A GameObject is a container for many different Components. By default, all GameObjects automatically have a Transform Component. This is because the Transform dictates where the GameObject is located, and how it is rotated and scaled. Without a Transform Component, the GameObject wouldn’t have a location in the world.
Even empty GameObjects have a Transform Component
Remember that you can always use the Inspector to see which Components are attached to the selected GameObject. As Components are added and removed, the Inspector will always show you which ones are currently attached. You will use the Inspector to change all the properties of any Component (including scripts).

组件是游戏中对象和行为的基本要素。 它们是每个GameObject的功能部分。
GameObject是许多不同组件的容器。 默认情况下,所有GameObjects都自动拥有一个Transform Component。 
这是因为Transform指示了GameObject的位置,以及它是如何旋转和缩放的。 
如果没有变换组件,GameObject将没有世界上的位置。
即使是空的GameObject也有一个Transform Component
请记住,您始终可以使用Inspector查看哪些组件附加到选定的GameObject。 
随着组件的添加和删除,Inspector将始终显示当前连接的组件。 您将使用Inspector更改任何Component(包括脚本)的所有属性。

(2) 描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件

table对象的属性:activeInHierarchy(表示GameObject是否在场景中处于active状态)、activeSelf(GameObject的本地活动状态)、isStatic(仅编辑器API,指定游戏对象是否为静态)、layer(游戏对象所在的图层)、scene(游戏对象所属的场景)、tag(游戏对象的标签)、transform(游戏对象的转换,最常见的部件)
table的Transform的属性:Position、Rotation、Scale
table的部件有:Mesh Filter、Box Collider、Mesh Renderer


(3) 用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)


· 整理相关学习资料,编写简单代码验证以下技术的实现:
(1) 查找对象
通过名字查找:

public static GameObject Find(string name)

例:创建Cube对象cube1,标签为Finish:

查找代码:

 GameObject tmp = GameObject.Find("cube1");
 Debug.Log(tmp.name);

输出:


通过标签查找:

public static GameObject FindWithTag(string tag))

查找代码:

GameObject tmp = GameObject.FindGameObjectWithTag("Finish");
Debug.Log(tmp.name+"000");

输出:


通过类别查找:

public static FindObjectOfType(System.Type type)

注:上述查找方式,也可一次查找多个对象。

(2) 添加子对象
代码:

 GameObject cube = GameObject.Find("cube1");
 GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
 obj.transform.position = new Vector3(0, -2, 0);
 obj.name = "cube2";
 obj.transform.parent = cube.transform;

发现cube1多了一个子对象cube2:
在这里插入图片描述

(3) 遍历对象树

foreach (Transform child in transform) {
  Debug.Log(child.gameObject.name);
}

(4) 清除所有子对象

foreach (Transform child in transform) {
Destroy(child.gameObject);
}

· 资源预设(Prefabs)与 对象克隆 (clone)
(1) 预设(Prefabs)有什么好处?

Unity的Prefab系统允许用户创建,配置和存储GameObject及其所有组件,属性值和子GameObjects作为可重用资源。预设资产充当模板,用户可以在该模板中在场景中创建新的预设实例。
如果要重新使用以特定方式配置的GameObject(如非玩家角色(NPC),道具或场景 - 在场景中的多个位置或项目中的多个场景中),则应将其转换为预设。这比简单地复制和粘贴GameObject要好,因为Prefab系统允许用户自动保持所有副本同步。
用户对Prefab资产所做的任何编辑都会自动反映在该预制件的实例中,使用户可以轻松地对整个项目进行广泛的更改,而无需对资产的每个副本重复进行相同的编辑。

(2) 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?

预设和克隆的作用都是通过复制产生对象,区别是:预设的对象是统一的,“牵一发而动全身”;而克隆的对象是互不影响的,修改一个并不会影响到另一个。

(3) 制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象

void Start () {  
    GameObject anotherTable = (GameObject)Instantiate(table.gameObject);  
} 

2. 编程实践,小游戏

· 游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
· 技术限制:仅允许使用IMGUI构建UI
· 作业目的:提升debug能力;提升阅读API文档能力

我完成的是一款简单的“数字华容道”,具体见Github传送门


3. 思考题【选做】

· 微软XNA 引擎的 Game 对象屏蔽了游戏循环的细节,并使用一组虚方法让继承者完成它们,我们称这种设计为“模板方法模式”。 为什么是“模板方法”模式而不是“策略模式”呢?

模板方法模式:定义一个算法流程,将一些特定步骤的具体实现、延迟到子类。使得可以在不改变算法流程的情况下,通过不同的子类、来实现“定制”流程中的特定的步骤。
策略模式:使不同的算法可以被相互替换,而不影响客户端的使用。
微软XNA只是给出了虚方法,等待子类实现,而不是给出现成的算法,所以是“模板方法模式”而不是“策略模式”。


· 将游戏对象组成树型结构,每个节点都是游戏对象(或数)。
(1) 尝试解释组合模式(Composite Pattern / 一种设计模式)。
(2) 使用 BroadcastMessage() 方法,向子对象发送消息。你能写出 BroadcastMessage() 的伪代码吗?

组合模式(Composite Pattern),又叫部分整体模式,允许用户将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以一致的方式处理单个对象以及对象的组合。它创建了对象组的树形结构,创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

void Start () {
		this.BroadcastMessage("Message");
}

void Message(){
		Debug.Log("Hello!");
}

· 一个游戏对象用许多部件描述不同方面的特征。我们设计坦克(Tank)游戏对象不是继承于GameObject对象,而是 GameObject 添加一组行为部件(Component)。
(1) 这是什么设计模式?

装饰器模式。

(2) 为什么不用继承设计特殊的游戏对象?

装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。它是作为现有的类的一个包装,创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
而继承则限制了系统的灵活性,增强了耦合,因为继承是侵入式的,子类必须拥有父类的所有方法和属性。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值