作者:风晓融冰

原文:http://www.taidous.com/forum.php?mod=viewthread&tid=28412

 

尽管随机运动可能完全不可预知,它还是相当无趣的,因为它完全是以相同的方式工作——完全随机。下面要学习到的算法是根据具体环境作出不同响应的处理。作为例子,这里选择了追踪算法。追踪AI考虑到跟踪目标的位置,然后改变AI对象的轨道好让它移向被追踪的对象。

追踪可以是将方向矢量直接指向目标,或者采用跟真实的模型,使得物体像导弹那样行动。

 

 
本文将的就是第一种,直接矢量追踪,效果如下图所示
 

 

通过键盘方向键控制幽灵,然后蚊子会追踪幽灵,在这里我做了一些界面处理,当蚊子或者幽灵运动超过了屏幕范围的时候让它们出现在屏幕的另一边而不是消失在屏幕上,代码如下:
 
[AppleScript] 纯文本查看 复制代码
using unityEngine;
using System.Collections;
using UnityEngine.UI;

public class AITrack : MonoBehaviour {
    public Image target;
    public float moveSpeed;//追踪目标移动速度
    public float targetSpeed;//追踪速度
    public float target_x;//追踪移动的单位量
    public float target_y;
        // Use this for initialization
        void Start () {
            
        }
        // Update is called once per frame
        void Update () {
        MoveTarget();
        Track_AI();
        }
    void Track_AI()
    {
        //x方向的追踪
        if(target.transform.position.x>this.transform.position.x)
        {
            this.transform.position += new Vector3(target_x, 0, 0)*targetSpeed;
        }
        else if(target.transform.position.x<this.transform.position.x)
        {
            this.transform.position -= new Vector3(target_x, 0, 0)*targetSpeed;
        }
        //y方向的追踪
        if(target.transform.position.y>this.transform.position.y)
        {
            this.transform.position += new Vector3(0, target_y, 0)*targetSpeed;
        }
        else if(target.transform.position.y<this.transform.position.y)
        {
            this.transform.position -= new Vector3(0, target_y, 0)*targetSpeed;
        }
        //检测是否超出了边界
        if(this.transform.position.x>=Screen.width)
        {
            this.transform.position = new Vector3(-this.GetComponent<Image>().rectTransform.lossyScale.x, 0, 0);
        }
        else if(this.transform.position.x<-this.GetComponent<Image>().rectTransform.lossyScale.x)
        {
            this.transform.position = new Vector3(Screen.width, this.transform.position.y, 0);
        }
        if(this.transform.position.y>=Screen.height)
        {
            this.transform.position = new Vector3(this.transform.position.x,-this.GetComponent<Image>().rectTransform.lossyScale.y, 0);
        }
        else if(this.transform.position.y<-this.GetComponent<Image>().rectTransform.lossyScale.y)
        {
            this.transform.position = new Vector3(this.transform.position.x, Screen.height, 0);
        }
    }
    void MoveTarget()
    {
        float x = Input.GetAxis("Horizontal")*100;
        float y = Input.GetAxis("Vertical")*100;

        target.transform.Translate(x*Time.deltaTime*moveSpeed,y*Time.deltaTime*moveSpeed,0);
        //如果超出屏幕范围则让它出现在另一面
        if (target.transform.position.x >= Screen.width)
        {
            //使用了Image的target.rectTransform.lossyScale.x来表示显示的图片宽度
            target.transform.position = new Vector3(-target.rectTransform.lossyScale.x, target.transform.position.y, 0);
        }
        else if(target.transform.position.x<-target.rectTransform.lossyScale.x)
        {
            target.transform.position = new Vector3(Screen.width, target.transform.position.y, 0);
        }
        if(target.transform.position.y>=Screen.height)
        {
            target.transform.position = new Vector3(target.transform.position.x, -target.rectTransform.lossyScale.y, 0);
        }
        else if(target.transform.position.y<-target.rectTransform.lossyScale.y)
        {
            target.transform.position = new Vector3(target.transform.position.x, Screen.height, 0);
        }
    }
}



另外本例中使用到了一段读取Sprite制作动画的代码,如下:
本帖隐藏的内容

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public enum AnimPalyStyle : byte
{
    Once, Loop, Poop
}
public class SpriteAnim : MonoBehaviour {
    public Image image;
    private List<Sprite> m_sprites=new List<Sprite>();
    public string path;
    public float playSpeed;
    public AnimPalyStyle playStyle;
    public int MaxFrame;
        // Use this for initialization
        void Start () {
        
        }
        void OnEnable()
    {
        StartCoroutine(LoadSprites(MaxFrame, path));
    }
        // Update is called once per frame
        void Update () {
        
        }
    IEnumerator LoadSprites(int max,string name)
    {
        Sprite tempSprite;
        int j = 0;
        int nameLenght = name.Length;
        for (; j < max; j++)
        {
            name = name.Substring(0, nameLenght - j.ToString().Length + 1) + j;
            tempSprite = Resources.Load<Sprite>(name);
            yield return new WaitForSeconds(playSpeed);
            image.sprite = tempSprite;
            if (!m_sprites.Contains(tempSprite))
            {
                m_sprites.Add(tempSprite);
            }

            if (playStyle == AnimPalyStyle.Once)
            {
                this.enabled = false;
            }
        }
        j = 0;
        if (playStyle == AnimPalyStyle.Loop)
        {
            for (; j < max; j++)
            {
                yield return new WaitForSeconds(playSpeed);
                image.sprite = m_sprites[j];
                if (j == max - 1)
                {
                    j = 0;
                }
            }
        }
        else if (playStyle == AnimPalyStyle.Poop)
        {
            while (true)
            {
                while (j < max)
                {
                    if (j == -1) j = 0;
                    yield return new WaitForSeconds(playSpeed);
                    image.sprite = m_sprites[j];
                    j++;
                }
                while (j > -1)
                {
                    if (j == max) j = max - 1;
                    yield return new WaitForSeconds(playSpeed);
                    image.sprite = m_sprites[j];
                    j--;
                }
            }
        }
    }
}

本例中使用的是unity5.1.1

工程下载地址:

http://www.taidous.com/forum.php?mod=viewthread&tid=28412