热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Unity游戏开发中的人工智能编程

unity3dAI学习--群组行为https:blog.csdn.netqq_28221881articledetails52856757Unity群组行为https:blog.c

unity3d AI 学习--群组行为

https://blog.csdn.net/qq_28221881/article/details/52856757

Unity群组行为

https://blog.csdn.net/qq_38186269/article/details/81486139

自己实现效果

Unity游戏开发中的人工智能编程

 具体的分离 队列 聚合力的大小参数根据实际情况修改

演示图

飞往目标点

Unity游戏开发中的人工智能编程

到达目标点后

Unity游戏开发中的人工智能编程

 代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CrowAI : MonoBehaviour
{
    public Transform targetTranform;
    public float speed = 3;

    /// 
    /// 开始速度
    /// 
    private Vector3 startVelocity;
    /// 
    /// 当前的速度
    /// 
    public Vector3 velocity = Vector3.forward;



    /// 
    /// 质量
    /// 
    public float m = 3;

    /// 
    /// 距离我们三米内的乌鸦 就会跟其他乌鸦进行分离
    /// 
    [Header("距离我们三米内的乌鸦 就会跟其他乌鸦进行分离")]
    public float separatiOnDistance= 2;

    [Header("要添加的 3米附近的乌鸦集合 ")]
    public List seapratiOnNeighbors= new List();

    


    /// 
    /// 权重的力
    /// 
    public float separatiOnWeight= 1;

   
    [Header("综合的力")]
    public Vector3 sumForce = Vector3.zero;

    [Header("分离的力")]
    public Vector3 separatiOnForce= Vector3.zero;

    [Header(" 队列 的距离 ")]
    public float alignmentDistance = 6;
    [Header(" 队列 的力的全中 ")]
    public float alignmentWeight = 1;
    [Header("队列的集合")]
    public List alignmentNeighbors = new List();

    [Header("队列的力")]
    public Vector3 alignmentForce = Vector3.zero;


    /// 
    /// 聚集的力的全中
    /// 
    public float cOnhesionWeight= 1;

    [Header("聚集的力")]
    public Vector3 cohesiOnForce= Vector3.zero;

 
    [Header("检查的时间间隔")]
    public float chechInterval = 0.2f;  //若在Update中调用,比较耗费性能

    public float animRandom = 2f;
    public Animation animatio;
    private void Start()
    {


        targetTranform = GameObject.Find("Target").transform;


        //使乌鸦的运动速度保持不变
        startVelocity = velocity;

        InvokeRepeating("CalcForce", 0, chechInterval);
        // targetTranform = GameObject.Find("TargetPos").transform;
        animatio = GetComponentInChildren();
        //yield return new WaitForSeconds(UnityEngine. Random.Range(0, animRandom));
        Invoke("PlayAnim", Random.Range(0, animRandom));
    }

    void PlayAnim() {
        animatio.Play(); 
    }

    void CalcForce()
    {
        //每次计算 把力归零
        sumForce = Vector3.zero;
        separatiOnForce= Vector3.zero;
        alignmentForce = Vector3.zero;
        cohesiOnForce= Vector3.zero;


        seaprationNeighbors.Clear();
                    //Physics.OverlapSphere   (物体位置,半径)  检测球范围内内有多少物体(包含自身) 返回一个Collide集合
        Collider[] colliders = Physics.OverlapSphere(this.transform.position, separationDistance);

                    //将Collide添加到集合中
        foreach (Collider item in colliders)
        {
            if (item != null && item.gameObject != this.gameObject)
            {
                seaprationNeighbors.Add(item.gameObject);
            }
        }

         
         //分离的力
        foreach (GameObject neighbor in seaprationNeighbors)
        {
            Vector3 dir = transform.position - neighbor.transform.position;//得到分离的方向   相反的方向,远离
 
            separationForce += dir.normalized / dir.magnitude;  // dir(得到方向向量) /   dir的长度(自己到neighbor的距离)
                                                                //dir的长度 越小 得到的 力就越大  长度越大产生的力就越小
        }
            //旁边有乌鸦才会更新
        if (seaprationNeighbors.Count>0)
        {
            //现在 separationWeight 的力为1 没有影响  如果发现separationWeight  比较小  就刷一个全中 让他变大
            separationForce *= separationWeight; 
            sumForce += separationForce; 
        }


        //队列的力
        alignmentNeighbors.Clear();

        colliders = Physics.OverlapSphere(this.transform.position, alignmentDistance);

        foreach (Collider c in colliders)
        {
            if (c!=null && c.gameObject!=this.gameObject)
            {
                alignmentNeighbors.Add(c.gameObject);
            }
 
        }
        //平均朝向
        Vector3 avgDir = Vector3.zero;

        foreach (GameObject n in alignmentNeighbors)
        {
            //总的朝向
            avgDir += n.transform.forward;
        }
        if (alignmentNeighbors.Count > 0)
        {
            //除以总数等于   平均朝向   即为  want方向
            avgDir /= alignmentNeighbors.Count;
            //根据 平均方向 - 当前方向  就等于 要朝向的 朝向     即temp方向 
            alignmentForce = avgDir - transform.forward;//越靠近,temp向量越小,力越小
            //刷个权重  如果力太小的话可以放大
            alignmentForce *= alignmentWeight;
            sumForce += alignmentForce;
        }


        //聚集的力  
        //seaprationNeighbors  分离的数组大于0  只有小于等于0的时候 才能聚集 
        //alignmentNeighbors  队列的力小于等于0   都没办法计算 队列的力了
        if (alignmentNeighbors.Count > 0) {
            //中心点
            Vector3 center = Vector3.zero;

            foreach (GameObject item in alignmentNeighbors)
            {
                center += item.transform.position;
            }
            center /= alignmentNeighbors.Count;
            //得到移动的力  center 越大  得到的力就越大 刚好符合
            Vector3 dirToCenter = center - this.transform.position;
            cohesionForce += dirToCenter;
            // 如果上面的力不行的话就是用这种方法
            // cohesionForce += dirToCenter .normalized *velocity.magnitude; 
            cohesionForce *= conhesionWeight;
            sumForce += cohesionForce;
        }
        

        ////
        ////保持恒定飞行速度向前飞 
        // Vector3 engineForce = startVelocity - velocity;
        ////Vector3 engineForce = velocity.normalized * startVector3.magnitude;
        //sumForce += engineForce * 0.1f;

        //向某个物体飞去
        Vector3 targetDir = targetTranform.position - transform.position;
        //temp方向减去 当前方向 
        sumForce += (targetDir.normalized - transform.forward) * speed;


  
    }
    // Update is called once per frame
    void Update()
    {
         //加速度
        Vector3 a = sumForce / m;
        velocity += a * Time.deltaTime;

        //因为 初始的队列的方向是一致的 就会导致  队列的力不起作用 所以必须加上下面的代码
        //当前的朝向 和速度的朝向保持一致
        //transform.rotation = Quaternion.LookRotation(velocity);
        //加入插值,不会突然变向
        transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime);


        //transform.Translate(velocity * Time.deltaTime, Space.World);
        transform.Translate(transform.forward * Time.deltaTime *velocity.magnitude, Space.World);


    }
}

 


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • Givenasinglylinkedlist,returnarandomnode'svaluefromthelinkedlist.Eachnodemusthavethe s ... [详细]
  • 如何在php文件中添加图片?
    本文详细解答了如何在php文件中添加图片的问题,包括插入图片的代码、使用PHPword在载入模板中插入图片的方法,以及使用gd库生成不同类型的图像文件的示例。同时还介绍了如何生成一个正方形文件的步骤。希望对大家有所帮助。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文详细介绍了PHP中与URL处理相关的三个函数:http_build_query、parse_str和查询字符串的解析。通过示例和语法说明,讲解了这些函数的使用方法和作用,帮助读者更好地理解和应用。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
  • 本文介绍了一种在PHP中对二维数组根据某个字段进行排序的方法,以年龄字段为例,按照倒序的方式进行排序,并给出了具体的代码实现。 ... [详细]
author-avatar
宁艺汉先生
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有