Unity官方教程1——Playground学习记录

文章链接

Unity

Unity编辑器

属性

  • AddComponentMenu,通过该属性,可以在Unity的Component菜单下添加子菜单;
  • AssemblyIsEditorAssembly,程序集级别的属性,具有该属性的程序集中的任何类都将被视为编辑器类;
  • MenuItem,通过该属性,可以在Unity的菜单栏上添加菜单项;
  • SerializeField,强制Unity对脚本的私有字段进行序列化(Unity对脚本进行序列化时,仅对公共非静态的字段进行序列化,如果需要序列化私有非静态字段,则需要用SerializeField属性来指定);
  • TooltipAttribute,通过该属性,可以在Inspector窗口中为组件的属性指定工具提示(鼠标悬停在上面会有一个工具气泡提示);
  • DisallowMultipleComponent,通过该属性,可以防止将相同类型(或子类型)的 MonoBehaviour 多次添加到 GameObject;

精灵

在2D工作控件中,精灵的实质就是2D图形对象,在3D控件中,精灵的实质就是标准纹理,精灵不同于纹理的地方在于可以通过一些特殊技巧在开发过程中组合和管理精灵纹理从而达到提高效率和方便性的目的。

刚体(RigidBody2D)的四个属性:

  • Mass,质量,物体的质量
  • Friction, 摩擦力,摩擦力越大,物体运动的阻力越大
  • Angular Friction,
  • Gravity,重力,重力为0是GameObject不会掉下来;

MonoBehaviour

Unity 脚本的基类,继承它的脚本才能被作为组件加入到GameObject中,同时它还提供了基本的事件回调。除此之外:

1. Coroutines,MonoBehaviour允许开启、停止和管理协程;
 2. Events,提供了一个事件集合,可以根据具体回调的时机选择执行相应的脚步代码
     1. Start,当GameObject开始存在于场景中,或者GameObject开始实例化时。
     2. Update,每一帧都会调用
     3. FixedUpdate,每一个物理时间段都为调用,调用频率低于Update
     4. OnBecameVisible 和 OnBecameInvisible,当游戏对象的渲染器进入或离开摄像机视图时回调
     5. OnCollisionEnter 和 OnTriggerEnter,碰撞进入或者触发器进入时回调
     6. OnDestroy,游戏对象被销毁时回调

Playground简介

Playground包含的内容:

  1. 5个完整的小游戏示例;

  2. 上面5个小游戏示例所需要的图片资源(精灵)

  3. 上面5个小游戏中用到的预制件(Prefab),包括角色预制件和粒子效果预制件;

  4. 包含了四种类型的脚本,分别是:

    1. Attributes脚本

    2. Conditions脚本

    3. GamePlay脚本

    4. MoveMent脚本

问题

  1. 问:Maze游戏新建关卡时,先添加背景图片,然后添加砖块,但砖块被背景图片遮挡住了

    答:注意场景中层的概念,图片精灵添加到场景中后,除了每个组件都会有的Transform组件,还会生成一个SpriteRender组件,同时还会多出一个Additional Setting选项,这里面可以设置它在场景中的层级,值越小,越在下面,所以只要把砖块的层级设置的比背景的大就可以了。

  2. 问:Maze游戏中,触碰到旗子后如何进行场景的切换的

    答: 采用了Condition Area组件,然后在组件中执行EndOfLevelGameplayAction

  3. 问: UserInterface(游戏界面)的UI层级是如何保证的?

    答:

  4. 问:为关卡添加背景音效?

    答:添加背景音效

什么是Condition Area组件?

即条件判定区域组件,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using UnityEngine;
using System.Collections;
using UnityEngine.Events;

[AddComponentMenu("Playground/Conditions/Condition Area")]
public class ConditionArea : ConditionBase
{
// the amount of times (in seconds) that this Condition will call OnTriggerStay
// i.e. if it's 1, it means that OnTriggerStay will be called every second
// i.e. if it's 4, it means that it will be called every 4 seconds
// ... and so on...
public float frequency = 1f;
//not used in case of ColliderEventTypes.Enter and ColliderEventTypes.Exit


//the type of event to check for
[Header("Type of Event")]
public ColliderEventTypes eventType = ColliderEventTypes.Enter;

private float lastTimeTriggerStayCalled;

// This function will be called at the beginning
void Start()
{
lastTimeTriggerStayCalled = -frequency;
}

//This will create a dialog window asking for which dialog to add
private void Reset()
{
Utils.Collider2DDialogWindow(this.gameObject, true);
}

//this function is called every time another collider enters this trigger
private void OnTriggerEnter2D(Collider2D otherCollider)
{
//is this the type of event we need?
if(eventType == ColliderEventTypes.Enter)
{
//check for the tag of the object which entered the area, if necessary
if(otherCollider.CompareTag(filterTag) || !filterByTag)
{
ExecuteAllActions(otherCollider.gameObject);
}
}
}

// This will be called EVERY FRAME when something stays inside the trigger collider
void OnTriggerStay2D(Collider2D otherCollider)
{
//is this the type of event we need?
if(eventType == ColliderEventTypes.StayInside
&& Time.time >= lastTimeTriggerStayCalled + frequency) //check also the frequency
{
//check for the tag of the object which entered the area, if necessary
if(otherCollider.CompareTag(filterTag) || !filterByTag)
{
ExecuteAllActions(otherCollider.gameObject);
lastTimeTriggerStayCalled = Time.time;
}
}
}

//this function is called every time another collider exits this trigger
private void OnTriggerExit2D(Collider2D otherCollider)
{
//is this the type of event we need?
if(eventType == ColliderEventTypes.Exit)
{

//check for the tag of the object which entered the area, if necessary
if(otherCollider.CompareTag(filterTag)
|| !filterByTag)
{
ExecuteAllActions(otherCollider.gameObject);
}
}
}

public enum ColliderEventTypes
{
Enter,
Exit,
StayInside
}
}

上述代码中,类开头的[AddComponentMenu("Playground/Conditions/Condition Area")]、属性上面的[Header("Type of Event")],这些类似于Java中的注解,在C#中这个叫特性,继承于System.Attribute类,通常用作限定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Events;

public abstract class ConditionBase : MonoBehaviour
{
//actionitems can be connected to GameplayAction scripts, and execute their one action (the method ExecuteAction implemented in each child class)
[SerializeField]
public List<Action> actions = new List<Action>();

//custom actions are more complicated to setup but more powerful, and appear only if useCustomActions is enabled
public bool useCustomActions = false;
public UnityEvent customActions;

//to perform the actions only once
public bool happenOnlyOnce = false;
private bool alreadyHappened = false;

public bool filterByTag = false;
public string filterTag = "Player";

//dataObject is usually the other object in the collision
public void ExecuteAllActions(GameObject dataObject)
{
//first check if the action has already been executed
if(happenOnlyOnce && alreadyHappened)
return;

//first execute the simple GameplayActions, if present
bool actionResult;
foreach(Action ga in actions)
{
if(ga != null)
{
actionResult = ga.ExecuteAction(dataObject);
if(actionResult == false)
{
Debug.LogWarning("An action failed and interrupted the chain of Actions");
return;
}
}
}

//execute the custom actions, if present and enabled
if(useCustomActions)
{
customActions.Invoke();
}

alreadyHappened = true; //will prevent re-executing the actions if happenOnlyOnce is true
}
}

什么是GameplayAction?

Playground 作业

注意:在学习如何制作游戏时,模仿 80 年代老游戏(例如小行星、打砖块、太空侵略者、青蛙等等……)的玩法一般来说是很不错的做法,因为这些游戏很简单。然后,随着你的水平不断提升,你可以添加越来越多的细节并优化互动方式。

如果你需要灵感,请打开 Examples 文件夹并启动其中一个游戏。检查游戏对象,看看我们是如何制作这些游戏对象的,然后尝试创建类似的游戏对象。

todo

打印高级概念中的PDF资料

利用瓦片地图构建关卡

  1. 瓦片地图
  2. 官网TileMap相关教程