How to make a DOOM CLONE in Unity || E1M2 Enemy Hit Detection

SpawnCampGames
4 Dec 202023:00

Summary

TLDR本视频教程介绍了如何为游戏角色设置类似《毁灭战士》的枪械行为和目标敌人的能力。首先,通过调整玩家的移动脚本,为角色添加了动量效果,使其移动更加自然。接着,创建了基础的敌人系统,包括敌人健康值的管理。然后,详细讲解了如何为枪械添加检测敌人和视线检测的功能,并通过射线检测来确定是否对敌人造成伤害。最后,通过调整伤害值和设置射线层遮罩,完成了一个基本的枪械和敌人交互系统,为游戏开发提供了一个坚实的基础。

Takeaways

  • 🎮 视频讲解了如何设置枪械行为和敌人目标系统,模仿《毁灭战士》(Doom)风格的瞄准辅助功能。
  • 🔧 首先,需要解决玩家的移动惯性问题,使其不会像当前那样突然停止,而是模仿《毁灭战士》中的平滑减速。
  • 🗂️ 组织项目窗口,创建了动画相关的文件夹,包括动画器和动画剪辑。
  • ⏩ 通过修改玩家移动脚本,引入了输入向量的线性插值(Lerp),实现平滑的移动效果。
  • 🚶 更新了玩家移动逻辑,区分了按键持续按住和释放时的不同行为。
  • 🔫 创建了一个基本的敌人系统,包括敌人健康值,并为敌人添加了刚体组件用于碰撞检测。
  • 📁 建立了一个敌人管理器,用于跟踪玩家面前的敌人,并在触发器进入和退出时添加或删除敌人。
  • 🔒 通过射线检测(Raycast),确保玩家在射击时有视线范围内的敌人才能造成伤害。
  • 💥 实现了枪械的射击功能,包括射击频率控制和对敌人造成伤害的逻辑。
  • 🎯 根据敌人与玩家的距离,调整了伤害值,实现了距离越远伤害越小的效果。
  • 🛠️ 视频最后提供了一个基础框架,为未来游戏开发提供了扩展的可能性。

Q & A

  • 视频中提到的'doom style'瞄准辅助是如何实现的?

    -视频中通过设置枪的射线检测(raycast)来实现'doom style'瞄准辅助,允许玩家射击高于或低于玩家位置的敌人,并检查是否在视线范围内。

  • 如何在游戏中实现玩家的动量(momentum)效果?

    -通过在玩家移动脚本中使用线性插值(lerp)将输入向量平滑地向零过渡,实现了类似Doom游戏中玩家移动的动量效果。

  • 视频中提到的'player move script'是做什么用的?

    -'player move script'用于控制玩家的移动。它接收输入值,并根据这些值来移动玩家角色。

  • 如何在游戏中创建一个基本的敌人系统?

    -通过创建一个带有刚体(Rigidbody)组件的3D胶囊形状的敌人对象,并为其添加敌人(enemy)组件和敌对管理器(enemy manager)脚本来实现基本的敌人系统。

  • 视频中提到的'gun trigger'组件的作用是什么?

    -'gun trigger'组件是一个触发器(trigger)类型的盒子碰撞器(Box Collider),用于检测玩家枪口前方的敌人,并在玩家射击时触发事件。

  • 如何在游戏中实现敌人的健康系统?

    -通过在敌人脚本中添加一个私有浮点数变量来表示敌人的健康值,并提供一个公共的'take damage'方法来减少健康值,当健康值降至零或以下时,敌人将被销毁。

  • 视频中提到的'enemy manager'脚本的作用是什么?

    -'enemy manager'脚本用于管理游戏中所有敌人的集合,提供添加和移除敌人的方法。

  • 如何在游戏中实现枪械的射击功能?

    -通过检测鼠标左键的按下事件,并在满足射击间隔(fire rate)条件时,调用'fire'方法来实现射击功能。

  • 视频中提到的射线检测(raycast)如何用于判断敌人是否在玩家视线内?

    -通过从玩家位置发出射线,检测是否能够直接击中敌人位置,如果可以,则认为敌人在玩家视线内。

  • 如何在游戏中实现不同距离下的敌人受到不同伤害的效果?

    -通过计算玩家与敌人之间的距离,并根据这个距离来调整对敌人造成的伤害值,距离越远,伤害越小。

  • 视频中提到的'layer mask'在射线检测中的作用是什么?

    -'layer mask'用于指定射线检测时应该忽略的层,例如在这个视频中,射线检测需要忽略枪的层,以防止误检测到枪本身。

Outlines

00:00

🎮 游戏开发:设置玩家动作和枪械系统

本段介绍了如何在游戏中设置玩家的移动和枪械行为,模仿《毁灭战士》(Doom)的风格。开发者首先强调了保持项目窗口整洁的重要性,然后创建了动画相关的文件夹。接着,他们修改了玩家移动脚本,加入了动量衰减和速度调整,以模拟《毁灭战士》中的玩家移动特性。此外,还提到了如何通过脚本实现玩家的行走和停止动作,并解决了头部晃动的问题。最后,为了测试枪械,创建了一个3D胶囊形状的敌人,并为其添加了刚体组件,但移除了重力以用于碰撞检测。

05:00

🔫 枪械机制:检测敌人和射线投射

在这一部分中,开发者详细说明了如何创建枪械机制,包括使用盒子碰撞器来追踪玩家前方的敌人,并通过射线投射来确定玩家是否对敌人有视线。他们创建了一个空对象作为玩家的枪,并为其添加了盒子碰撞器,设置为触发器。然后,通过脚本修改盒子碰撞器的大小和中心点,以表示枪的射程。此外,还介绍了如何通过触发器进入和退出事件来管理敌人列表,并创建了敌人管理器脚本来处理敌人的添加和移除。

10:04

👾 敌人管理:创建敌人列表和伤害系统

本段讲述了如何创建和管理敌人列表,以及如何实现对敌人的伤害。开发者首先创建了一个名为'enemy manager'的空游戏对象,并为其添加了脚本来管理敌人列表。然后,他们为敌人组件添加了健康值,并实现了一个'take damage'函数,用于减少敌人的健康值并在健康值降至零时销毁敌人对象。此外,还介绍了如何在敌人管理器中添加和移除敌人,以及如何通过射线投射来检测玩家是否能够击中敌人。

15:14

🎯 射线投射和敌人伤害逻辑

在这一部分中,开发者实现了枪械的射线投射功能,以确保玩家只能击中视线内的敌人。他们首先在枪脚本中创建了一个射线投射,从玩家的位置出发,向敌人的方向投射。然后,通过检查射线投射是否击中了敌人,来调用敌人的'take damage'函数。此外,还介绍了如何设置层级掩码,以确保射线投射忽略特定的对象,如枪的碰撞器。最后,他们通过调试工具来可视化射线投射,并测试了整个系统。

20:15

🛡️ 完善系统:调整伤害和优化射线投射

最后一段介绍了如何完善敌人检测系统和枪械的伤害逻辑。开发者首先通过射线投射来检查敌人是否在玩家的视线范围内,并根据敌人与玩家之间的距离来调整伤害值。他们设置了不同的伤害值,以模拟远距离和近距离的伤害差异。此外,还介绍了如何通过设置层级掩码来优化射线投射,确保它能够正确地忽略特定的对象。最后,他们测试了整个系统,确保枪械可以在不同的位置和视线条件下正确地击中并伤害敌人。

Mindmap

Keywords

💡枪械行为

枪械行为在视频中指的是游戏中模拟枪械射击敌人的机制。这是视频的核心内容之一,涉及到如何编程实现玩家控制的角色能够使用枪械攻击敌人。例如,在设置枪械行为时,视频提到了考虑《毁灭战士》(Doom)风格的瞄准辅助,允许玩家射击高于或低于玩家位置的敌人。

💡目标敌人

目标敌人是指游戏中玩家需要攻击的对象。视频中讨论了如何设置敌人系统,包括敌人的健康值,并确保玩家的枪械能够瞄准并射击这些敌人。例如,通过设置一个基本的敌人系统,敌人具有健康值,并且玩家需要通过枪械射击来减少敌人的健康值直至消灭。

💡玩家动量

玩家动量是指玩家角色在移动时保持的惯性,即使停止输入指令,角色仍会继续移动一段距离。视频中提到了原始《毁灭战士》中玩家的动量效果,并与项目中玩家的突然停止行为进行了对比,然后通过代码调整实现了类似的动量效果。

💡动画剪辑

动画剪辑是指游戏中角色动作的动画序列。视频提到了创建动画剪辑文件夹,用于组织和存储角色的各种动作动画,如行走、射击等,这是游戏开发中角色动画制作的一部分。

💡射线检测

射线检测是一种游戏开发中常用的技术,用于确定两点之间是否存在障碍物。视频中使用射线检测来实现枪械的瞄准功能,通过从玩家的位置发射射线到敌人位置,检测是否有障碍物阻挡视线,从而判断是否能够射击到敌人。

💡触发器

触发器在Unity中是一种特殊的碰撞器,可以检测对象是否进入或离开特定的区域,而不需要实际的物理碰撞。视频中使用触发器来检测敌人是否进入了玩家枪械的射击范围内,从而激活射线检测和瞄准逻辑。

💡敌人管理器

敌人管理器是一个用于跟踪和管理游戏中所有敌人对象的组件或脚本。视频中创建了一个名为'enemy manager'的空GameObject,并为其添加了脚本来管理敌人的添加和移除,以及敌人的健康值和死亡逻辑。

💡伤害

伤害是指游戏中敌人或玩家受到的损伤量。视频脚本中提到了设置敌人的健康值,并在玩家射击时调用敌人的'take damage'方法来减少其健康值。伤害的计算还考虑了玩家与敌人之间的距离,以决定伤害的大小。

💡线视线检测

线视线检测是确定玩家与敌人之间是否存在清晰的视线路径,以判断玩家是否能够击中敌人。视频中通过射线检测实现线视线检测,确保玩家射击时能够直接瞄准到敌人,而不是被障碍物阻挡。

💡层蒙版

层蒙版是Unity中用于控制哪些层的对象可以相互交互的一种技术。视频中设置了层蒙版,以确保射线检测可以忽略特定的层,例如玩家的枪械层,从而提高射线检测的准确性和性能。

Highlights

视频将设置枪支行为和目标敌人的能力,采用毁灭战士风格。

将考虑毁灭战士的瞄准辅助,能够射击玩家上方或下方的敌人。

在设置枪支之前,将解决玩家的动量问题,使其不会突然停止。

强调保持项目窗口整洁的重要性,并创建动画相关文件夹。

介绍玩家移动脚本,解释输入值如何影响玩家移动。

使用move towards函数和lerp实现玩家动量衰减。

通过if语句区分玩家是否按住WASD键,并实现不同移动效果。

移除原有的head bob功能,改为在玩家行走时手动添加。

创建3D胶囊形状的敌人,并为其添加材料和刚体组件。

使用box collider和raycast检测玩家与敌人之间的视线。

创建枪支空对象,并为其添加box collider作为触发器。

编写枪支脚本,包含敌人管理器和敌人列表,用于追踪敌人。

实现枪支射击逻辑,包括射击频率控制和敌人伤害计算。

为敌人添加健康值和受到伤害时的逻辑处理。

通过raycast检测玩家与敌人之间是否视线清晰。

设置层级掩码,确保raycast能够正确识别敌人。

实现基于距离的伤害计算,远距离敌人受到的伤害较小。

完成枪支和敌人的基础系统,为未来扩展打下良好基础。

Transcripts

play00:03

in this video we'll set up the gun

play00:04

behavior and ability to target enemies

play00:06

doom style

play00:07

we'll take into consideration doom's aim

play00:08

assist be able to shoot enemies above or

play00:10

below the player

play00:11

and check for line of sight in the

play00:13

process we'll set up a super basic enemy

play00:15

system with enemy health

play00:17

before we get into the gun stuff i was

play00:19

referencing doom's gun mechanics and i

play00:21

noticed that the og doom has momentum

play00:23

for his player

play00:24

he doesn't come to an abrupt stop like

play00:25

our player does so we'll address that

play00:27

first

play00:28

okay first off let's clean this project

play00:30

window i can't stress how important it

play00:32

is to keep this thing clean

play00:33

so i'm just going to move my scripts

play00:34

where they need to go i'm going to

play00:35

create a new folder

play00:37

for animation things one's going to be a

play00:40

animators folder and what's going to be

play00:41

an animation clips folder

play00:44

now let's go straight into our player

play00:45

move script

play00:49

so this block of code is where we get

play00:51

our starting input it's either negative

play00:54

one

play00:54

zero or one and then we put it all

play00:56

together and we finally use that to move

play00:59

our player

play01:00

if we're holding the keys we want this

play01:01

to happen when we release the keys we

play01:03

want something else to happen

play01:05

we'll just say that here for now and

play01:07

it's that we want the last number

play01:09

used as input vector to be alert down

play01:12

towards zero

play01:13

there's a function called move towards

play01:16

which is probably better for this since

play01:17

alert never truly makes it to zero but

play01:19

for us it's good enough

play01:21

so let's learn our input vector and

play01:23

we're gonna lerp it

play01:25

towards vector 3.0

play01:28

and the time variable will be time dot

play01:31

delta time

play01:32

but multiplied by something that we

play01:34

control so we'll call this

play01:38

momentum damping

play01:47

[Music]

play01:48

and at the top we'll just say it's a new

play01:50

float

play01:51

and we'll set it equal to five and while

play01:54

we're here let's go ahead and slow down

play01:56

our player a bit

play01:57

and we'll change this to 10.

play02:04

so back down in input we're going to say

play02:07

this part

play02:08

is if we're holding down wasd and this

play02:11

part

play02:12

is if you're not

play02:15

so the easiest way that i thought to do

play02:18

this was just make an

play02:19

if statement so we'll just go back up

play02:22

to above this block and we're going to

play02:24

use an if statement and it's going to be

play02:26

input.getkey instead of getkeydown

play02:29

and it's going to be keycode.w and we're

play02:33

going to use

play02:34

the double pops to mean or and then we

play02:38

can copy and paste it a few times

play02:43

then we can go back and change this to

play02:46

make sure it says

play02:47

w a s or d

play02:51

and then we can get rid of the last or

play02:56

and then lastly we'll throw this bit of

play02:59

code inside the if block

play03:03

so now we can say else if none of those

play03:05

keys are held we want to do our alert

play03:07

and since the code above doesn't get a

play03:09

chance to update the input using the

play03:11

axes

play03:12

we'll have whatever the last input was

play03:14

to lerp to zero

play03:16

so after that we can clean the script up

play03:18

a little bit

play03:19

but now we have to do something about

play03:21

this head bob let's go down here and

play03:23

look at the way it works

play03:24

so it uses the velocity of the character

play03:26

controller but now we have the situation

play03:28

where like at the very end of your walk

play03:30

the camera will still be bobbing so

play03:31

let's just go ahead and get rid of this

play03:33

function completely

play03:34

and instead we'll check here when we're

play03:36

holding the keys down

play03:40

and if we're doing that we must be

play03:42

walking so we'll put a is walking equals

play03:45

true

play03:47

and if we're not well we're not walking

play03:49

and then we'll put a

play03:50

is walking equals false now we can go

play03:53

back up to the update and we can delete

play03:55

the old function and let's save and go

play03:58

into unity

play04:00

if we go to our player and we look at

play04:02

the player speed

play04:03

it's different than what we set in the

play04:05

script we're going to go to reset

play04:07

and that's going to change everything

play04:08

it's also going to make us lose our

play04:10

camera

play04:11

enum reference so let's just go ahead

play04:13

and drag that back

play04:14

in

play04:17

and if we save and test you'll see that

play04:19

our player has momentum

play04:23

to work on the gun we'll need an enemy

play04:25

to test let's create a 3d capsule

play04:28

we're going to name it enemy

play04:31

reset its transform and pull it out of

play04:34

the ground

play04:35

so we're going to hop into our materials

play04:37

and duplicate our player material

play04:39

rename it to enemy gonna make it a

play04:42

red

play04:46

then we can drag that onto our enemy

play04:49

since we're gonna need our gun to detect

play04:51

the enemy then they're gonna need a

play04:53

rigid body

play04:54

so we're gonna add a rigid body to this

play04:58

since it's only for collision detection

play05:00

though we can remove gravity from it

play05:03

as well as making it kinematic

play05:07

so let's post this little enemy up here

play05:09

and we'll take a look at how the gun

play05:10

works

play05:12

so you can see here we're using this big

play05:14

box collider

play05:15

about one meter wide cast out in front

play05:17

of the player

play05:18

and it's keeping track of what enemies

play05:20

are in that collider

play05:22

then when you pull the trigger it'll

play05:23

shoot a raycast at every enemy that's in

play05:26

the clotter

play05:26

and make sure you got line of sight to

play05:28

that enemy and if you do

play05:30

it damages that enemy so with that crash

play05:33

course let's get started on the gun

play05:35

first we'll create it as an empty object

play05:37

of the player

play05:38

we'll name it gun as we also check that

play05:41

his position is zeroed out

play05:43

so now on the gun object we need to add

play05:45

a box collider

play05:46

that will set as trigger

play05:51

now using scripting we're going to

play05:53

modify its size and center points

play05:55

to represent the gun's range so we'll go

play05:58

to the bottom and we'll add a component

play06:00

and we'll call this gun and we'll hit

play06:02

enter twice

play06:03

and open it up first we need a reference

play06:06

to that box collider that we just set up

play06:08

and since it's on this game object we

play06:10

can make a private reference

play06:12

to a box collider

play06:15

and we'll call this gun trigger

play06:19

and then in our start function we'll

play06:21

just say gun trigger

play06:22

equals get component box collider

play06:31

now back up top we'll need two variables

play06:33

to modify the spots collider

play06:35

and they'll both be public floats one

play06:37

will be called range

play06:39

and the other will be called vertical

play06:40

range

play06:42

so back in the start right after we get

play06:44

the gun trigger we'll change its size

play06:46

with gun trigger

play06:47

dot size equals a new vector three

play06:52

and for the x i want to keep one meter

play06:55

to mimic aim assist

play06:56

and i want vertical range for its y

play07:01

and for the z it's just going to be

play07:03

range

play07:06

so on the next line to compensate for

play07:08

the size we're going to say gun trigger

play07:09

dot center

play07:10

equals new vector 3 0 on the x

play07:14

0 on the y and on the z we want it to be

play07:17

half of our range so we're going to say

play07:18

range times 0.5

play07:23

let's say we put this code in the update

play07:25

block just to see what happens

play07:27

so if we say we go in here now we can

play07:29

see if we move our range

play07:31

the pivot corresponds with that

play07:36

so let's put this back into our start

play07:40

because we only wanted to happen

play07:41

when the game starts and

play07:45

up here we're going to go ahead and set

play07:46

our range to 20

play07:48

and our vertical range we're going to

play07:50

set it to 20 as well

play07:53

and underneath our void update we're

play07:54

going to need two unity functions

play07:57

uh one's on trigger enter and the other

play08:00

is going to be

play08:01

on trigger exit and for our ontrigger

play08:04

enter

play08:05

we're gonna want to

play08:08

add a potential enemy

play08:13

and then on our on trigger exit

play08:16

we want to remove enemy

play08:22

but to add remove these enemies we're

play08:23

gonna need to know what an enemy is

play08:26

so we're going to go back into unity and

play08:28

on our enemy we're going to

play08:30

add a new component and it's going to be

play08:32

called enemy

play08:33

we'll hit enter twice and that's pretty

play08:36

much it

play08:36

for now

play08:40

and let's put these scripts in the

play08:42

folder

play08:45

so now we go back to our player and our

play08:46

gun and

play08:48

inside the gun script we now have a way

play08:50

to get our enemies

play08:53

so in the trigger enter we're going to

play08:55

try to get the enemy component from

play08:57

another object

play08:58

by saying enemy named enemy equals

play09:03

other.transform.getcomponent

play09:06

top enemy

play09:10

and then we can use if enemy which just

play09:12

checks whether the enemy variable

play09:14

isn't null

play09:19

and if there's an enemy then we can add

play09:21

it here

play09:24

and then we can copy this over to the

play09:26

exit trigger because we're gonna do the

play09:28

same thing

play09:29

but only this time we're gonna remove

play09:31

enemies

play09:32

so now we need something to keep track

play09:34

of these enemies

play09:38

back in unity we're going to go to the

play09:39

hierarchy and we're going to

play09:41

create a new empty game object we're

play09:44

going to reset its transform to be 000

play09:47

and we're going to name it we're gonna

play09:50

call it

play09:51

enemy manager and we're also going to

play09:55

add a script to it

play09:57

called enemy manager

play10:04

so double click it to open it up and we

play10:05

can get rid of all the starting

play10:07

functions

play10:09

we'll be using the public list and this

play10:12

is a list of

play10:13

type enemy and we'll call the list

play10:17

enemies and trigger and is equal to

play10:21

a new list of top enemy

play10:25

we're using a list because it's easy to

play10:27

add and remove objects to and that's

play10:29

what we're going to do here

play10:30

we're going to add a new public void add

play10:33

enemy

play10:34

and we're gonna pass in an enemy and

play10:37

it's just gonna be called

play10:38

enemy

play10:39

[Music]

play10:42

and then inside we're gonna say enemies

play10:45

and trigger

play10:46

dot add

play10:51

and then we're gonna add the enemy

play10:54

and then we can copy and paste this

play10:56

function down below

play10:58

and this is gonna be identical except

play11:00

it's going to be called

play11:01

remove enemy and it's going to access

play11:03

the dot remove function

play11:05

of enemies and trigger now we can save

play11:08

and we're pretty much done with the

play11:10

script so let's go back into our

play11:12

gun script of the player so now we know

play11:15

what enemies are and we have a way to

play11:17

add and remove them from a collection

play11:19

so first thing we'll do is declare a

play11:22

public variable that's going to be the

play11:23

reference to our enemy manager

play11:25

and we'll call it enemy manager as well

play11:31

so if you save and go into unity we have

play11:33

a new field called enemy manager

play11:35

so let's just drag in our enemy manager

play11:38

and go back in the script

play11:41

so down here in the ontrigger enter

play11:44

after we check if there's an enemy

play11:48

we're gonna say enemymanager dot

play11:51

add enemy

play11:55

and then we're gonna pass in enemy and

play11:58

that's this guy

play11:59

right here

play12:03

so we can just copy this line and we're

play12:05

gonna paste it down here on the

play12:06

ontrigger exit

play12:10

and this time it's going to be remove

play12:12

enemy

play12:14

[Music]

play12:16

now we can save and go into unity and

play12:19

we'll

play12:20

create a few more enemies here to test

play12:22

this

play12:24

so now if you test out the enemy manager

play12:27

while playing

play12:27

you'll see that our enemies are getting

play12:30

added and removed from our collection

play12:32

so once more back in our gun script and

play12:35

now that we have a way of knowing what

play12:36

enemies are in front of the player let's

play12:38

get a way to damage them so first we'll

play12:40

make our gun fire

play12:41

we'll use a public float which will be

play12:43

our fire rate

play12:45

and then we'll use a private float

play12:46

called next time to fire

play12:48

to keep track of it to get our gun to

play12:51

shoot

play12:52

it's simply an if statement saying if

play12:55

input dot get mouse button down

play13:00

and we'll use the index of zero which is

play13:02

the left mouse button

play13:05

then we'll fire

play13:10

so we'll go beneath this and we'll make

play13:12

the fire method

play13:13

and inside of it well what do we want to

play13:16

do is we want to hurt

play13:17

the enemy so once we get the enemy

play13:20

damage code in here this should be fine

play13:22

except for you can spam the mouse button

play13:25

and it's gonna fire as fast as you click

play13:27

the button

play13:27

so let's go ahead and implement our fire

play13:30

rate

play13:31

so in this if statement we'll say if our

play13:33

mouse button is pressed

play13:35

and time dot time which is the time this

play13:38

passes the game

play13:39

started is greater than next time to

play13:42

fire

play13:43

which starts out at zero's default then

play13:45

fire

play13:46

so right off the bat we'll be able to

play13:47

fire so in our fire method we need to

play13:51

reset this time so now we're going to

play13:54

say

play13:55

next time to fire equals time dot time

play13:59

and then we're going to add on to that

play14:01

our fire rate

play14:02

so every time we fire it's taking the

play14:04

time and adding on so

play14:08

when making this i didn't have a default

play14:10

uh fire rate in mind so i didn't set one

play14:13

in the script

play14:13

so we're gonna save and hop into unity

play14:16

real quick

play14:17

we'll go to the gun and we'll make sure

play14:19

that we have something assigned here for

play14:21

the fire rate

play14:21

i'm just going to use one for now and

play14:24

then our gun script and the fire

play14:26

method we're going to finally damage our

play14:29

enemies by using

play14:31

a for each statement

play14:34

and it looks like this so we have four

play14:38

each variable in a collection and we

play14:40

just so happen to have a collection

play14:42

so the variable name is enemy and we're

play14:46

going through the collection

play14:47

of enemy manager dot

play14:51

enemies and trigger and then for each

play14:55

enemy that's in the trigger

play14:56

it's gonna damage that enemy so we're

play14:59

gonna save this

play15:00

and we're gonna make one last detour

play15:03

back to the

play15:04

empty enemy strip that we made earlier

play15:13

so up here we're gonna need a private

play15:15

float and this is gonna be

play15:16

some health that we can take away from

play15:18

our enemy and we're just gonna default

play15:20

that to two

play15:22

then beneath the update function we're

play15:25

going to make a

play15:26

public void take damage

play15:32

and it's going to take in a float called

play15:34

damage and then we can set

play15:37

enemy health minus equals the damage

play15:46

and then in our update we'll have a

play15:48

death check

play15:50

and this will just be an if statement

play15:51

that says enemy health is

play15:53

less than equal to zero then you're dead

play15:55

so first we want to destroy the game

play15:57

object

play15:58

but we also want to remove this from the

play16:00

list because

play16:02

if we don't we'll get some weird errors

play16:05

with the box collider so we're gonna

play16:08

make a public

play16:09

enemy manager called enemy manager

play16:12

and then back in the update we can just

play16:14

say enemymanager.remove

play16:16

enemy and then the enemy is gonna be

play16:19

this

play16:20

so the enemy is removing itself so now

play16:24

this one's pretty much done so we can

play16:25

save it

play16:26

go back into unity so now my enemy

play16:29

component

play16:30

has a new field for enemy manager so i'm

play16:32

going to select all

play16:33

enemies that i have and i'm going to

play16:35

drag in my enemy manager

play16:38

so now the enemy manager is done and the

play16:40

enemy script is done

play16:41

for now so let's go back into our gun

play16:43

script and finish it up

play16:45

so under here where it says four each so

play16:49

for each enemy that we get in our

play16:50

collider we want to damage the enemy so

play16:52

now that there's a function

play16:54

on the enemy component we can just call

play16:55

it so we'll just say

play16:57

enemy dot take damage

play17:00

and we're going to pass in damage

play17:03

which is a variable our gun doesn't have

play17:05

yet so we'll go to the top

play17:07

and we'll make a public float called

play17:11

damage and we're going to default that

play17:13

to two and give it full damage so now we

play17:15

can save and test

play17:21

bang

play17:27

bang so you can see that it works but it

play17:29

works the walls too

play17:30

the final thing we'll be doing is a

play17:32

raycast to see

play17:34

if the enemy is in line of sight of the

play17:36

player

play17:37

so in the gun script and inside our for

play17:40

each statement we'll start constructing

play17:42

this raycast

play17:43

we'll start by needing a hit variable

play17:45

and this is going to be a raycast

play17:47

hit that we just name hit

play17:50

then we can say if physics.raycast

play17:56

and our origin is just going to be us so

play17:58

it's going to be transform.position

play18:01

and then we need a direction and getting

play18:04

our directions pretty simple

play18:06

since we have the enemies transform

play18:08

position

play18:09

so we'll say r d i r

play18:13

for direction equals

play18:16

enemy dot transform dot position

play18:19

and we'll subtract our position by using

play18:21

transform dot position

play18:24

and that should give us our direction

play18:27

so now we can say that we want it to out

play18:30

our hit

play18:31

variable and for the distance we want it

play18:34

to be the range of the gun

play18:36

but if we test this and think about it

play18:38

for a second the raycast would reach

play18:40

straight ahead all the way to the end of

play18:42

the clotter but if the enemy would say

play18:44

in this corner it would not reach

play18:46

because the ray would have to be longer

play18:48

so let's extend the range

play18:50

of the ray cast just a little bit by

play18:53

multiplying it by something like

play18:55

1.5 and then finally we'll need a layer

play18:58

mask

play18:59

and this is just going to be called

play19:01

raycast layer mask

play19:07

and we'll go up to the top and make a

play19:11

reference to this by saying public

play19:14

layer mask and it's going to be called

play19:17

raycast layer mask

play19:19

so back inside the if statement of our

play19:21

raycast so if we hit something now we're

play19:24

going to do another comparison we're

play19:25

going to say

play19:26

if hit.transform is equal to

play19:29

our enemy.transform so this goes to our

play19:32

list of enemies gets the direction

play19:34

towards the enemy

play19:35

raycasts towards it and after all that

play19:37

if it hits the enemy we can finally call

play19:39

our enemy damage function and now

play19:43

we can save this so we can go into unity

play19:46

and now we can set up our layer mask

play19:48

this box collider here is the reason we

play19:50

need the mask

play19:51

we need the raycast to ignore this

play19:53

collider so we'll go to our layer

play19:56

add new layer and we'll create one

play19:59

called gun

play20:00

and then we'll have to go back to the

play20:02

gun object to assign its layer

play20:04

as the new gun layer then we need to go

play20:07

to the gun script component

play20:08

in the inspector and for the layer mask

play20:11

we'll select default

play20:13

and this will correctly ignore our gun

play20:15

layer

play20:17

this would be easy to visualize by

play20:19

adding debug.drawarray in the code

play20:22

and we can use our origin and the

play20:24

direction that we've already calculated

play20:27

and since it happens in a fraction of a

play20:28

second we can also use

play20:30

debug.break to pause our editor so we

play20:33

can

play20:34

see what's happening so i'm gonna shoot

play20:36

this guy here

play20:37

and it paused and shows us the line so

play20:40

we continue

play20:41

so now this enemy over here by the wall

play20:44

so they're in the trigger and i'm

play20:45

spamming the button but nothing's

play20:47

happening

play20:47

and it's not until i walk around the

play20:49

corner and get line of sight that

play20:51

now the game will pause and let me know

play20:52

that i've hit this enemy

play20:54

now that we know that works we can

play20:56

delete those debug lines and i think to

play20:58

pretty much wrap up the system we can do

play21:00

a range check so enemies farther away

play21:02

can take less damage

play21:04

to do that we'll use a float for our

play21:06

distance

play21:09

and we can set that equal to vector

play21:14

3.distance

play21:18

and we want the distance from the enemy

play21:20

transform to our transform

play21:23

then we can use that float in an if

play21:24

statement saying

play21:26

if our distance is greater than our

play21:29

range times 0.5 so i'm saying if our

play21:32

distance

play21:33

is greater than half of our range

play21:36

then we're going to damage the enemy's

play21:38

sum else if the enemy is in the first

play21:41

half of our box collider that means it's

play21:43

closer and we're gonna deal a lot of

play21:44

damage

play21:45

so we're gonna grab this enemy.take

play21:47

damage function

play21:48

and we're gonna paste it in both

play21:50

conditions and in the true condition

play21:53

we'll set this to small damage

play21:58

and for the false statement we'll go

play22:00

with big damage

play22:07

and back up at the top we'll change our

play22:09

regular damage

play22:10

to big damage since it's already set at

play22:12

two and our enemy only has two health

play22:15

and then we'll make a new flow for small

play22:16

damage and we'll default that to one

play22:19

so i'll look over the script one last

play22:21

time and then up here we're gonna add a

play22:24

comment for this line

play22:26

and now we can save and go back into

play22:29

unity

play22:30

so let's check over the gun script and

play22:31

make sure all the variables are assigned

play22:34

and make sure that all of your enemies

play22:36

have the enemy manager assigned

play22:38

so now if we test we should have our

play22:40

enemy detection system fully working

play22:43

we have a gun we have enemies we can

play22:45

shoot them on level ground

play22:46

and elevated or lowered positions as

play22:49

long as we can see them

play22:50

and they can take damage with two

play22:52

different versions of damage from

play22:54

here we have a good base for everything

play22:56

else so until next time spine camp out

Rate This

5.0 / 5 (0 votes)

相关标签
游戏开发Doom风格枪械机制敌人AI目标系统射线检测玩家动量Unity3D脚本编程游戏测试