【UnityRPG游戏制作】NPC交互逻辑、动玩法

news2025/2/24 9:54:55

在这里插入图片描述


👨‍💻个人主页:@元宇宙-秩沅

👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 秩沅 原创
👨‍💻 收录于专栏:就业宝典

🅰️推荐专栏

⭐-软件设计师高频考点大全



文章目录

    • 前言
    • 🎶(==二==) NPC逻辑相关
    • (==1==) NPC范围检测
    • (==2==) NPC动画添加
    • (==3==) NPC和玩家的攻击受伤交互(事件中心)
    • (==4==) NPC的受伤特效添加
    • (==5==) NPC的死亡特效添加
    • 🅰️


前言


🎶( NPC逻辑相关



1 NPC范围检测


在这里插入图片描述

在这里插入图片描述

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

//-------------------------------
//-------功能: NPC交互脚本
//-------创建者:         -------
//------------------------------

public class NPCContorller : MonoBehaviour
{
    public PlayerContorller playerCtrl;

    //范围检测
    private void OnTriggerEnter(Collider other)
    {
        playerCtrl.isNearby  = true;
    }
    private void OnTriggerExit(Collider other)
    {
        playerCtrl.isNearby = false;
    }
}


2 NPC动画添加


在这里插入图片描述
请添加图片描述


3 NPC和玩家的攻击受伤交互(事件中心)


  • EnemyController 敌人

   using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

//-------------------------------
//-------功能:  敌人控制器
//-------创建者:         -------
//------------------------------

public class EnemyController : MonoBehaviour
{
    public GameObject player;   //对标玩家
    public Animator animator;   //对标动画机
    public GameObject enemyNPC; //对标敌人
    public int hp;              //血量
    public Image hpSlider;      //血条
    private int attack = 10;    //敌人的攻击力
    public float CD_skill ;         //技能冷却时间

    private void Start()
    {
       
        enemyNPC = transform.GetChild(0).gameObject;
        animator = enemyNPC.GetComponent<Animator>();
        SendEvent();  //发送相关事件
    }

    private void Update()
    {
        CD_skill += Time.deltaTime; //CD一直在累加

    }

    /// <summary>
    /// 发送事件
    /// </summary>
    private void SendEvent()
    {
        //传递怪兽攻击事件(也是玩家受伤时)
        EventCenter.GetInstance().AddEventListener(PureNotification.PLAYER_INJURY, (int attack) =>
        {
            animator.SetBool("attack",true ); //攻击动画激活     
        });

        //传递怪兽受伤事件(玩家攻击时)
        EventCenter.GetInstance().AddEventListener(PureNotification.PLAYER_ATTRACK, ( ) =>
        { 
                animator.SetBool("hurt", true);  //受伤动画激活
        });

        //传递怪兽死亡事件
        EventCenter.GetInstance().AddEventListener(PureNotification.NPC_Died , () =>
        {      
                animator.SetBool("died", true);  //死亡动画激活
                gameObject.SetActive(false);     //给物体失活
                //暴金币
        });

    }

    //碰撞检测
    private void OnCollisionStay(Collision collision)
    {
        if (collision.gameObject.tag == "Player") //检测到如果是玩家的标签
        {
         
            if(CD_skill > 2f)  //攻击动画的冷却时间
            {
                Debug.Log("怪物即将攻击");
                CD_skill = 0;
                //触发攻击事件
                EventCenter.GetInstance().EventTrigger(PureNotification.PLAYER_INJURY, Attack());
               
            }    
    
        }
    }



    /// <summary>
    /// 传递攻击力
    /// </summary>
    /// <returns></returns>
    public  int  Attack()
    {
        return attack;
    }
   
    //碰撞检测
    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.tag == "Player") //检测到如果是玩家的标签
        {
            animator.SetBool("attack", false);       
            collision.gameObject.GetComponent<PlayerContorller>().animator .SetBool("hurt", false);

        }
    }


    //范围触发检测
    private void OnTriggerStay(Collider other)
    {
      if(other.tag == "Player")  //检测到如果是玩家的标签
        {
            //让怪物看向玩家
            transform.LookAt(other.gameObject.transform.position);
            //并且向其移动
            transform.Translate(Vector3.forward * 1 * Time.deltaTime);
        
        }

    }
 
}


  • PlayerContorller玩家
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;
using static UnityEditor.Experimental.GraphView.GraphView;

//-------------------------------
//-------功能: 玩家控制器
//-------创建者:        
//------------------------------

public class PlayerContorller : MonoBehaviour
{
    //-----------------------------------------
    //---------------成员变量区-----------------
    //-----------------------------------------

    public float  speed = 1;         //速度倍量
    public Rigidbody rigidbody;      //刚体组建的声明
    public Animator  animator;       //动画控制器声明
    public GameObject[] playersitem; //角色数组声明
    public bool isNearby = false;    //人物是否在附近
    public float CD_skill ;         //技能冷却时间
    public int curWeaponNum;        //拥有武器数
    public int attack ;             //攻击力
    public int defence ;            //防御力
  

    //-----------------------------------------
    //-----------------------------------------


    void Start()
    {
        rigidbody = GetComponent<Rigidbody>();

        SendEvent();//发送事件给事件中心
    }
    void Update()
    {
        CD_skill += Time.deltaTime;       //CD一直在累加
        InputMonitoring();
    }
        void FixedUpdate()
    {
        Move();
    }


    /// <summary>
    /// 更换角色[数组]
    /// </summary>
    /// <param name="value"></param>
    public void ChangePlayers(int value)
    {
        for (int i = 0; i < playersitem.Length; i++)
        {
            if (i == value)
            {
                animator = playersitem[i].GetComponent<Animator>();
                playersitem[i].SetActive(true);
            }
            else
            {
                playersitem[i].SetActive(false);
            }
        }
    }
  
    /// <summary>
    ///玩家移动相关
    /// </summary>
    private void Move()
    {
        //速度大小
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
    
        if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0)
        {
            //方向
            Vector3 dirction = new Vector3(horizontal, 0, vertical);
            //让角色的看向与移动方向保持一致
            transform.rotation = Quaternion.LookRotation(dirction);
            rigidbody.MovePosition(transform.position + dirction * speed * Time.deltaTime);
            animator.SetBool("walk", true);
            //加速奔跑
            if (Input.GetKey(KeyCode.LeftShift) )
            {
                animator.SetBool("run", true);
                animator.SetBool("walk", true);                
                rigidbody.MovePosition(transform.position + dirction * speed*3 * Time.deltaTime);
            }
            else 
            {
                animator.SetBool("run", false);;
                animator.SetBool("walk", true);
            }            
        }
        else 
        {
            animator.SetBool("walk", false);
        }
    }


    /// <summary>
    /// 键盘监听相关
    /// </summary>
    public void InputMonitoring()
    {
        //人物角色切换
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            ChangePlayers(0);
        }

        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            ChangePlayers(1);
        }

        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            ChangePlayers(2);
        }
        //范围检测弹出和NPC的对话框
        if (isNearby && Input.GetKeyDown(KeyCode.F))
        {          
            //发送通知打开面板
            GameFacade.Instance.SendNotification(PureNotification.SHOW_PANEL, "NPCTipPanel");
        
        }
        //打开背包面板
        if ( Input.GetKeyDown(KeyCode.Tab))
        {
            //发送通知打开面板
            GameFacade.Instance.SendNotification(PureNotification.SHOW_PANEL, "BackpackPanel");

        }
        //打开角色面板
        if ( Input.GetKeyDown(KeyCode.C))
        {
            //发送通知打开面板
            GameFacade.Instance.SendNotification(PureNotification.SHOW_PANEL, "RolePanel");
        }

        //攻击监听
        if (Input.GetKeyDown(KeyCode.Space) && CD_skill >= 1.0f) //按下空格键攻击,并且技能恢复冷却
        {

            if (curWeaponNum > 0)  //有武器时的技能相关
            {
                animator.speed = 2;
                animator.SetTrigger("Attack2");
            }
            else                  //没有武器时的技能相关
            {
                animator.speed = 1;
                animator.SetTrigger("Attack1");
            }

            CD_skill = 0;

            #region
            //技能开始冷却

            //    audioSource.clip = Resources.Load<AudioClip>("music/01");
            //    audioSource.Play();
            //    cd_Put = 0;
            //var enemys = GameObject.FindGameObjectsWithTag("enemy");
            //foreach (GameObject enemy in enemys)
            //{
            //    if (enemy != null)
            //    {
            //        if (Vector3.Distance(enemy.transform.position, this.transform.position) <= 5)
            //        {
            //            enemy.transform.GetComponent<_03EnemyCtrl>().SubSelf(50);
            //        }
            //    }
            //}
            //var bosses = GameObject.FindGameObjectsWithTag("boss");
            //foreach (GameObject boss in bosses)
            //{
            //    if (boss != null)
            //    {
            //        if (Vector3.Distance(boss.transform.position, this.transform.position) <= 5)
            //        {
            //            boss.transform.GetComponent<boss>().SubHP();
            //        }
            //    }
            //}
            #endregion
        }

        //if (Input.GetKeyDown(KeyCode.E))
        //{
        //    changeWeapon = !changeWeapon;
        //}
        //if (Input.GetKeyDown(KeyCode.Q))
        //{
        //    AddHP();
        //    diaPanel.USeHP();
        //}
        //if (enemys != null && enemys.transform.childCount <= 0 && key != null)
        //{
        //    key.gameObject.SetActive(true);
        //}


    }


    /// <summary>
    /// 发送事件
    /// </summary>
    private void SendEvent()
    {
        //传递玩家攻击事件
        EventCenter.GetInstance().AddEventListener(PureNotification.PLAYER_ATTRACK, () =>
        {
           
        });

        //传递玩家受伤事件(怪物攻击时)
        EventCenter.GetInstance().AddEventListener(PureNotification.PLAYER_INJURY , (int attack) =>
        {
            animator.SetBool("hurt", true);
           Debug.Log(attack + "掉血了");                                 
        });   
    }
}


4 NPC的受伤特效添加


请添加图片描述

    /// <summary>
    /// 碰撞检测
    /// </summary>
    /// <param name="collision"></param>
    private void OnCollisionStay(Collision collision)
    {
        //若碰到敌人,并进行攻击
        if (collision.gameObject.tag == "enemy" && Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("造成伤害");
            enemyController = collision.gameObject.GetComponent<EnemyController>();
            //触发攻击事件
            enemyController.animator.SetBool("hurt", true);  //怪物受伤动画激活
            enemyController.transform.GetChild(2).GetChild(0).GetComponent<ParticleSystem>().Play();
            enemyController.hp -= attack;//减少血量
            enemyController. hpSlider.fillAmount = (enemyController.hp / 100.0f);
            if (enemyController.hp <= 0) //死亡判断
            {
                collision.transform.GetChild(0).GetComponent<Animator>() .SetBool("died", true);  //死亡动画激活
                                                                                                  //播放动画
                collision.transform.GetChild(2).GetChild(0).GetComponent<ParticleSystem>().Play();
                collision. gameObject.SetActive(false); //将敌人失活
                //暴钻石(实例化)
                Instantiate(Resources.Load<GameObject>("Perfab/Prop/damon"), collision.transform.position , Quaternion.identity);
                Destroy(collision.gameObject, 3);
            }
        }
    }

5 NPC的死亡特效添加


请添加图片描述

   /// <summary>
   /// 碰撞检测
   /// </summary>
   /// <param name="collision"></param>
   private void OnCollisionStay(Collision collision)
   {
       //若碰到敌人,并进行攻击
       if (collision.gameObject.tag == "enemy" && Input.GetKeyDown(KeyCode.Space))
       {
           Debug.Log("造成伤害");
           enemyController = collision.gameObject.GetComponent<EnemyController>();
           //触发攻击事件
           enemyController.animator.SetBool("hurt", true);  //怪物受伤动画激活
           enemyController.transform.GetChild(2).GetChild(0).GetComponent<ParticleSystem>().Play();
           enemyController.hp -= attack;//减少血量
           enemyController. hpSlider.fillAmount = (enemyController.hp / 100.0f);
           if (enemyController.hp <= 0) //死亡判断
           {
               collision.transform.GetChild(0).GetComponent<Animator>() .SetBool("died", true);  //死亡动画激活
                                                                                                 //播放动画
               collision.transform.GetChild(2).GetChild(0).GetComponent<ParticleSystem>().Play();
               collision. gameObject.SetActive(false); //将敌人失活
               //暴钻石(实例化)
               Instantiate(Resources.Load<GameObject>("Perfab/Prop/damon"), collision.transform.position , Quaternion.identity);
               Destroy(collision.gameObject, 3);
           }
       }
   }

🅰️


⭐【Unityc#专题篇】之c#进阶篇】

⭐【Unityc#专题篇】之c#核心篇】

⭐【Unityc#专题篇】之c#基础篇】

⭐【Unity-c#专题篇】之c#入门篇】

【Unityc#专题篇】—进阶章题单实践练习

⭐【Unityc#专题篇】—基础章题单实践练习

【Unityc#专题篇】—核心章题单实践练习


你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!


在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1641386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle 数据库全面升级为 23ai

从 11g 到 12c 再到 19c&#xff0c;今天&#xff0c;我们迎来了 23ai &#xff01; “ Oracle AI Vector Search allows documents, images, and relational data that are stored in mission-critical databases to be easily searched based on their conceptual content Ge…

算法打卡day40

今日任务&#xff1a; 1&#xff09;139.单词拆分 2&#xff09;多重背包理论基础&#xff08;卡码网56携带矿石资源&#xff09; 3&#xff09;背包问题总结 4&#xff09;复习day15 139单词拆分 题目链接&#xff1a;139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; …

【22-处理不平衡数据集:Scikit-learn中的技术和策略】

文章目录 前言了解不平衡数据集重采样技术过采样欠采样生成合成样本调整类别权重使用适合于不平衡数据集的评估指标结论前言 在机器学习任务中,不平衡数据集是一个非常常见的问题。它指的是数据集中各类别样本数量差异较大,这种情况在现实世界的数据收集中非常普遍,特别是在…

WebDriver使用带用户名密码验证的IP代理解决方案

背景&#xff0c;使用python3 selenium 先定义一个方法&#xff0c;这里主要用到了chrome插件的功能&#xff0c;利用这个插件来放进代理内容。 def create_proxy_auth_extension(proxy_host, proxy_port,proxy_username, proxy_password, schemehttp):manifest_json "…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(一)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; Phpsploit-Framework&#xff08;简称 PSF&#xff09;框架软件&#xff0c;是一款什么样的软件呢&#xff1f; Phpspl…

开源的贴吧数据查询工具

贴吧数据查询工具 这是一个贴吧数据查询工具&#xff0c;目前仍处于开发阶段。 本地运行 要本地部署这个项目&#xff0c;请 克隆这个仓库并前往项目目录 git clone https://github.com/Dilettante258/tieba-tools.git cd tieba-tools安装依赖 pnpm install运行项目 np…

如何配置Jupyter Lab以允许远程访问和设置密码保护

如何配置Jupyter Lab以允许远程访问和设置密码保护 当陪你的人要下车时&#xff0c;即使不舍&#xff0c;也该心存感激&#xff0c;然后挥手道别。——宫崎骏《千与千寻》 在数据科学和机器学习工作流中&#xff0c;Jupyter Lab是一个不可或缺的工具&#xff0c;但是默认情况下…

《金融研究》:普惠金融改革试验区DID工具变量数据(2012-2023年)

数据简介&#xff1a;本数据集包括普惠金融改革试验区和普惠金融服务乡村振兴改革试验区两类。 其中&#xff0c;河南兰考、浙江宁波、福建龙岩和宁德、江西赣州和吉安、陕西铜川五省七地为普惠金融改革试验区。山东临沂、浙江丽水、四川成都三地设立的是普惠金融服务乡村振兴…

《Mask2Former》算法详解

文章地址&#xff1a;《Masked-attention Mask Transformer for Universal Image Segmentation》 代码地址&#xff1a;https://github.com/facebookresearch/Mask2Former 文章为发表在CVPR2022的一篇文章。从名字可以看出文章像提出一个可以统一处理各种分割任务&#xff08;…

C++学习第二十二课:STL映射类的深入解析

C学习第二十二课&#xff1a;STL映射类的深入解析 在C标准模板库&#xff08;STL&#xff09;中&#xff0c;映射类&#xff08;std::map和std::multimap&#xff09;是用来存储关联数据的容器。与集合类不同&#xff0c;映射类中的每个元素都是一个键值对&#xff08;key-val…

十四、网络编程

目录 一、二、网络通讯要素三、IP和端口号四、网络协议1、网络通信协议2、TCP/IP协议簇1&#xff09;TCP协议2&#xff09;UDP 3、Socket 五、TCP网络编程1、基于Socket的TCP编程1&#xff09;客户端创建socket对象2&#xff09; 服务器端建立 ServerSocket对象 2、UDP网络通信…

17 内核开发-内核内部内联汇编学习

​ 17 内核开发-内核内部内联汇编学习 课程简介&#xff1a; Linux内核开发入门是一门旨在帮助学习者从最基本的知识开始学习Linux内核开发的入门课程。该课程旨在为对Linux内核开发感兴趣的初学者提供一个扎实的基础&#xff0c;让他们能够理解和参与到Linux内核的开发过程中…

【 书生·浦语大模型实战营】学习笔记(六):Lagent AgentLego 智能体应用搭建

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…

MySQL技能树学习——数据库组成

数据库组成&#xff1a; 数据库是一个组织和存储数据的系统&#xff0c;它由多个组件组成&#xff0c;这些组件共同工作以确保数据的安全、可靠和高效的存储和访问。数据库的主要组成部分包括&#xff1a; 数据库管理系统&#xff08;DBMS&#xff09;&#xff1a; 数据库管理系…

node.js中path模块-路径处理,语法讲解

node中的path 模块是node.js的基础语法&#xff0c;实际开发中&#xff0c;我们通过使用 path 模块来得到绝对路径&#xff0c;避免因为相对路径带来的找不到资源的问题。 具体来说&#xff1a;Node.js 执行 JS 代码时&#xff0c;代码中的路径都是以终端所在文件夹出发查找相…

服务器被攻击,为什么后台任务管理器无法打开?

在服务器遭受DDoS攻击后&#xff0c;当后台任务管理器由于系统资源耗尽无法打开时&#xff0c;管理员需要依赖间接手段来进行攻击类型的判断和解决措施的实施。由于涉及真实代码可能涉及到敏感操作&#xff0c;这里将以概念性伪代码和示例指令的方式来说明。 判断攻击类型 步…

DHCPv4_CLIENT_ALLOCATING_04: 发送DHCPREQUEST - 头部值‘secs‘字段

测试目的&#xff1a; 验证客户端发送的DHCPREQUEST消息是否使用了与原始DHCPDISCOVER消息相同的’secs’字段值。 描述&#xff1a; 本测试用例旨在确保DHCP客户端在发送DHCPREQUEST消息时&#xff0c;使用了与它之前发送的DHCPDISCOVER消息相同的’secs’字段值。这是DHCP…

国产数据库的发展势不可挡

前言 新的一天又开始了&#xff0c;光头强强总不紧不慢地来到办公室&#xff0c;准备为今天一天的工作&#xff0c;做一个初上安排。突然&#xff0c;熊二直接进入办公室&#xff0c;说&#xff1a;“强总老大&#xff0c;昨天有一个数据库群炸了锅了&#xff0c;有一位姓虎的…

【LLM 论文】UPRISE:使用 prompt retriever 检索 prompt 来让 LLM 实现 zero-shot 解决 task

论文&#xff1a;UPRISE: Universal Prompt Retrieval for Improving Zero-Shot Evaluation ⭐⭐⭐⭐ EMNLP 2023, Microsoft Code&#xff1a;https://github.com/microsoft/LMOps 一、论文速读 这篇论文提出了 UPRISE&#xff0c;其思路是&#xff1a;训练一个 prompt retri…

Git可视化工具tortoisegit 的下载与使用

一、tortoisegit 介绍 TortoiseGit 是一个非常实用的版本控制工具&#xff0c;主要用于与 Git 版本控制系统配合使用。 它的主要特点包括&#xff1a; 图形化界面&#xff1a;提供了直观、方便的操作界面&#xff0c;让用户更易于理解和管理版本控制。与 Windows 资源管理器…