孙广东 2015.8.15 一、Enemy Aim Ai
这种效应可以创建的 Lerping 旋转角度对玩家的敌人。这种情况是在动作游戏,敌人跟随,目的是何地然后射球员的情况下非常有用。对敌人遵循概念是在早些时候发布的博客中已经讨论过。在推行针对在游戏的同时,理解四元数的概念是非常必要的。 四元数存储对象的旋转,还可以计算价值取向。一个可以直接玩欧拉角,但可能会出现 万向锁 的情况。 根据当地的坐标系统,如果你旋转模型X 轴,然后其 Y 和 Z 轴经验万向节锁被'锁定'在一起。 现在回到我们的主题,给出了下面是一个简单的例子来解释 Enemy aim AI 按照下面给出的步骤。 1、创建Cube将作用在player control
TargetMovementScript.cs public class TargetMovementScript : MonoBehaviour {
public float targetSpeed=9.0f;//Speed At Which the Object Should Move
void Update ()
transform.Translate (Input.GetAxis ('Horizontal')*Time.deltaTime*targetSpeed,Input.GetAxis ('Vertical')*Time.deltaTime*targetSpeed,0);
}
} 2、创建一个Enemy对象,由箭头和Cube组成, 1、应用适当的材料对Cube 。 2、使箭头Sprite作为一个不同的对象 3、其方向由 Cube指出 . 所以在这里,箭头将充当了敌人的枪。 4、此箭头将指向目标对象和它看起来就好像它试图锁定目标 5、我们也可以操纵速度,敌人将能够锁定目标属性 ;作为不同的敌人应该是不同的困难,以及不同的功能。 EnemyAimScript.cs public class EnemyAimScript : MonoBehaviour {
public Transform target; // Target Object
public float enemyAimSpeed=5.0f; // Speed at Which Enenmy locks on the Target
Quaternion newRotation;
float orientTransform;
float orientTarget;
void Update () {
orientTransform = transform.position.x;
orientTarget = target.position.x;
// To Check on which side is the target , i.e. Right or Left of this Object
if (orientTransform > orientTarget) {
// Will Give Rotation angle , so that Arrow Points towards that target
newRotation = Quaternion.LookRotation (transform.position - target.position, -Vector3.up);
}
else {
newRotation = Quaternion.LookRotation (transform.position - target.position,Vector3.up);
}
// Here we have to freeze rotation along X and Y Axis, for proper movement of the arrow
newRotation.x = 0.0f;
newRotation.y = 0.0f;
// Finally rotate and aim towards the target direction using Code below
transform.rotation = Quaternion.Lerp (transform.rotation,newRotation,Time.deltaTime * enemyAimSpeed);
// Another Alternative
// transform.rotation = Quaternion.RotateTowards(transform.rotation,newRotation, Time.deltaTime * enemyAimSpeed);
}
} 7、Hierarchy 和 Scene View 可能会像作为给定下面 备注:-
二、通过有限状态机实现AI Contents Objective Step - 1: Set up the scene Step - 2: Create and place Game Objects Step - 3: Implement the BoxMovement Script Step - 4: FSM Modelled Script Step - 5: AI Script for the Box - 目的: 这篇文章的主要目的是要给你一个关于如何使用有限状态机模型在 实现 AI 。
Step - 1: Set up the scene 以一个平面和两个Box在场景中,如下图所示的设置。 Step - 2: Create and place Game Objects 创建空的游戏对象并将其作为游子点Wanderer Points。放置这些空的游戏对象下,为您选择平面周围。在这里蓝色的Cube是 AI Cube和红一个是玩家控制的Cube。将它们放在距离不够远。 Step - 3: Implement the BoxMovement Script 实现 BoxMovement 脚本来控制玩家的Cube的移动:如下: public class BoxMovementScript : MonoBehaviour
{
public float speed = 0.1f;
private Vector3 positionVector3;
void Update ()
{
InitializePosition ();
if (Input.GetKey (KeyCode.LeftArrow)) {
GoLeft ();
}
if (Input.GetKey (KeyCode.RightArrow)) {
GoRight ();
}
if (Input.GetKey (KeyCode.UpArrow)) {
GoTop ();
}
if (Input.GetKey (KeyCode.DownArrow)) {
GoDown ();
}
RotateNow ();
}
private void InitializePosition ()
{
positionVector3 = transform.position;
}
private void RotateNow ()
{
Quaternion targetRotation = Quaternion.LookRotation (transform.position - positionVector3);
transform.rotation = targetRotation;
}
private void GoLeft ()
{
transform.position = transform.position new Vector3 (-speed, 0, 0);
}
private void GoRight ()
{
transform.position = transform.position new Vector3 (speed, 0, 0);
}
private void GoTop ()
{
transform.position = transform.position new Vector3 (0, 0, speed);
}
private void GoDown ()
{
transform.position = transform.position new Vector3 (0, 0, -speed);
}
} Step - 4: FSM Modelled Script 构建FSM模型脚本: public class FSM : MonoBehaviour
{
//Player Transform
protected Transform playerTransform;
//Next destination position of the Box
protected Vector3 destPos;
//List of points for patrolling
protected GameObject[] pointList;
protected virtual void Initialize (){
}
protected virtual void FSMUpdate (){
}
protected virtual void FSMFixedUpdate (){
}
void Start ()
{
Initialize ();
}
void Update ()
{
FSMUpdate ();
}
void FixedUpdate ()
{
FSMFixedUpdate ();
}
}
Step - 5: AI Script for the Box 构建 AI 脚本作为Box扩展. public class BoxFSM : FSM
{
public enum FSMState
{
None,
Patrol,
Chase,
}
//Current state that the Box is in
public FSMState curState;
//Speed of the Box
private float curSpeed;
//Box Rotation Speed
private float curRotSpeed;
//Initialize the Finite state machine for the AI Driven Box
protected override void Initialize ()
{
curState = FSMState.Patrol;
curSpeed = 5.0f;
curRotSpeed = 1.5f;
//Get the list of points
pointList = GameObject.FindGameObjectsWithTag ('WandarPoint');
//Set Random destination point for the patrol state first
FindNextPoint ();
//Get the target enemy(Player)
GameObject objPlayer = GameObject.FindGameObjectWithTag ('Player');
playerTransform = objPlayer.transform;
if (!playerTransform)
print ('Player doesn't exist.. Please add one ' 'with Tag named 'Player'');
}
//Update each frame
protected override void FSMUpdate ()
{
switch (curState) {
case FSMState.Patrol:
UpdatePatrolState ();
break;
case FSMState.Chase:
UpdateChaseState ();
break;
}
}
protected void UpdatePatrolState ()
{
//Find another random patrol point on reaching the current Point
//point is reached
if (Vector3.Distance (transform.position, destPos) <= 2.5f) {
print ('Reached to the destination point\n' 'calculating the next point');
FindNextPoint ();
}
//Check the distance with player Box
//When the distance is near, transition to chase state
else if (Vector3.Distance (transform.position, playerTransform.position) <= 15.0f) {
print ('Switch to Chase State');
curState = FSMState.Chase;
}
//Rotate to the target point
Quaternion targetRotation = Quaternion.LookRotation (destPos - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, Time.deltaTime * curRotSpeed);
//Go Forward
transform.Translate (Vector3.forward * Time.deltaTime * curSpeed);
}
protected void FindNextPoint ()
{
print ('Finding next point');
int rndIndex = Random.Range (0, pointList.Length);
float rndRadius = 5.0f;
Vector3 rndPosition = Vector3.zero;
destPos = pointList [rndIndex].transform.position rndPosition;
//Check Range to Move and decide the random point
//as the same as before
if (IsInCurrentRange (destPos)) {
rndPosition = new Vector3 (Random.Range (-rndRadius, rndRadius), 0.0f, Random.Range (-rndRadius, rndRadius));
destPos = pointList [rndIndex].transform.position rndPosition;
}
}
protected bool IsInCurrentRange (Vector3 pos)
{
float xPos = Mathf.Abs (pos.x - transform.position.x);
float zPos = Mathf.Abs (pos.z - transform.position.z);
if (xPos <= 8 && zPos <= 8)
return true;
return false;
}
protected void UpdateChaseState ()
{
//Set the target position as the player position
destPos = playerTransform.position;
//Check the distance with player Box When
float dist = Vector3.Distance (transform.position, playerTransform.position);
//Go back to patrol as player is now too far
if (dist >= 15.0f) {
curState = FSMState.Patrol;
FindNextPoint ();
}
//Rotate to the target point
Quaternion targetRotation = Quaternion.LookRotation (destPos - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, Time.deltaTime * curRotSpeed);
//Go Forward
transform.Translate (Vector3.forward * Time.deltaTime * curSpeed);
}
} 此脚本适用于Cube是要跟随玩家,不要忘记把player标记Tag为 Player 和 Tag 为 WandarPoint,现在如 FSMUpdate() 所示的脚本将调用方法,这在子类中重写和它将在每个 update () 上执行。 在这里switch case被实施 将用于执行的当前状态的操作。 因此扩展 AI 是很简单的仅仅通过添加新的state。Initialize() 方法也重写,并将在 start () 方法中调用执行。UpdatePatrolState() 将在每次更新上执行,当当前状态是patrol 周围巡逻,也将会发生在 UpdateChaseState(),当玩家在接近度 AI Box。如果当处于巡逻,玩家进来的 AI Box中,状态将更改为 巡逻,相同 类型的检查仍在 追逐模式检查如果球员已远离其视野范围, 然后切换回巡逻状态, 在每个更新,检查状态更改。 结论: FSM 的很容易理解和实现,Fsm 可以用于执行复杂的 AI 。他们也可以表示使用图,允许开发人员很容易理解,因此开发人员可以调整、 改变和优化的最终结果。有限状态机使用的函数或方法来代表状态执行是简单、 功能强大、 易于扩展。 可以使用基于堆栈的状态机,确保易于管理和稳定的 执行流,而不会产生消极影响的代码应用甚至更复杂的 AI。 所以让你的敌人更聪明使用有限状态机,让您的游戏的成功。 |
|
来自: W_R_F > 《KnowLedge》