近期热门
粉丝2
关注 0
获赞 0
增加敌人并添加AI---射击游戏系列教程之四

[U3D] 增加敌人并添加AI---射击游戏系列教程之四

[复制链接]
5521 1 0 0 12年前 举报
在本章节中,我们给场景中增加敌人,并赋予其AI,在前面的几节中,角色的控制及运动已构建完成,接下来我们需要做的就是在此基础上,创建敌人prefab并增加AI部分,使其能发现并攻击玩家角色。
We're ready to start coding our enemy AI. Now that our movement and animation framework is
already in place, all we really need to is fill our FindAIinput function with code and add a new enemy
prefab to our game.
创建一个新的prefab,将其命名为:EnemyPrefab,在层级列表中,选择Player并复制,将复制的物体重命名为enemy,在属性面板中,将新物体的tag改为untagged,这是为了将其与Player分别开来。现在我们有了一个全新的角色敌人。
Firstly prefabs. Hopefully you have browsed through the Unity tutorials enough to understand what a
prefab is. Let's create a new prefab, right click in our project window and select (create – prefab) and
name it something like EnemyPrefab.
Now duplicate your player object, click it and press CTRL-D, name it to something like 'enemy'. Make
sure you change the enemies 'tag' to 'untagged' in the inspector when you highlight it otherwise you'll
just be creating another player. Move your enemy to another location away from your player, run your
game and you have a brand new character object.
此外将角色的碰撞体半径设为0.45是比较合适的,将敌人的碰撞体半径设为0.25,看来我们的角色要比敌人雄壮一些。现在我们需要创建材质更换贴图并将其赋予“enemy ”敌人物体,省事的办法是直接复制角色的材质,将此新材质重命名为"EnemyMaterial",同理,其动作也是通过播放一张贴图序列来实现的,所以我们将此材质的贴图更换为EnemySpriteSheet.png,下面设置相关的参数,首先要关闭EnemySpriteSheet.png图片的Generate Mip Maps选项,然后将贴图的XYtiling更改为-0.2和-0.167.
At this point feel free to play around with your Capsule Collider component on your player and enemy,
I found a radius of 0.45 to be good. Now your characters will collide with more correct collision.
Now you can create a new material, by duplicating the player material and naming it EnemyMaterial.
And giving it the texture EnemySpriteSheet.png. Just remember to turn off Generate Mip Maps for the
texture otherwise your enemy character might look blurry. Add your EnemyMaterial to your enemies
MeshRenderer Material, and give it an X tiling of -0.2 and a Y tiling of -0.167.
Set the radius of your enemies Capsule Collider to 0.25.
更改下面的两个变量值,在层级列表中,选中“enemy ”,并拖动到项目面板中我们前面创建的“EnemyPrefab”上,OK,敌人模板创建完成,这样你就可以使用大量的敌人而不必一个一个的去创建。
Also change your public enemies animation variables as follows:
animationFrameRate = 15;
spriteSheetTotalHigh = 6;
Now click and drag your enemy object from your Hierarchy to your EnemyPrefab in your project
window. And voila you have your prefab! Now whatever you do make sure your enemy objects are
always connected to your prefab, let them go and any changes you make to your prefab, global variable
values etc, wont follow through consistently to each prefab and it can get very annoying if you placed
lots of enemies.
Any changes you make to your enemies later on, either make them to the prefab itself, or if you make
the changes to one of the objects in your scene, but want the changes to be made to all your objects in
your scene, drag your object again onto your prefab and the changes you made on that one object will
be applied to your prefab and all objects using that prefab.
Run your game and your Alien enemy should be standing there if all has worked well and good.
Now to make your enemy run towards the player!
接下来我们添加一段代码,使敌人朝着玩家跑去,
Add the following to FindAIinput:
void FindAIinput ()
{
inputMovement = objPlayer.transform.position - transform.position;
inputRotation = inputMovement; // face the direction we are moving
}
It's that simple! What wonderful framework we've put in place. The direction we need to move to is
the Vector from our position 'transform.position' to the player's position ' objPlayer.transform.position'.
Time to implement melee attacks.
Remember back in our ProcessAnimation function how we commented out a few lines involving a
'meleeAttackState' variable? Uncomment that code and add the following variable to your script:
//input variables (variables used to process and handle input)
private Vector3 inputRotation;
private Vector3 inputMovement;
private bool meleeAttackState;
Now make the following changes to your FindAIinput function:
void FindAIinput ()
{
inputMovement = objPlayer.transform.position -
transform.position;
inputRotation = inputMovement; // face the direction we are
moving, towards the player
meleeAttackState = false;
if
( Vector3.Distance(objPlayer.transform.position,transform.position) < 1.2f )
{
meleeAttackState = true;
inputMovement = Vector3.zero;
if (currentAnimation != animationMelee) { frameNumber
= meleeAnimationMin + 1; }
}
}
敌人物体的AI,其实就是各种条件及状态的判断,首先要设定一个感应范围,并监测敌人物体的当前帧,使其动作保持完整的循环。
Firstly we are setting meleeAttackState to false so that we don't melee if we are too far away from the
player. Next we are checking to see our distance from the Player, if we are within 1.2 units (the f is
there because the function Vector3.Distance returns a floating point number. We then set
meleeAttackState to true. We set each x,y and z value of inputMovement to 0. And if we are not
playing the melee animation we set the current frame to be at the beginning of the animation. If we
didn't set it to play at the beginning it might start half way through the animation. We didn't need to do
it for cyclic animations because they would just loop but this animation needs to play from start to
finish. We don't need the +1 added to frameNumber, I just noticed on my pc the animation plays better
starting a little bit into it.
Now make the following changes to your FindAnimation function:
void FindAnimation ()
{
if (meleeAttackState == true || currentAnimation == animationMelee)
{
currentAnimation = animationMelee;
return;
}if (
inputMovement.magnitude >
0)
{
currentAnimation = animationWalk;
} else {
currentAnimation = animationStand;
}
}
We check to see if meleeAttackState is true and if it is we will begin playing the melee animation, we
also check to see if we have not yet finished playing the melee animation, even if meleeAttackState is
set to false we will still play the melee animation if we haven't reached the end of it yet.
We add the return command to stop the currentAnimation variable being set below.
And now the code we uncommented before:
if (currentAnimation == animationMelee)
{
frameNumber =
Mathf.Clamp(frameNumber,meleeAnimationMin,meleeAnimationMax+1);
if (frameNumber > meleeAnimationMax)
{
if (meleeAttackState == true)
{
frameNumber = meleeAnimationMin;
} else {
currentAnimation = animationWalk;
frameNumber = walkAnimationMin;
}
}
}
此部分添加的代码并不是很多,可以直接拷贝添加我们的脚本文件中,当然,手动输入更有助于理解其作用。保存场景,此部分结束。准备进入下一部分的制作。uke翻译整理,转载请注明出处:unity3d8.com
Firstly we check to see if frameNumber has reached the end of the animation, we then check to see if
the enemy is still close to the player, if we are still close reset the animation to play from the beginning.
But if we are far away from the player go and play our walk animation, keep in mind that previous I
had it set to the stand animation here. If the alien is always walking or meleeing it will never actually
play the stand animation, in this old case the stand animation would have played for one frame before
being set to the walk animation, I changed it back here to the walk animation to make the transition
from the end of the melee animation straight to the walk animation for a better transition.
Now we have enemies that will chase the player and attack near proximity. Right now there is no
damage being applied to the player when this happens, and we could add a bit of a push back that
happens when the enemy hits a player. We will cover these things in a later tutorial. For now our next
tutorial is to add weapons so that the player can shoot and destroy the aliens.
Don't Forget to save your scene Goto > File > Save Scene.
Time to implement projectiles!
0
点赞
0
打赏
0
添加到收藏夹

0

点击复制链接

使用微信扫码分享
一次扣10个券
全部评论1
您需要登录后才可以回帖 登录

赞一个
10年前
回复

使用道具 举报

您当前使用的浏览器IE内核版本过低会导致网站显示错误

请使用高速内核浏览器或其他浏览器