是不是被上节的理论知识弄到头大?怀念使用
unity
的日子吧?哈哈……这节开始我们就要用以前学到的知识在unity中应用啦。今天我们先做一个简单的你追我跑的智能逻辑。程序的功能大概是这样的,场景中有一个角色和N个敌人。N个敌人根据角色的位置判断自己是该停止还是该躲避(逃跑)。如果角色距离某一个敌人距离小于该角色害怕(开始逃避)的距离,则敌人开始逃跑。否则,敌人保持站立。
1. 首先新建一个场景,在场景中新建一个Plane,命名为floor作为地面,然后创建一个点光源,调节点光源的位置和范围,照亮整个场景(这里作为我们教程的标配场景,以后新建一个场景如无特别说明,都以此场景为准)。完成场景如图:
2.导入所需要的敌人和角色的模型,这里提一点大家导入模型的时候注意的,在导模型的时候,一定先把模型贴图导进来,也就是拷贝到工程目录下。然后再拷贝模型,这样就不会出现贴图丢失的问题了。模型大家可以自己做也可以上网找,需要有两个动画状态的文件,一个是静止站立(idle)的,一个是跑步(run)。这里的动画设置问题,大家可以参考论坛的公开课教学。我就不多说了。
3.把导入的模型拖到场景中,为它们添加角色控制器代码(CharacterController),如果找不到这个脚本,说明你没有导入角色控制器插件包,在工程视图点击右键,import package-->Character Controller。注意把这个代码添加到所有的需要运动的角色身上,这里指一个角色模型,和N个敌人的模型。现在万事具备,只差让他们动起来了。场景完成如图:这里灰色的机器人是我们能够控制的角色,四个红色的机器人是敌人角色。
4.由于角色运动是需要我们控制的,而敌人的运动是根据角色的位置自动判断的。所以我们只需要编写控制角色移动的代码即可。
首先我们要考虑角色移动方式,这里角色主要根据玩家按键是前后移动,并在移动的同时播放跑步动画。
首先是控制动画播放,新建一个C#代码PlayerAnim_CS。它的主要功能是根据玩家按键,控制角色播放相应的动画。
首先在开始的函数中添加如下代码:animation.wrapMode = WrapMode.Loop; //控制动画播放方式为循环播放在Update函数中,我们希望系统能够实时检测用户输入,根据用户输入播放响应动画:
5. 控制角色前后移动,新建一个C#代码RobotController_CS 定义变量:
然后在FixedUpdate中添加如下方法:
到现在为止,我们已经完成了角色的控制方法,把PlayerAnim_CS和RobotController_CS 添加给角色,并确保角色已经添加了CharacterController。点击运行,按下上下方向键或者W、S键,即可看到角色已经动起来了。
6.大家可能已经发现,现在只有角色自己在动,场景中其他的敌人并没有运动。我们来为敌人角色添加代码,让他们能够感知到角色的位置,并及时作出逃跑的动作。新建C#代码NeutralBot_CS。定义如下变量:
首先在Awake函数中获取敌人的角色控制器 controller = GetComponent<CharacterController>();
在update函数中,我们首先要判断敌人当前所处状态,然后根据状态作出相应反应
确保编译没有错误,将NeutralBot_CS代码添加到敌人物体这里指四个红色机器人身上,保存场景,运行程序。可以按下W键向前跑动机器人查看效果。最终结果如图:
本节我们通过一个实例讲解了如何通过距离判断角色运动状态的方法,并学习了播放动画的方式,动画播放速度控制等知识。大家可以自己做一个追击的小demo试验一下。
1. 首先新建一个场景,在场景中新建一个Plane,命名为floor作为地面,然后创建一个点光源,调节点光源的位置和范围,照亮整个场景(这里作为我们教程的标配场景,以后新建一个场景如无特别说明,都以此场景为准)。完成场景如图:
2.导入所需要的敌人和角色的模型,这里提一点大家导入模型的时候注意的,在导模型的时候,一定先把模型贴图导进来,也就是拷贝到工程目录下。然后再拷贝模型,这样就不会出现贴图丢失的问题了。模型大家可以自己做也可以上网找,需要有两个动画状态的文件,一个是静止站立(idle)的,一个是跑步(run)。这里的动画设置问题,大家可以参考论坛的公开课教学。我就不多说了。
3.把导入的模型拖到场景中,为它们添加角色控制器代码(CharacterController),如果找不到这个脚本,说明你没有导入角色控制器插件包,在工程视图点击右键,import package-->Character Controller。注意把这个代码添加到所有的需要运动的角色身上,这里指一个角色模型,和N个敌人的模型。现在万事具备,只差让他们动起来了。场景完成如图:这里灰色的机器人是我们能够控制的角色,四个红色的机器人是敌人角色。
4.由于角色运动是需要我们控制的,而敌人的运动是根据角色的位置自动判断的。所以我们只需要编写控制角色移动的代码即可。
首先我们要考虑角色移动方式,这里角色主要根据玩家按键是前后移动,并在移动的同时播放跑步动画。
首先是控制动画播放,新建一个C#代码PlayerAnim_CS。它的主要功能是根据玩家按键,控制角色播放相应的动画。
首先在开始的函数中添加如下代码:animation.wrapMode = WrapMode.Loop; //控制动画播放方式为循环播放在Update函数中,我们希望系统能够实时检测用户输入,根据用户输入播放响应动画:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
if
(Input.GetAxis(
"Vertical"
)>0.2f)
//向前移动
{
animation[
"run"
].speed = 1.0f;
//动画播放速度
animation.CrossFade(
"run"
);
//播放向前跑动动画
}
else
if
(Input.GetAxis(
"Vertical"
)<-0.2f)
//向后移动
{
animation[
"run"
].speed = -1.0f;
animation.CrossFade(
"run"
);
}
else
{
animation.CrossFade(
"idle"
);
//静止状态
}
}
|
5. 控制角色前后移动,新建一个C#代码RobotController_CS 定义变量:
[C#]
纯文本查看
复制代码
1
2
3
|
public
int
speed = 6;
public
int
gravity = 20;
private
Vector3 moveDirection = Vector3.zero;
|
然后在FixedUpdate中添加如下方法:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
void
FixedUpdate()
{
CharacterController controller = GetComponent<CharacterController>();
if
(controller.isGrounded)
{
//只计算Z轴方向的位移
//也可以根据需要控制左右移动,现在为了简单考虑,我们没有做左右移动的控制
moveDirection =
new
Vector3(0, 0, Input.GetAxis(
"Vertical"
));
moveDirection = transform.TransformDirection(moveDirection);
//叠加移动速度,以便我们能在编辑器窗口中控制角色移动速度。
moveDirection *= speed;
}
//根据鼠标X轴向,控制角色左右旋转
float
rotateY = (Input.GetAxis(
"Mouse X"
) * 200) * Time.deltaTime;
controller.transform.Rotate(0, rotateY, 0);
moveDirection.y -= gravity * Time.deltaTime;
controller.SimpleMove(moveDirection * Time.deltaTime);
}
|
到现在为止,我们已经完成了角色的控制方法,把PlayerAnim_CS和RobotController_CS 添加给角色,并确保角色已经添加了CharacterController。点击运行,按下上下方向键或者W、S键,即可看到角色已经动起来了。
6.大家可能已经发现,现在只有角色自己在动,场景中其他的敌人并没有运动。我们来为敌人角色添加代码,让他们能够感知到角色的位置,并及时作出逃跑的动作。新建C#代码NeutralBot_CS。定义如下变量:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public
float
awareDistance = 15.0f;
//敌人意识到角色的距离
public
float
scaredDistance = 10.0f;
//敌人开始逃跑的距离
public
Transform player;
//角色
public
float
runSpeed = 4.0f;
//逃跑速度
public
enum
AIStatus { Idle=0,Scared=1}
//敌人状态,静止和害怕
private
AIStatus status = AIStatus.Idle;
CharacterController controller;
//敌人本身的角色控制器
private
Vector3 moveDirection = Vector3.zero;
|
首先在Awake函数中获取敌人的角色控制器 controller = GetComponent<CharacterController>();
在update函数中,我们首先要判断敌人当前所处状态,然后根据状态作出相应反应
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
|
void
Update()
{
CheckStatus();
//检查角色状态的函数
switch
(status)
//根据不同状态作出相应行动
{
case
AIStatus.Idle:
//静止
Idle();
break
;
case
AIStatus.Scared:
//逃跑
RunAway();
break
;
default
:
break
;
}
}
//逃跑方法
private
void
RunAway()
{
transform.eulerAngles =
new
Vector3(transform.eulerAngles.x, -player.transform.eulerAngles.y,transform.eulerAngles.z);
moveDirection =
new
Vector3(0, 0, 40);
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= runSpeed;
controller.SimpleMove(moveDirection * Time.deltaTime);
animation.CrossFade(
"run"
);
}
//静止方法
private
void
Idle()
{
animation.CrossFade(
"idle"
);
}
//根据自身和角色的距离,判断出自己是该逃跑还是该静止。
private
void
CheckStatus()
{
float
dist = (player.position - transform.position).magnitude;
if
(dist<scaredDistance)
{
status = AIStatus.Scared;
}
else
if
(dist>awareDistance)
{
status = AIStatus.Idle;
}
}
|
确保编译没有错误,将NeutralBot_CS代码添加到敌人物体这里指四个红色机器人身上,保存场景,运行程序。可以按下W键向前跑动机器人查看效果。最终结果如图:
本节我们通过一个实例讲解了如何通过距离判断角色运动状态的方法,并学习了播放动画的方式,动画播放速度控制等知识。大家可以自己做一个追击的小demo试验一下。