UnityAI——动物迁徙中的跟随实现实例(二)

简介: UnityAI——动物迁徙中的跟随实现实例

第三步

创建一个空物体,起名为follersGenerator,用于生成跟随者,并添加脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateBotsForFollowLeader : MonoBehaviour
{
    public GameObject botPrefab;
    public GameObject leader;
    public int botCount;
    public float minX = -5f;
    public float maxX = 5.0f;
    public float minZ = -5.0f;
    public float maxZ = 5.0f;
    public float Yvalue = 1.026003f;
    void Start()
    {
        Vector3 spawnPosition;
        GameObject bot;
        for(int i = 0; i < botCount; i++)
        {
            spawnPosition = new Vector3(Random.Range(minX, maxX), Yvalue, Random.Range(minZ, maxZ));//随机产生一个生成位置
            bot = Instantiate(botPrefab, spawnPosition, Quaternion.identity) as GameObject;
            bot.GetComponent<SteeringForLeaderFollowing>().leader = leader;
            bot.GetComponent<SteeringForEvade>().target = leader;
            bot.GetComponent<SteeringForEvade>().enabled = false;
            bot.GetComponent<EvadeController>().leader = leader;
        }
    }
}

第四步

创建一个方块预设,作为跟随者,挂上下列脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AILocomotion : Vehicle
{
    private CharacterController controller;  //AI�Ľ�ɫ������
    private Rigidbody theRigidbody;
    private Vector3 moveDistance;//AI��ɫÿ�ε��ƶ�����
    void Start()
    {
        controller = GetComponent<CharacterController>();
        theRigidbody = GetComponent<Rigidbody>();
        moveDistance = new Vector3(0, 0, 0);
        base.Start();//���û����start��������������ij�ʼ��
    }
    //������ز�����FixedUpdate�и���
    void FixedUpdate()
    {
        velocity += acceleration * Time.fixedDeltaTime;//�����ٶ�
        if (velocity.sqrMagnitude > sqrMaxSpeed)   //��������ٶ�
        velocity = velocity.normalized * maxSpeed;
        moveDistance = velocity * Time.fixedDeltaTime;
        if (isPlanar)  
        {
            velocity.y = 0;
            moveDistance.y = 0;
        }
        if (controller != null)//����Ѿ�ΪAI��ɫ���ӽ�ɫ����������ô���ý�ɫ������ʹ���ƶ�
            controller.SimpleMove(velocity);
        //�����ɫ��û��ɫ��������ҲûRigidbody
        //����Rigidbody����Ҫ�ɶ���ѧ�ķ�ʽ�������ƶ�
        else if (theRigidbody == null || !theRigidbody.isKinematic)
            transform.position += moveDistance;
        else //��Rigidbody���ƽ�ɫ���˶�
            theRigidbody.MovePosition(theRigidbody.position+moveDistance);
        if(velocity.sqrMagnitude>0.00001)//���³�������ٶȴ���һ����ֵ��Ϊ�˷�ֹ������
        {
            Vector3 newForward = Vector3.Slerp(transform.forward, velocity, damping * Time.deltaTime);
            if(isPlanar)
                newForward.y = 0;
            transform.forward = newForward;
        }
        //�������߶���
        gameObject.GetComponent<Animation>().Play("walk");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForArrive : Steering
{
    public bool isPlanar = true;
    public float arrivalDistance = 0.3f;
    public float characterRadius = 1.2f;
    public float slowDownDistance;
    public GameObject target;
    private Vector3 desiredVelocity;//预期速度
    private Vehicle m_vehicle;//获得被操控的AI角色
    private float maxSpeed;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
        isPlanar = m_vehicle.isPlanar;
    }
    public override Vector3 Force()
    {
        Vector3 toTarget = target.transform.position - transform.position;
        Vector3 desiredVelocity;
        Vector3 returnForce;
        if (isPlanar)
            toTarget.y = 0;
        float distance = toTarget.magnitude;
        if (distance > slowDownDistance)
        {
            desiredVelocity = toTarget.normalized * maxSpeed;
            returnForce = desiredVelocity - m_vehicle.velocity;
        }
        else
        {
            desiredVelocity = toTarget - m_vehicle.velocity;
            returnForce = desiredVelocity - m_vehicle.velocity;
        }
        return returnForce;
    }
    void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(target.transform.position, slowDownDistance);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(SteeringForArrive))]
public class SteeringForLeaderFollowing : Steering
{
    public Vector3 target;
    private Vector3 desiredVelocity;//预期速度
    private Vehicle m_vehicle;//获得被操控的AI角色
    private float maxSpeed;
    private bool isPlanar;
    public GameObject leader;
    private Vehicle leaderController;
    private Vector3 leaderVelocity;
    private float LEADER_BEHIND_DIST=2.0f;
    private SteeringForArrive arriveScript;
    private Vector3 randomOffset;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
        isPlanar = m_vehicle.isPlanar;
        leaderController=leader.GetComponent<Vehicle>();
        arriveScript= GetComponent<SteeringForArrive>();//为抵达行为指定目标点
        arriveScript.target = new GameObject("arriveTarget");
        arriveScript.target.transform.position = leader.transform.position;
    }
   public override Vector3 Force()
    {
        leaderVelocity = leaderController.velocity;
        target=leader.transform.position+LEADER_BEHIND_DIST*(-leaderVelocity).normalized;//计算目标点
        arriveScript.target.transform.position = target;
        return new Vector3(0, 0, 0);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Radar : MonoBehaviour
{
    private Collider[] colliders;//碰撞体的组数
    private float timer = 0;//计时器
    public List<GameObject> neighbors;
    public float checkInterval = 0.3f;//设置检测的时间间隔
    public float detectRadius = 10f;//设置邻域半径
    public LayerMask layersChecked;//设置检测哪一层的游戏对象
    void Start()
    {
        neighbors = new List<GameObject>();
    }
    void Update()
    {
        timer += Time.deltaTime;
        if(timer > checkInterval)
        {
            neighbors.Clear();
            colliders = Physics.OverlapSphere(transform.position, detectRadius, layersChecked);//查找当前AI角色邻域内的所有碰撞体
            for(int i = 0; i < colliders.Length; i++)//对于每个检测到的碰撞体,获取Vehicle组件,并且加入邻居列表钟
            {
                if (colliders[i].GetComponent<Vehicle>())
                    neighbors.Add(colliders[i].gameObject);
            }
            timer = 0;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForSeparation : Steering
{
    public float comforDistance = 1;//可接受的距离
    public float multiplierInsideComfortDistance = 2;//当AI角色与邻居距离过近时的惩罚因子
 public override Vector3 Force()
    {
        Vector3 steeringForce = new Vector3(0, 0, 0);
        foreach(GameObject s in GetComponent<Radar>().neighbors)//遍历这个AI角色的邻居列表中的每个邻居
        {
            if ((s != null) && (s != this.gameObject))
            {
                Vector3 toNeighbor = transform.position - s.transform.position;//计算当前AI角色与邻居s之间的距离
                float length=toNeighbor.magnitude;
                steeringForce += toNeighbor.normalized / length;//计算这个邻居引起的操控力
                if (length < comforDistance)
                    steeringForce *= multiplierInsideComfortDistance;
            }
        }
        return steeringForce;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForEvade :Steering
{
    public GameObject target;
    private Vector3 desiredVelocity;//预期速度
    private Vehicle m_vehicle;//获得被操控的AI角色
    private float maxSpeed;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
    }
    public override Vector3 Force()
    {
        Vector3 toTarget = target.transform.position - transform.position;
        float lookaheadTime = toTarget.magnitude / (maxSpeed + target.GetComponent<Vehicle>().velocity.magnitude);//向前预测的时间
        desiredVelocity = (transform.position - (target.transform.position+target.GetComponent<Vehicle>().velocity*lookaheadTime)).normalized * maxSpeed;
        return (desiredVelocity - m_vehicle.velocity);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EvadeController : MonoBehaviour
{
    public GameObject leader;
    private Vehicle leaderLocomotion;
    private Vehicle m_vehicle;
    private bool isPlanar;
    private Vector3 leaderAhead;
    private float LEADER_BEHIND_DIST;
    private Vector3 dist;
    public float evadeDistance;
    private float sqrEvadeDistance;
    private SteeringForEvade evadeScript;
    void Start()
    {
        leaderLocomotion = leader.GetComponent<Vehicle>();
        evadeScript= GetComponent<SteeringForEvade>();
        m_vehicle= GetComponent<Vehicle>();
        isPlanar=m_vehicle.isPlanar;
        LEADER_BEHIND_DIST = 2.0f;
        sqrEvadeDistance=sqrEvadeDistance*sqrEvadeDistance;
    }
    void Update()
    {
        leaderAhead=leader.transform.position+leaderLocomotion.velocity.normalized*LEADER_BEHIND_DIST;  //计算领队前方的一个点
        dist = transform.position - leaderAhead;
        if (isPlanar)
        {
            dist.y = 0;
        }
        if(dist.sqrMagnitude < sqrEvadeDistance)
        {
            evadeScript.enabled = true;
            Debug.DrawLine(transform.position, leader.transform.position);
        }
        else
        {
            evadeScript.enabled = false;
        }
    }
}

收尾

最后再给各个角色装上刚体,设置好Leader等参数就可以了。

很多行为我们都可以通过设定规则来实现,可能乍一看行为很难摸索,但慢慢分析出其中的规则并逐一实现后,问题往往就会被解决

相关文章
|
定位技术 图形学
Unity3D——射击游戏(多地图,多人物,枪支切换,驾车,扔手雷等功能,堪比小型和平精英)
Unity3D——射击游戏(多地图,多人物,枪支切换,驾车,扔手雷等功能,堪比小型和平精英)
|
机器学习/深度学习 人工智能 图形学
UnityAI——动物迁徙中的跟随实现实例(一)
UnityAI——动物迁徙中的跟随实现实例
101 0
|
算法 计算机视觉
CV:利用人工智能算法让古代皇帝画像以及古代四大美女画像动起来(模仿偶像胡歌剧中角色表情动作)
CV:利用人工智能算法让古代皇帝画像以及古代四大美女画像动起来(模仿偶像胡歌剧中角色表情动作)
|
传感器 编解码 安全
毅力号睁开几双「眼睛」,360度全景展示它的火星新家
近日,在火星安家的「毅力号」向地球发回了一张全景图,展示了着陆点杰泽罗陨石坑周围的面貌。
189 0
毅力号睁开几双「眼睛」,360度全景展示它的火星新家
|
人工智能 算法 vr&ar
「缸中之脑」成真?动态电极绕过眼睛直接刺激大脑,在盲人脑海画出字母
最新研究绕过眼睛,通过动态电极刺激大脑,直接让天生的盲人脑海中出现字母!「智子倒计时」、「缸中之脑」、「黑客帝国」,让人分不清虚拟还是现实的直接意识输入,或许真的离我们不远了。
270 0
「缸中之脑」成真?动态电极绕过眼睛直接刺激大脑,在盲人脑海画出字母
|
机器学习/深度学习 人工智能 vr&ar
几分钟让小孩的人物涂鸦「动起来」,Meta AI创建了一个奇妙的火柴人世界
几分钟让小孩的人物涂鸦「动起来」,Meta AI创建了一个奇妙的火柴人世界
625 0
几分钟让小孩的人物涂鸦「动起来」,Meta AI创建了一个奇妙的火柴人世界
|
人工智能 编解码 5G
“任意门”来了!全息投影瞬间转移身体,实时交互,还能“召回”去世亲友,售价40万
“任意门”来了!全息投影瞬间转移身体,实时交互,还能“召回”去世亲友,售价40万
407 0
|
机器学习/深度学习 PyTorch 算法框架/工具
北大图灵班本科生带来动画CG福音,「最懂骨骼的卷积网络」,无需配对样本实现动作迁移 | SIGGRAPH
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 我有一个动画形象,我有一套人体动作,可想要把它们组合成真正的动画,可不是 1+1 这么简单。 别看这体型迥异的三位动作整齐划一,支撑动画的骨架却差异甚大。
|
人工智能
分辨垃圾材质自动分类 支付宝升级垃圾分类AI回收箱
在今天召开的云栖大会现场,支付宝推出了智能垃圾箱,可对各类不同材质的饮料瓶自动识别、分类丢弃,为行业领先。
2155 0
分辨垃圾材质自动分类 支付宝升级垃圾分类AI回收箱
“洞察”号探测器成功着陆火星,首次揭秘火星内部结构
值得一提的是,这一次“洞察”号不光执行探测任务,还带去了240多万个地球人的名字,它们被载入一块芯片中,跟随探测器登陆上了火星。
436 0

热门文章

最新文章

下一篇
开通oss服务