翻译章节 Collecting the Pick Up Objects
英文原文
00:02 - 00:04
We want to be able to pick up our collectable game
00:04 - 00:07
objects when our player game object collides with them.
00:07 - 00:09
To do this we need to detect our collisions
00:09 - 00:11
between the player game object and
00:11 - 00:13
the PickUp game objects.
00:13 - 00:15
We will need to have these collisions
00:15 - 00:17
trigger a new behaviour and we will need to
00:17 - 00:19
test these collisions to make sure we are
00:19 - 00:21
picking up the correct objects.
00:21 - 00:23
The PickUp objects, the player’s sphere,
00:23 - 00:25
the ground plane and the walls all have
00:25 - 00:28
colliders that inform us about collisions.
00:29 - 00:30
If we didn’t test our collisions to find out
00:30 - 00:32
which objects we have collided with
00:32 - 00:34
we could collect the wrong objects.
00:35 - 00:37
We could collect the floor, or the walls.
00:37 - 00:40
As a matter of face if we didn’t test our collisions
00:40 - 00:42
on the very first frame of the game we would
00:42 - 00:44
come in contact with the ground plane
00:44 - 00:45
and we would collect the ground plane
00:45 - 00:48
and then we would fall in to the void of the scene space
00:48 - 00:50
and the game would essentially be over.
00:51 - 00:55
First, we don’t need our player to remain inactive.
00:55 - 00:56
so let’s tick the Active checkbox and
00:56 - 00:58
bring back our player.
01:00 - 01:02
Next let’s select the PlayerController script
01:02 - 01:04
and open it for editing.
01:04 - 01:06
Just a note, we could edit this
01:06 - 01:08
script regardless of whether the game
01:08 - 01:09
object is active or not.
01:11 - 01:13
Now that we have the script open,
01:13 - 01:14
what code are we going to write?
01:15 - 01:17
We could write collider
01:17 - 01:19
and then search the documentation using the
01:19 - 01:20
hot key combination.
01:21 - 01:24
But there is a different way that we could do this as well.
01:25 - 01:27
Let’s return to Unity and look at the details
01:27 - 01:29
of our player game object.
01:30 - 01:32
What we are interested in here is the
01:32 - 01:34
sphere collider component.
01:34 - 01:37
In the header of each component on the left
01:37 - 01:39
is the component’s turndown arrow,
01:39 - 01:42
the icon, the Enable checkbox
01:42 - 01:45
if it’s available, and the type of the component.
01:46 - 01:49
On the right is the context sensitive gear gizmo
01:49 - 01:52
and an icon of a little book with a question mark.
01:53 - 01:54
Now this is what we need.
01:54 - 01:57
This is the quick link to the component reference.
01:58 - 02:00
If we select this icon we are taken
02:00 - 02:02
not to the scripting reference but to the
02:02 - 02:04
component reference.
02:05 - 02:07
We would read this document to find out more
02:07 - 02:09
about how to use this component in the context
02:09 - 02:10
of the editor.
02:10 - 02:13
We, however, want to find out how to
02:13 - 02:15
script to this component’s class.
02:15 - 02:18
To do this we simply switch to scripting
02:19 - 02:21
and we are taken to the scripting reference
02:21 - 02:22
for the sphere collider.
02:23 - 02:26
We want to detect and test our collisions.
02:26 - 02:28
For this project we are going to use
02:28 - 02:30
OnTriggerEnter.
02:37 - 02:40
Just imagine if we were, say, a daring plumber
02:40 - 02:43
and we jumped up to collect a perfect arch of coins
02:43 - 02:45
and bounced off the very first one as we
02:45 - 02:47
collected it and fell back to the ground.
02:48 - 02:49
Not very elegant.
02:50 - 02:52
This code will give us the ability to detect
02:52 - 02:54
the contact between our player game object
02:54 - 02:56
and our PickUp game objects
02:56 - 02:59
without actually creating a physical collision.
03:00 - 03:02
The code example however is not exactly
03:02 - 03:03
what we’re looking for.
03:03 - 03:06
But that’s okay, we can change that.
03:06 - 03:08
First, let’s copy the code,
03:09 - 03:11
and then let’s return to our scripting application.
03:12 - 03:15
Now that we’re back in scripting let’s paste the code.
03:16 - 03:18
As we have copied this code from a webpage
03:18 - 03:20
let’s correct the indents.
03:20 - 03:21
In this case I’m going to make sure the
03:21 - 03:23
indents are tabs and that all of the tabs are
03:23 - 03:25
correctly aligned.
03:25 - 03:27
Next, let’s look at this code.
03:27 - 03:30
We are using the function OnTriggerEnter.
03:30 - 03:32
OnTriggerEnter will be called by Unity
03:32 - 03:34
when our player game object first touches
03:34 - 03:36
a trigger collider.
03:36 - 03:38
We are given as an argument
03:38 - 03:41
a reference to the trigger collider that we have touched.
03:42 - 03:44
This is the collider called Other.
03:44 - 03:46
This reference gives us a way to get a
03:46 - 03:48
hold of the colliders that we touch.
03:49 - 03:51
With this code, when we touch another trigger
03:51 - 03:54
collider we will destroy the game object
03:54 - 03:56
that the trigger collider is attached to
03:56 - 03:59
through the reference other.gameObject.
03:59 - 04:02
By destroying that game object, the game object,
04:02 - 04:04
all of it’s components and all of it’s
04:04 - 04:06
children and their components are removed
04:06 - 04:08
from the scene.
04:08 - 04:10
For the sake of example in this assignment
04:10 - 04:12
we won’t destroy the other game object
04:12 - 04:14
we will deactivate it.
04:14 - 04:16
Just like we deactivated the player object
04:16 - 04:19
when we were creating our PickUp objects.
04:20 - 04:23
First, let’s remove the Destroy(other.gameobject)
04:23 - 04:25
code from the function.
04:25 - 04:27
But let’s paste it down below our script
04:27 - 04:29
as a palette to work with.
04:30 - 04:33
How will we deactivate our PickUp objects?
04:34 - 04:35
Well what clues do we have?
04:36 - 04:38
We can address the other collider’s game
04:38 - 04:41
object through other.gameObject.
04:41 - 04:43
We can see this here in the sample code.
04:43 - 04:45
And we want to test the other game object
04:45 - 04:48
and if it’s a PickUp object we want to deactivate
04:48 - 04:49
that game object.
04:50 - 04:52
So let’s look up GameObject
04:52 - 04:55
with our hot key combination and see what we can find.
04:56 - 04:59
Now we have the page on GameObject.
04:59 - 05:01
There are two important items here that we want.
05:02 - 05:04
They are tag,
05:04 - 05:06
tag allows us to identify the game object
05:06 - 05:09
by comparing the tag value to a string.
05:09 - 05:11
And SetActive.
05:11 - 05:15
This is how we activate or deactivate a game object through code.
05:16 - 05:18
The last item we need to know about is
05:18 - 05:20
Compare Tag.
05:20 - 05:22
Compare Tag allows us to efficiently
05:22 - 05:27
compare the tag of any game object to a sting value.
05:28 - 05:32
Let’s open up these three items, each in their own tab.
05:35 - 05:39
Tag allows us to identify a game object by a tag value.
05:40 - 05:45
We must declare our tags in the Tags and Layers Panel before using them.
05:46 - 05:49
It is possible to test a tag against a string value directly
05:49 - 05:51
with code like
05:51 - 05:57
if gameObject.tag is the same as some string value.
05:57 - 06:01
But there is a more efficient built-in way to do this,
06:01 - 06:03
and that is CompareTag
06:04 - 06:06
With CompareTag we can efficiently
06:06 - 06:10
compare the tag of any game object with a string value.
06:12 - 06:14
Let’s copy the sample code and
06:14 - 06:16
paste it in to our working palette.
06:21 - 06:26
Now GameObject.SetActive.
06:27 - 06:30
This is how we activate or deactivate a game object.
06:31 - 06:33
This is the code equivalent of clicking
06:33 - 06:35
the Active check box next to the
06:35 - 06:37
Name field in the Inspector.
06:40 - 06:42
In our case, just like the code snippet,
06:42 - 06:46
we will call GameObject.SetActive (false)
06:46 - 06:48
to deactivate our PickUp game objects.
06:50 - 06:55
Let’s copy this code and returning to our script editor
06:55 - 06:57
paste it in to our palette as well.
06:59 - 07:01
I feel we have enough pieces to write our code
07:03 - 07:10
so let’s write if (other.gameObject.CompareTag
07:11 - 07:13
with the string value of PickUp
07:14 - 07:18
and we will have to define this tag in Unity later.
07:19 - 07:24
other.gameObject.SetActive (false);
07:26 - 07:28
Now this code will be called every time
07:28 - 07:30
we touch a trigger collider.
07:30 - 07:33
We are given a reference to the collider we touch,
07:33 - 07:34
we test it’s tag,
07:34 - 07:37
and if the tag is the same as the string value
07:37 - 07:40
PickUp we will take the other game object
07:40 - 07:42
and we will call SetActive (false),
07:42 - 07:45
which will deactivate that game object.
07:45 - 07:48
Now we don’t need this code we’ve been saving anymore
07:48 - 07:51
and keeping it will only confuse the compiler
07:51 - 07:52
so we can delete it.
07:54 - 07:56
Let’s save this script and return to Unity
07:56 - 07:57
and check for errors.
07:59 - 08:01
The first thing we need to do it set up the tag value
08:01 - 08:03
for the PickUp objects.
08:03 - 08:06
Select the prefab asset for the PickUp object.
08:06 - 08:08
When we look at the tag list
08:08 - 08:10
we don’t see any tag called PickUp
08:10 - 08:12
so we need to add one.
08:12 - 08:14
Select Add Tag.
08:15 - 08:19
This brings up the Tags and Layers Panel.
08:19 - 08:21
Here we can customise tags and layers.
08:22 - 08:25
Note that this list is empty.
08:26 - 08:29
To create a new custom tag select the + button
08:29 - 08:32
to add a new row to the tags list.
08:33 - 08:37
In the new empty element, in our case tag 0,
08:37 - 08:40
type PickUp, and this is case sensitive
08:40 - 08:43
and needs to be exactly the same string
08:43 - 08:45
that we have in our script.
08:45 - 08:47
If in doubt we can copy and paste
08:47 - 08:50
this string to get the exact value.
08:52 - 08:54
When we look back at the prefab asset
08:54 - 08:57
note that the asset is still untagged.
08:57 - 09:00
By selecting Add Tag we changed our focus
09:00 - 09:02
from the prefab asset to the Tag Manager
09:02 - 09:05
and in the Tag Manager we created our tag.
09:05 - 09:07
Now we need to apply that tag
09:07 - 09:08
to the prefab asset.
09:09 - 09:11
Select the Tag drop down again
09:11 - 09:14
and see how we now have PickUp in the list.
09:14 - 09:16
Select this tag from the list and the asset
09:16 - 09:17
is now tagged PickUp.
09:17 - 09:20
And with the power of prefabs
09:20 - 09:23
all of the instances are now tagged PickUp as well.
09:25 - 09:27
Now let’s test our game.
09:27 - 09:29
Save the scene and enter play mode.
09:33 - 09:36
Hmm, okay, our tag is set to PickUp
09:36 - 09:38
but we are still bouncing off the PickUp cubes
09:38 - 09:41
just like we are bouncing off the walls.
09:41 - 09:43
So let’s exit play mode.
09:43 - 09:45
Before we discuss why we are bouncing off
09:45 - 09:47
the PickUp cubes rather than picking them up
09:47 - 09:49
we need to have a brief discussion about
09:49 - 09:50
Unity’s physics system.
09:51 - 09:54
I’m going to enter play mode for this discussion.
09:58 - 10:01
Let’s look at one of our cubes and our player.
10:01 - 10:03
As an aside we can select two or
10:03 - 10:05
more game objects at the same time
10:05 - 10:07
and inspect them all.
10:07 - 10:09
We do this by holding down the command key
10:09 - 10:12
on the mac or the control key on the PC,
10:12 - 10:13
and selecting the game objects.
10:14 - 10:16
When we select multiple game objects
10:16 - 10:18
note how the inspector changes to show
10:18 - 10:20
the common components and property
10:20 - 10:22
values of the selected game objects.
10:23 - 10:26
The inspector also allows for multi-object editing.
10:26 - 10:28
Using multi-object editing I’m going to
10:28 - 10:30
disable the mesh renderer on both the
10:30 - 10:33
player’s sphere and the selected cube with a single click.
10:34 - 10:36
This leaves us with the two green outlines
10:36 - 10:39
of the collider volumes for these two objects.
10:40 - 10:43
How do collisions work in Unity’s physics engine?
10:44 - 10:46
The physics engine does not allow two collider
10:46 - 10:47
volumes to overlap.
10:47 - 10:49
When the physics engine detects that any two
10:49 - 10:52
or more colliders will overlap that frame
10:52 - 10:54
the physics engine will look at the objects and
10:54 - 10:57
analyse their speed and rotation and shape
10:57 - 10:59
and calculate a collision.
10:59 - 11:01
One of the major factors in this calculation
11:01 - 11:03
is whether the colliders are static
11:03 - 11:05
or dynamic.
11:05 - 11:08
Static colliders are usually non-moving
11:08 - 11:10
parts of your scene, like the walls, the floor,
11:10 - 11:12
or the fountain in the courtyard.
11:12 - 11:15
Dynamic colliders are things that move
11:15 - 11:17
like the player’s sphere or a car.
11:18 - 11:20
When calculating a collision the static geometry
11:20 - 11:22
will not be affected by the collision.
11:23 - 11:25
But the dynamic objects will be.
11:25 - 11:27
In our case the player’s sphere is dynamic,
11:27 - 11:29
or moving geometry, and it is bouncing
11:29 - 11:31
off the static geometry of the cubes.
11:32 - 11:34
Just as it bounces off the static geometry
11:34 - 11:36
of the walls.
11:36 - 11:38
The physics engine can however allow the
11:38 - 11:41
penetration or overlap of collider volumes.
11:41 - 11:43
When it does this the physics engine
11:43 - 11:45
still calculates the collider volumes and
11:45 - 11:47
keeps track of the collider overlap.
11:48 - 11:50
But it doesn’t physically act on the overlapping
11:50 - 11:53
objects, it doesn’t cause a collision.
11:53 - 11:56
We do this by making our colliders in to
11:56 - 11:58
triggers, or trigger colliders.
11:58 - 12:00
When we make our colliders in to a trigger,
12:00 - 12:02
or trigger collider, we can detect
12:02 - 12:05
the contact with that trigger through the
12:05 - 12:07
OnTrigger event messages.
12:07 - 12:09
When a collider is a trigger you can do
12:09 - 12:11
clever things like place a trigger in the middle
12:11 - 12:14
of a doorway in, say, an adventure game,
12:14 - 12:15
and when the player enters the trigger
12:15 - 12:17
the mini-map updates and a message plays
12:17 - 12:19
‘you have discovered this room’.
12:20 - 12:22
Or every time your player walks around
12:22 - 12:24
that corner spiders drop from the ceiling
12:24 - 12:26
because the player has walked through a trigger.
12:27 - 12:30
For more information on OnCollision and on
12:30 - 12:32
trigger messages see the lessons linked below.
12:33 - 12:35
We are using OnTriggerEnter in our code
12:35 - 12:37
rather than OnCollisionEnter.
12:37 - 12:39
So we need to change our collider volumes
12:39 - 12:41
in to trigger volumes.
12:41 - 12:44
To do this we must be out of play mode.
12:46 - 12:48
Let’s select the prefab asset and look at
12:48 - 12:50
the box collider component.
12:50 - 12:52
Here we select Is Trigger
12:52 - 12:54
and again the power of prefabs
12:54 - 12:58
all of our PickUp objects are now using trigger colliders.
12:58 - 13:02
Let’s save our scene, enter play mode and test.
13:02 - 13:04
And as our player enters the trigger
13:04 - 13:06
we pickup the objects.
13:06 - 13:08
Excellent.
13:09 - 13:11
Let’s exit play mode.
13:12 - 13:14
Everything looks great.
13:14 - 13:16
We only have one issue.
13:16 - 13:19
We have made one small mistake,
13:19 - 13:21
and this is related to how Unity
13:21 - 13:22
optimises it’s physics.
13:23 - 13:25
As a performance optimisation Unity
13:25 - 13:27
calculates all the volumes
13:27 - 13:29
of all the static colliders in a scene
13:29 - 13:32
and holds this information in a cache.
13:32 - 13:34
This makes sense as static colliders
13:34 - 13:37
shouldn’t move, and this saves recalculating this
13:37 - 13:39
information every frame.
13:39 - 13:42
Where we have made our mistake is by rotating our cubes.
13:42 - 13:46
Any time we move, rotate, or scale a static collider
13:46 - 13:49
Unity will recalculate all the static colliders again
13:49 - 13:51
and update the static collider cache.
13:51 - 13:54
To recalculate the cache takes resources.
13:55 - 13:57
We can move, rotate or scale dynamic
13:57 - 14:00
colliders as often as we want and Unity won’t
14:00 - 14:02
recache any collider volumes.
14:02 - 14:04
Unity expects us to move colliders.
14:04 - 14:06
We simply need to indicate to Unity which
14:06 - 14:09
colliders are dynamic before we move them.
14:09 - 14:12
We do this by using the rigid body component.
14:12 - 14:14
Any game object with a collider
14:14 - 14:17
and a rigid body is considered dynamic.
14:18 - 14:20
Any game object with a collider attached
14:20 - 14:24
but no physics rigid body is expected to be static.
14:24 - 14:26
Currently our PickUp game objects have a
14:26 - 14:29
box collider but no rigid body.
14:29 - 14:31
So Unity is recalculating our static
14:31 - 14:33
collider cache every frame.
14:34 - 14:36
The solution is to add a rigid body
14:36 - 14:38
to the PickUp objects.
14:38 - 14:41
This will move the cubes from being static colliders
14:41 - 14:43
to being dynamic colliders.
14:43 - 14:45
Let’s save and play.
14:46 - 14:48
And our cubes fall through the floor.
14:48 - 14:51
Gravity pulls them down, and as they are triggers
14:51 - 14:53
they don’t collide with the floor.
14:53 - 14:55
Let’s exit play mode.
14:55 - 14:58
If we look at the rigid body component
14:58 - 15:01
we could simply disable Use Gravity,
15:01 - 15:04
which would prevent the cubes from being pulled downwards.
15:04 - 15:06
This is only a partial solution however.
15:07 - 15:09
If we did this, even though our cubes
15:09 - 15:11
would not respond to gravity they would still
15:11 - 15:13
respond to physics forces
15:13 - 15:15
There is a better solution.
15:15 - 15:18
And that is to select Is Kinematic.
15:19 - 15:22
When we do this we set this rigid body component to be
15:22 - 15:24
a kinematic rigid body.
15:24 - 15:26
A kinematic rigid body will not react
15:26 - 15:29
to physics forces and it can be animated
15:29 - 15:31
and moved by it’s transform.
15:32 - 15:35
This is great for everything from objects with colliders
15:35 - 15:37
like elevators and moving platforms,
15:37 - 15:39
to objects with triggers, like our collectables
15:39 - 15:42
that need to be animated or moved by their transform.
15:42 - 15:44
For more information on the rigid body
15:44 - 15:48
and Is Kinematic see the lessons linked below.
15:49 - 15:52
Let’s save our scene and enter play mode to test.
15:52 - 15:56
Now our behaviour is identical and performant.
15:56 - 15:59
So, static colliders shouldn’t move,
15:59 - 16:01
like walls and floors.
16:01 - 16:03
Dynamic colliders can move,
16:03 - 16:05
and have a rigid body attached.
16:05 - 16:08
Standard rigid bodies are moved using physics forces.
16:08 - 16:10
Kinematic rigid bodies are moved using
16:10 - 16:12
their transform.
16:13 - 16:15
In the next assignment we will count our
16:15 - 16:17
collectable object and make a simple UI
16:17 - 16:20
to display our score and messages.
译文
00:02 - 00:07
我们想要拾起可捡起的物体当我们的player撞到它们的时候
00:07 - 00:13
因此我们需要探测到player和可捡起的小方块之间的碰撞
00:13 - 00:15
我们需要这些碰撞触发一个行为,并且这些碰撞能够保证我们捡起正确的物体
00:21 - 00:23
可捡起的小方块,玩家的小球,地板和墙都是可以通知我们有碰撞了的碰撞物体
00:29 - 00:30
如果我们不检测哪个物体发生了碰撞,我们可能会捡起错误的物体
00:35 - 00:37
我们可能会捡起地板或者墙
00:37 - 00:40
事实上如果我们不检测碰撞,我们在进入游戏的第一帧就会把地板给捡起来,然后我们会掉入一个空的场景,游戏就结束了
00:51 - 00:55
首先我们要让player可见
00:55 - 00:56
所以我们要让player回来,勾选上player的框框
01:00 - 01:02
接下爱我们选择PlayerController 脚本,打开编辑
01:04 - 01:06
注意一下,我们可以编辑这个脚本,不管这个物体是否可见
01:11 - 01:13
既然我们打开了这个脚本,那么我们写什么呢?
01:15 - 01:17
我们可以写一个collider,然后用快捷键搜索文档
01:21 - 01:24
但是这里我们可以用一个不同的方法
01:25 - 01:27
我们回到Unity界面看一下player的细节
01:30 - 01:32
注意看Inspector里的 sphere collider 组件
01:34 - 01:37
在每个组件的头部左边有一个可以折叠组建的箭头,一个图标,一个选择框可以控制是否有效,还有一个组件类型的文字
01:46 - 01:49
右边有一个下啦菜单,还有一个带有问号的书的图标
01:53 - 01:54
带有问号的书的图标是这里我们需要的
01:54 - 01:57
这是一个快捷链接到组件参考内容
01:58 - 02:00
选择这个图标会连接到组件参考而不是脚本参考信息
02:05 - 02:07
我们阅读这个文档去了解如何在编辑器中使用组件
02:10 - 02:13
我们也要了解组件的相关脚本
02:15 - 02:18
我们可以选择“switch to scripting”,就会跳转到sphere collider的脚本参考页面
02:23 - 02:26
我们需要探测碰撞
02:26 - 02:28
这个项目,我们需要使用OnTriggerEnter方法
02:37 - 02:40
仅仅想象一下,我们是一个水管工人,我们跳起来捡起每一个硬币然后弹开,硬币落到地面
02:48 - 02:49
不是很优雅的比喻
02:50 - 02:52
OnTriggerEnter方法可以让我们不用创建physical collision就能检测player和可拾起的小方块之间的碰撞
03:00 - 03:02
事例代码不是很适合我们
03:03 - 03:06
我们可以修改一下,回到脚本编辑的页面
03:12 - 03:15
复制一下代码
03:16 - 03:18
调整一下缩进
03:25 - 03:27
接下来看一下代码
03:27 - 03:30
我们使用OnTriggerEnter方法
03:30 - 03:32
当player 第一次碰到触发碰撞的物体,OnTriggerEnter就会调用
03:36 - 03:38
OnTriggerEnter提供了一个参数指代我们碰到的物体
03:42 - 03:44
这个碰撞体叫other
03:44 - 03:46
这样我们就能得到碰撞的物体
03:49 - 03:51
在事例代码里,发生碰撞的时候我们通过other.gameObject关联到物体
就可以销毁这个物体
03:59 - 04:02
通过销毁物体,物体的所有组件和子元素都会被从场景里移除
04:08 - 04:10
这里为了示例,我们不销毁它而是使物体无效
04:14 - 04:16
就像取消player的勾选框一样
04:20 - 04:23
首先我们移除“Destroy(other.gameobject)”
04:25 - 04:27
但是我们复制到脚本下面去作为参考用
04:30 - 04:33
我们如何让小方块无效呢?
04:36 - 04:38
我们可以通过other.gameObject得到碰撞的物体
04:41 - 04:43
我们想检测一下物体当我们要让小方块实效的时候
04:50 - 04:52
用快捷键查阅 GameObject脚本
04:56 - 04:59
看下 GameObject页面.
04:59 - 05:01
两个我们需要的属性
05:02 - 05:04
tag,tag可以通过字符串来比较和标记游戏物体和设置是否有效
05:16 - 05:18
最后一个是Compare Tag,Compare Tag可以更高效的比较tag
05:28 - 05:32
我们打开这3个项目,Tag可以定义一个物体,在用之前我们需要声明一下
05:46 - 05:49
用CompareTag方法比较tag更高效
06:12 - 06:14
复制一下代码
06:21 - 06:26
GameObject.SetActive和在Inspector里点击勾选框设置有效和无效效果是一样的
06:40 - 06:42
我们这里通过调用 GameObject.SetActive (false)来让小方块无效
06:50 - 06:55
再复制一下代码
06:59 - 07:01
后面我们需要在Unity中定义tag
07:26 - 07:28
现在每次触发碰撞的时候都会调用我们的方法
07:59 - 08:01
首先我们需要设置一下小方块的tag
08:03 - 08:06
选中prefab资源
08:06 - 08:08
当我们看tag list,我们找不到我们需要的“PickUp”
08:12 - 08:14
选择Add Tag
08:15 - 08:19
增加一个tag
在prefab中设置好tag之后,所有的实例的tag都设置好了
09:25 - 09:27
现在测试一下游戏,保存场景,进入游戏模式,但是player仍然被小方块弹开,就像被墙弹开一样
09:41 - 09:43
退出游戏模式
09:43 - 09:45
在我们讨论被弹开而不是拾起物体之前,我们先讨论一下Unity’s physics system.
09:51 - 09:54
我进入游戏模式讨论
09:58 - 10:01
我们看一下player和一个小方块
10:01 - 10:03
我们可以同时选中多个物体,在检查器中操作它们
10:07 - 10:09
按住“command”键来选择物体
10:14 - 10:16
选中多个物体的时候,可以同时对多个物体编辑,在mesh renderer取消勾选框,会看到两个绿色的方框
10:44 - 10:46
物理引擎不允许两个碰撞体重叠(译者注:并不绝对,看后面),
10:47 - 10:49
当物理引擎探测到两个或更多碰撞体可能重叠的时候,物理引擎会分析它们的速度,旋转角度,还有形状等来计算碰撞
10:59 - 11:01
在这个计算中一个主要的因素是碰撞体是静态的还是动态的
11:05 - 11:08
静态的碰撞体通常是不会动的,像墙,地板或者院子里的喷泉
11:12 - 11:15
动态的碰撞体是可以移动的,像player的小球,汽车
11:18 - 11:20
当计算碰撞的时候,一个静态的几何物体不会受碰撞的影响,动态的会受影响
11:25 - 11:27
在我们的案例中,小球是动态的,它被静态的小方块弹开了
11:32 - 11:34
就像被静态的墙弹开了
11:36 - 11:38
然而,我们通过给碰撞体设置triggers,或者triggers碰撞体,物理引擎可以允许碰撞体的穿透或重叠。
11:41 - 11:43
当它这样做时,物理引擎仍然计算碰撞体体积并且跟踪碰撞体重叠
11:48 - 11:50
但它不会物理地作用于重叠的对象,它不会导致碰撞
12:00 - 12:02
我们通过OnTrigger检测到碰撞
12:33 - 12:35
我在我们的代码中使用OnTriggerEnter而不是OnCollisionEnter
12:37 - 12:39
所以我们需要改变我们的碰撞器为一个trigger值
12:41 - 12:44
我们需要离开play模式
12:46 - 12:48
我们选中prefab资源,在collider组件中选中Trigger,这一次所有的小方块都会使用trigger碰撞器
12:58 - 13:02
保存场景,进入play模式测试
13:02 - 13:04
当我们的小球进入到触发器时我们捡起了小方块
13:06 - 13:08
完美
13:09 - 13:11
离开play模式
13:12 - 13:14
看起来很好
13:14 - 13:16
我们仅有一个问题
13:16 - 13:19
我们犯了一个小错误关于Unity如何优化物理操作
13:23 - 13:25
作为一个性能优化Unity会计算场景中所有静态碰撞体的值并且保存在缓存中
13:32 - 13:34
这是有道理的,因为静态碰撞者不应该移动,这将保存每帧重新计算的信息
13:39 - 13:42
我们犯错的地方在于我们旋转了小方块
13:42 - 13:46
每一次我们移动,旋转或者缩放静态碰撞体,Unity会重新计算静态碰撞并且更新他的缓存
13:51 - 13:54
重新计算占用资源了
13:55 - 13:57
只要Unity不重新计算缓存碰撞值,我们就可以移动,旋转或者缩放静态碰撞体
14:02 - 14:04
Unity期望我们移动碰撞
14:04 - 14:06
在我们移动物体之前,我们需要告诉Unity哪些碰撞体是动态的
14:09 - 14:12
我们可以使用rigid body组件
14:12 - 14:14
只要game object拥有碰撞体和rigid body就可以被认为是动态的
14:18 - 14:20
任何一个game object都有碰撞体属性但是没有rigid body,所以就会被认为是静态的了
14:24 - 14:26
当前我们的小方块有box collider但是没有刚体
14:29 - 14:31
所以Unity会在每帧重新计算静态collider缓存
14:34 - 14:36
解决办法是给小方块加上刚体属性就可以捡起物体了
14:38 - 14:41
这会让小方块从静态碰撞体变为动态碰撞体
14:43 - 14:45
保存,play
14:46 - 14:48
所有的小方块都会往下掉
14:48 - 14:51
重力会把它们拉下去,因为他们是触发器,他们不会与地板碰撞。
14:53 - 14:55
退出play模式
14:55 - 14:58
看一下刚体组件我们可以简单的让重力失效就可以阻止小方块被下拉
15:04 - 15:06
但这只是一个部分解决方案
15:07 - 15:09
如果我们这样做了,即使小方块不会在重力作用上被影响也会被其他的物理作用力所影响
15:13 - 15:15
这里有一个更好的解决办法
15:15 - 15:18
我们选择Kinematic
15:19 - 15:22
选中了之后我们会设置刚体成为一个运动学刚体
15:24 - 15:26
运动学刚体不受物理作用力的影响,但是可以动画运动
15:32 - 15:35
这对一些像升降机,移动平台,类似我们小方块带触发器并且需要动画控制变化的物体来说太棒了
15:49 - 15:52
保存场景退出play模式
15:52 - 15:56
现在看起来不错
15:56 - 15:59
所以,静态碰撞体不应该动,像墙和地板,动态碰撞体可移动,并且有rigid body组件
16:05 - 16:08
标准的刚体在外力作用下运动,Kinematic刚体通过变形动画运动
总结
这章节概念比较多,所以需要好好理解,下面总结一下
- 新建一个game object,此时这个物体只有transform属性,没有其他属性,在场景里看不到
- 新建的3d物体,比如sphere,cube是静态的,但是它们默认具体碰撞体属性
- 一般情况下,物理引擎不允许两个碰撞体重叠,当物理引擎检测到发生碰撞时,动态的碰撞体会被弹开,不会发生重叠或者穿透,静态的碰撞体依旧保持不动
- 当我们给碰撞体添加了触发器之后,碰撞体就可以重叠或者穿透了,通过OnTriggerEnter检测碰撞
- Unity会计算场景中所有静态碰撞体的值并且保存在缓存中,如果静态碰撞体发生动画变形运动,那么Unity每一帧都会计算该静态碰撞体的值并且缓存在缓存中,这会占用大量的资源,解决办法是给小方块添加刚体属性,一个物体具有碰撞体和刚体属性就会被认为是一个动态的碰撞体,这样就不会每一帧都会缓存碰撞值(小方块cube天生就具有碰撞体的组件,所以只需要添加刚体组件就行)
- 给小方块添加刚体组件之后,小方块不能被地板接住,会直接掉下去,解决办法是在刚体组件里选择Kinematic刚体属性,Kinematic刚体不受物理作用力的影响,但是可以动画运动
- 为什么小方块添加刚体组件不能被地板托举住而小球可以被地板托举住不往下掉?因为小方块在碰撞体里面勾选了触发器选项,带触发器的碰撞体可以在碰撞的时候穿透和重叠,所以就需要小方块在刚体里面勾选Kinematic刚体属性,这样就不受外力的影响了