【Unity2D 2022:Canvas】制作NPC

news2024/9/21 20:38:49

一、创建NPC角色

1. 创建JambiNPC并同时创建Jambi站立动画

        (1)点击第一张图片,按住shift不松,再选中后两张图片,拖到层级面板中

        (2)将动画资源文件保存到Animation Clips文件夹中

        (3)将动画控制器文件保存到Animators文件夹中

2. 将Jambi添加为预制体

二、编辑NPC属性

1. 修改层级为NPC

        (1)添加NPC层级

        (2)将Jambi的层级设置为NPC层级

2. 精灵渲染器(Sprite Renderer)

        (1)修改锚点为底部

        (2)修改渲染层级为1

3. 2D碰撞箱(Box Collider 2D)

        (1)添加 Box Collider 2D 组件(避免角色覆盖NPC)

        (2)调整碰撞体积大小

三、创建对话框

1. 创建对话框画布

2. 修改对话框画布属性

        (1)修改UI缩放模式为World(红色)

        (2)修改渲染层级为10(对话框要显示在其他游戏物体上方,因此要大于其他层级)(蓝色) 

        (3)修改缩放为0.01(绿色)

        (4)修改长度宽度,调整到合适的位置(黄色)

3. 添加图像子物体到对话框

4. 编辑图像子物体属性

        (1)使图像填充对话框画布

        (2)将对话框图片赋值给图像

5. 添加文本子物体到对话框

6. 编辑文本子物体属性

        (1)使文本填充对话框画布内边缘,锚点在文本框的四个角

        (2)调整字体大小(红色)

        (3)使文本左右居中,上下居中(蓝色)

        (4)更改文本内容(绿色)

        (5)调整字体颜色(黄色)

        (6)更改字体样式(粉色)

        (7)添加OutLine组件,为字体增加边框

        (8)改变字体边框的颜色

        (9)最终效果如下图所示

 四、添加NPC对话功能(射线检测)

1. 编辑Ruby脚本

        (1)判断E键是否按下

public class Ruby : MonoBehaviour 
{
    void Update() 
    {
        // 对话功能
        if(Input.GetKeyDown(KeyCode.E)) { // 当按下E键时

        }
    }
}

        (2)创建一条射线

public class Ruby : MonoBehaviour 
{
    void Update() 
    {
        // 对话功能
        if(Input.GetKeyDown(KeyCode.E)) { // 当按下E键时
            // 创建一条射线:起点为角色的位置偏上(Vector2.up为向上的单位向量),方向为角色的朝向, 射线长度为1.5, 发生碰撞的游戏物体层级为NPC层
            RaycastHit2D ray = Physics2D.Raycast(rb2d.position+0.2f*Vector2.up, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
            // ray碰撞到的物体会存储到ray自身当中
        }
    }
}

        (3)判断射线是否碰撞到物体

public class Ruby : MonoBehaviour 
{
    void Update() 
    {
        // 对话功能
        if(Input.GetKeyDown(KeyCode.E)) { // 当按下E键时
            // 创建一条射线:起点为角色的位置偏上(Vector2.up为向上的单位向量),方向为角色的朝向, 射线长度为1.5, 发生碰撞的游戏物体层级为NPC层
            RaycastHit2D ray = Physics2D.Raycast(rb2d.position+0.2f*Vector2.up, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
            // ray碰撞到的物体会存储到ray自身当中
            if(ray.collider != null) { // 若射线碰撞到的物体不为空
                
            }
        }
    }
}

        (4)使用Debug语句测试

public class Ruby : MonoBehaviour 
{
    void Update() 
    {
        // 对话功能
        if(Input.GetKeyDown(KeyCode.E)) { // 当按下E键时
            // 创建一条射线:起点为角色的位置偏上(Vector2.up为向上的单位向量),方向为角色的朝向, 射线长度为1.5, 发生碰撞的游戏物体层级为NPC层
            RaycastHit2D ray = Physics2D.Raycast(rb2d.position+0.2f*Vector2.up, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
            // ray碰撞到的物体会存储到ray自身当中
            if(ray.collider != null) { // 若射线碰撞到的物体不为空
                Debug.Log("射线碰撞到的物体是:" + ray.collider.gameObject);
            }
        }
    }
}

        检测成功: 

2. 创建NPCDialog脚本

        (1)创建对话框游戏物体

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

public class NPCDialog : MonoBehaviour
{
    // 创建对话框游戏物体
    public GameObject dialogBox;

}

        (2)设置初始时对话框为隐藏状态

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

public class NPCDialog : MonoBehaviour
{
    // 创建对话框游戏物体
    public GameObject dialogBox;

    void Start()
    {
        // 设置初始时对话框为隐藏状态
        dialogBox.SetActive(false);
    }

}

         (3)编写displayDialogBox方法,用来显示对话框

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

public class NPCDialog : MonoBehaviour
{
    // 创建对话框游戏物体
    public GameObject dialogBox;

    void Start()
    {
        // 设置初始时对话框为隐藏状态
        dialogBox.SetActive(false);
    }

    public void displayDialogBox()
    {
        // 设置对话框为显示状态
        dialogBox.SetActive(true);
    }
}

        (4)创建浮点型变量DisplayTime为对话框显示时间,DisplayTimer为对话框显示计时器

public class NPCDialog : MonoBehaviour
{
    // 创建对话框游戏物体
    public GameObject dialogBox;
    // 对话框展示时间
    public float displayTime = 4;
    public float displayTimer;

    void Start()
    {
        // 设置初始时对话框为隐藏状态
        dialogBox.SetActive(false);
    }

    public void displayDialogBox()
    {
        // 设置对话框为显示状态
        dialogBox.SetActive(true);
    }
}

        (5)在DisplayDialog方法中设置计时器的值为最长显示时间

public class NPCDialog : MonoBehaviour
{
    // 创建对话框游戏物体
    public GameObject dialogBox;
    // 对话框展示时间
    public float displayTime = 4;
    public float displayTimer;

    void Start()
    {
        // 设置初始时对话框为隐藏状态
        dialogBox.SetActive(false);
    }

    public void displayDialogBox()
    {
        // 设置对话框为显示状态
        dialogBox.SetActive(true);
        // 重置计时器
        displayTimer = displayTime;
    }
}

        (6)编辑Update函数,若对话框为显示状态,则开始计时。当计时器小于0后,设置对话框为隐藏状态

public class NPCDialog : MonoBehaviour
{
    // 创建对话框游戏物体
    public GameObject dialogBox;
    // 对话框展示时间
    public float displayTime = 4;
    public float displayTimer;

    void Start()
    {
        // 设置初始时对话框为隐藏状态
        dialogBox.SetActive(false);
    }

    private void Update()
    {
        if(dialogBox.active) {
            displayTimer -= Time.deltaTime;
            if(displayTimer < 0) {
                dialogBox.SetActive(false);
            }
        }
    }

    public void displayDialogBox()
    {
        // 设置对话框为显示状态
        dialogBox.SetActive(true);
        displayTimer = displayTime;
    }
}

3. 修改Ruby脚本

        (1)删除Debug语句,创建NPC对话对象为ray碰撞到的物体对话组件

public class Ruby : MonoBehaviour 
{
        // 对话功能
        if(Input.GetKeyDown(KeyCode.E)) { // 当按下E键时
            // 创建一条射线:起点为角色的位置偏上(Vector2.up为向上的单位向量),方向为角色的朝向, 射线长度为1.5, 发生碰撞的游戏物体层级为NPC层
            RaycastHit2D ray = Physics2D.Raycast(rb2d.position+0.2f*Vector2.up, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
            // ray碰撞到的物体会存储到ray自身当中
            if(ray.collider != null) { // 若射线碰撞到的物体不为空
                // 创建NPC对话对象为ray碰撞到的物体的对话组件
                NPCDialog npcDialog = ray.collider.gameObject.GetComponent<NPCDialog>();
            }
        }
    }

}

        (2)当对话组件不为空时,设置对话框为显示状态

public class Ruby : MonoBehaviour 
{
        // 对话功能
        if(Input.GetKeyDown(KeyCode.E)) { // 当按下E键时
            // 创建一条射线:起点为角色的位置偏上(Vector2.up为向上的单位向量),方向为角色的朝向, 射线长度为1.5, 发生碰撞的游戏物体层级为NPC层
            RaycastHit2D ray = Physics2D.Raycast(rb2d.position+0.2f*Vector2.up, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
            // ray碰撞到的物体会存储到ray自身当中
            if(ray.collider != null) { // 若射线碰撞到的物体不为空
                // 创建NPC对话对象为ray碰撞到的物体的对话组件
                NPCDialog npcDialog = ray.collider.gameObject.GetComponent<NPCDialog>();
                if(npcDialog != null) { // 若对话组件不为空
                    // 设置对话框为显示状态
                    npcDialog.displayDialogBox();
                }
            }
        }
    }

}

4. 为Jambi添加NPCDialog脚本,并将Dialog游戏物体赋值到Dialog Box中

5. 最终效果如下图所示

        (1)初始时:

        (2)按下E键后:

        (3)经过4秒后:

        本章完。感谢阅读!

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

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

相关文章

策划人必读:一场关于创意与市场的深度对话

活动策划、市场推广、品牌策划、营销策划&#xff0c;这四者在企业营销战略中各有侧重&#xff0c;但又相互促进&#xff1b;各有千秋&#xff0c;但又紧密相连&#xff0c;共同推动着企业的成长。 下面就来一一拆解&#xff0c;看看它们之间是怎么互相作用&#xff0c;打造出…

【方法】如何打开设置了密码的ZIP文件?

对于重要的ZIP文件&#xff0c;很多人会设置密码保护&#xff0c;那要如何打开设置了密码的ZIP文件呢&#xff1f;今天我们一起来看下&#xff0c;在记得密码和忘记密码的情况下&#xff0c;如何打开ZIP文件。 情况1&#xff1a; 如果知道ZIP文件原本设置的密码&#xff0c;我…

【2024——CUMCM】Matlab快速入门

目录 常识 disp and input 字符串合并 sum 提取矩阵指定位置的元素 指定行列 指定行or指定列&#xff08;返回行/列向量&#xff09; 指定某些行 指定全部元素&#xff0c;按列拼接 size repmat 矩阵的运算 基本运算 形状相同的矩阵运算 每个元素同时和常数相乘或相…

【IMU】 温度零偏标定

温度标定 IMU的零偏随着温度的变化而变化&#xff0c;在全温范围内形状各异&#xff0c;有些可能是单调的&#xff0c;有些可能出现拐点。 多项式误差温度标定 目的是对估计的参数进行温度补偿&#xff0c;获取不同温度时的参数值&#xff08;零偏、尺度、正交&#xff09;&…

关于10G光模块中SR, LR, LRM, ER 和 ZR的区别?

在10Gbps&#xff08;10千兆比特每秒&#xff09;光模块中&#xff0c;SR、LR、LRM、ER 和 ZR 是用来描述不同类型的模块及其适用的传输距离和光纤类型。下面是这些缩写的详细解释&#xff1a; 1.SR (Short Range) 2.LR (Long Range) 3.LRM (Long Reach Multimode) 4.ER (E…

移除元素的讲解,看这篇就够了!

一&#xff1a;题目 博主本文将用指向来形象的表示下标位的移动。 二&#xff1a;思路 1&#xff1a;两个整形&#xff0c;一个start&#xff0c;一个end&#xff0c;在一开始都 0&#xff0c;即这里都指向第一个元素。 2&#xff1a;在查到val之前&#xff0c;查一个&…

[数仓]七、离线数仓(PrestoKylin即席查询)

第1章 Presto 1.1 Presto简介 1.1.1 Presto概念 1.1.2 Presto架构 1.1.4 Presto、Impala性能比较 Presto、Impala性能比较_presto和impala对比-CSDN博客 测试结论:Impala性能稍领先于Presto,但是Presto在数据源支持上非常丰富,包括Hive、图数据库、传统关系型数据库、Re…

CentOS 8升级gcc版本

1、查看gcc版本 gcc -v发现gcc版本为8.x.x&#xff0c;而跑某个项目的finetune需要gcc-9&#xff0c;之前搜索过很多更新gcc版本的方式&#xff0c;例如https://blog.csdn.net/xunye_dream/article/details/108918316?spm1001.2014.3001.5506&#xff0c;但执行指令 sudo yu…

FastAPI是一个现代、快速(高性能)的Web框架

FastAPI是一个现代、快速&#xff08;高性能&#xff09;的Web框架&#xff0c;专门用于构建基于Python的API。以下是对FastAPI的详细介绍&#xff1a; 一、基本概述 定义与用途&#xff1a;FastAPI是一个开源项目&#xff0c;基于Starlette和Pydantic库构建而成&#xff0c;…

推出全新的无线通讯模块(1SJ型、2DT-158型、2GT-001型、1YN型、2AE型)助力物联网新发展

相关型号&#xff1a;LBAA0QB1SJ-296 LBAA0XV2DT-158 LBAA0XV2GT-001 LBEE5KL1YN-814 LBEE5PK2AE-564 全新的无线通讯模块&#xff08;1SJ型、2DT-158型、2GT-001型、1YN型、2AE型&#xff09;助力物联网新发展&#xff08;明佳达&#xff09; 1、1SJ型集成LoRaWAN调制解调器…

【1】A-Frame整体介绍

1.A-Frame是什么&#xff1f; A-Frame 是一个用于构建虚拟现实 (VR) 体验的 Web 框架。 A-Frame 基于 HTML 之上&#xff0c;因此上手简单。但 A-Frame 不仅仅是 3D 场景图或标记语言&#xff1b;它还是一种标记语言。其核心是一个强大的实体组件框架&#xff0c;为 Three.js …

QT文件生成可执行的exe程序

将qt项目生成可执行的exe程序可按照以下步骤进行&#xff1a; 1、在qt中构建运行生成.exe文件&#xff1b; 2、从自定义的路径中取出exe文件放在一个单独的空文件夹中&#xff08;exe文件在该文件夹中的release文件夹中&#xff09;&#xff1b; 3、从开始程序中搜索qt&#xf…

HumanoidBench——模拟仿人机器人算法有未来

概述 论文地址&#xff1a;https://arxiv.org/pdf/2403.10506 仿人机器人具有类似人类的外形&#xff0c;有望在各种环境和任务中为人类提供支持。然而&#xff0c;昂贵且易碎的硬件是这项研究面临的挑战。因此&#xff0c;本研究开发了使用先进模拟技术的 HumanoidBench。该基…

Java文件操作和IO的小案例

文章目录 案例1案例2案例3 案例1 要求&#xff1a; 扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&#xff08;不包含目录&#xff09;&#xff0c;并且后续询问用户是否要删除该文件。 代码实现&#xff1a; package shixun;import java.io.File; import…

deepstream段错误

&#x1f610; 错误&#xff1a; 探针中由于使用了pyds.get_nvds_buf_surface(hash(gst_buffer), frame_meta.batch_id)导致的段错误&#xff08;segmentation fault&#xff09;。 解决方式&#xff1a;

electron src build

编译文档&#xff1a; 构建说明 | Electron 1 下载depot_tools &#xff08;1&#xff09;安装depot_tools用于获取 Chromium 及其依赖项的工具集&#xff1a;地址 WINDOWS Download the depot_tools bundle and extract it somewhere. (2)在 Windows 上&#xff0c;您需要…

语义分割和实例分割区别?

语义分割&#xff1a;将图像中的每个像素分配给其对应的语义类别&#xff0c;其主要针对于像素&#xff0c;或者说它是像素级别的图像分割方法。&#xff1a;语义分割的目的是为了从像素级别理解图像的内容&#xff0c;并为图像中的每个像素分配一个对象类。 实例分割&#xf…

C++(第五天----多继承、虚继承、虚函数、虚表)

一、继承对象的内存空间 构造函数调用顺序&#xff0c;先调用父类&#xff0c;再调用子类 #include<iostream>using namespace std;//基类 父类 class Base{ public: //公有权限 类的外部 类的内部 Base(){cout<<"Base()"<<endl;}Base(int …

(补充):java各种进制和文本、图像、音频在计算机中的存储方式

文章目录 前言一、进制1 逢几进一2 常见进制在java中的表示3 进制中的转换(1)任意进制转十进制(2)十进制转其他进制二、计算机中的存储1 计算机的存储规则(文本数据)(1)ASCII码表(2)编码规则的发展演化2 计算机的存储规则(图片数据)(1)分辨率、像素(2)黑白图与灰度…

线程池【开发实践】

文章目录 一、为什么要用线程池1.1 单线程的问题1.2 手动创建多线程的问题1.3 线程池的作用&#xff08;优点&#xff09;1.4 线程池的使用场景 二、线程池的基础知识2.1 线程池的核心组件2.2 JUC中的线程池架构2.3 线程池的配置参数2.4 线程池常见的拒绝策略&#xff08;可自定…