1.18 从0开始学习Unity游戏开发--资源加载

news2024/11/18 17:37:43

在上一篇文章中,我们大约是开始接触到资源加载的事情了,场景资源则是一个比较特殊的资源,我们只要添加到Build Settings里面,那么我们就可以通过API直接加载。

但是其他类型的资源怎么办呢?比如我们制作一个网络游戏,接收到后台的返回数据要求给人物装上一把枪,但是我们也不可能把所有枪都作为成员数据赋值上去,肯定是希望用到哪个就加载哪个,所以这个时候就需要支持通过类似名字或者路径的方式加载资源。

因此本章我们将会讲解Unity中资源到底是什么,如何进行加载的,以及几种加载方式适用的场景。

引用形式的加载

之前的篇章里面我们要使用某个资源,都是在代码中加入成员变量,借助Unity的序列化能力显示在编辑器面板上,然后我们通过拖拽等方式,将场景内的物体或者Project窗口里面的资源赋值到对应的变量上去,这种加载资源的方法是通过引用来进行加载的。

之前分析实际场景文件的时候我们有分析过,我们的GameObject也好,组件类也罢,在序列化的时候都会生成一个唯一的id,这个id就是用来存储引用关系,在场景启动的时候就会加载场景里面已有的GameObject,然后根据文件内的id数据来索引所有的引用关系。

但是有一个问题就是,我们之前其实有使用Prefab赋值给场景内物体的组件变量上,那这个引用关系又是如何呢?

我们不妨以文本方式打开Demo.unity文件,找到我们赋值bullet的FireController这个物体的FireController组件:

可以看到这里我们又见到了fileID,但是很显然这个fileID我们是无法在场景文件内搜索到第二个使用的地方,毕竟这里赋值的Prefab是存在于Project窗口里面而非场景里面,那么我们注意到后面还有一个guid,擅长全局搜索的朋友可能会尝试把整个Assets目录都搜索一遍,很快就能找到其实这个guid存在于Bullet.prefab.meta文件中:

打开看内容就是这样:

可以看到这个meta文件里面记录的guid跟我们场景里面引用Prefab的变量上存的guid一致,并且如果你再打开Bullet.prefab就能找到fileID是对应的Prefab上的那个组件。

这个时候其实也就理解了,对于非场景内直接可以引用的资源,场景外的资源文件,都会带有一个.meta文件,这个文件内存储了这个资源的guid,而引用场景外资源的方法就是通过这个guid进行检索。

可以仔细观察,Assets文件夹下所有文件都会带上一个.meta文件,也就是说其实所有文件包括文件夹,在Unity中都是可以被引用的。

这也顺带解答了如果我们的游戏工程要上传git或者svn,p4这样的版本控制系统,.meta文件是一定需要上传的,如果没有上传,其他人打开工程时,Unity会自动生成新的.meta文件,那个时候你的所有通过guid引用的资源都将失效。

当然.meta文件不仅仅存了guid这个信息,还有很多其他的信息,这些我们会在后面每种资源类型进阶教程讲到的时候再详细说明。

在理解清楚Unity针对场景内和场景外资源的引用如何处理之后,其实也就能理解为什么我们的东西打包也能拿到,因为Unity打包是从Build Settings里面加入的场景查找所有资源的引用,所有用到的资源都会打包到最终游戏包中。

Resources文件夹

当我们没有在任何代码成员里面直接引用组件或者GameObject或者Prefab资源的时候,我们如何动态的加载一个Prefab或者什么的资源呢?Unity提供了一个特殊的潜规则,一个名字叫做Resources的文件夹,在你的Assets目录下,任何一个叫Resources的文件夹都可以,可以同时存在多个在不同目录下的Resources文件夹,这些文件夹会被Unity统一识别到,然后你就可以用Resources.Load 这个API加载里面的资源:

Unity - Scripting API: Resources.Load​docs.unity3d.com/ScriptReference/Resources.Load.html

有点类似我们加载新的场景,我们可以通过相对路径来加载Resources文件夹下的内容,注意路径一定需要使用/而不是\来作为路径的分隔符,

例如:

  1. Assets/Test1/Resources/a.prefab,那么你加载的时候用的是a,不带文件后缀名
  2. Assets/Test1/Resources/BB/a.prefab,那么你加载的时候用的是BB/a
  3. Assets/Test2/Resources/BB/a.prefab,你会和2冲突,Unity会告诉你所有Resources文件夹里面的文件不能有一样的相对路径

OK,那我们来试一下,之前我们的Bullet是通过直接赋值给成员变量,我们现在把Prefab资源放到Resources文件夹里面,我们目前没有,所以我们新建一个Resources文件夹,还是Project窗口右键Create->Folder,然后把我们的Bullet prefab文件直接拖进去,相当于剪切。

注意如果你是直接在windows资源管理器里面来做这个操作的话,应该把对应的.meta文件也一起剪切走,之前也说了这个.meta文件带有这个资源的guid信息,如果你不剪切走,那么就会导致原有的引用关系找不到了(虽然现在是直接用Resources来加载,可能不会有影响)。在Unity的Project窗口中看不到.meta文件,因为你剪切资源的时候会自动帮你处理。

然后我们需要修改一下之前创建子弹的FireController的代码:

using UnityEngine;
using Object = UnityEngine.Object;

public class FireController : MonoBehaviour
{
    private bool isMouseDown = false;
    private float lastFireTime = 0f;
    private Vector3 fireDirection;
    private AddVelocity bullet;
    public string bulletResourcesPath;
    public float fireInterval = 0.1f;
    public Transform fireBeginPosition;

    private void Start()
    {
        bullet = Resources.Load<AddVelocity>(bulletResourcesPath);
    }

    void Update()
    {
        if (Input.GetButton("Fire1"))
        {
            if (!isMouseDown)
            {
                isMouseDown = true;
                lastFireTime = Time.time;
                Fire();
            }
            else if (Time.time - lastFireTime > fireInterval)
            {
                lastFireTime = Time.time;
                Fire();
            }
        }
        else
        {
            isMouseDown = false;
        }
    }

    void Fire()
    {
        // 在这里实现每次触发的逻辑

        // 创建新的子弹,每次都是从模板bullet复制一个出来
        AddVelocity newBullet = Object.Instantiate(bullet);
        newBullet.transform.position = fireBeginPosition.position;
        newBullet.SetDirection(fireDirection);
    }

    public void SetDirection(Vector3 direction)
    {
        fireDirection = direction;
    }
}

我们的修改主要是将之前的public成员bullet换成了private成员,我们不再需要序列化这个成员,取而代之的是用了一个string成员来让编辑器上可以填入资源的路径。

然后我们在Start方法里面通过Resources.Load来加载一次这个资源,后续就和之前的使用方法一样。Resources.Load方法是带有泛型,或者用C++的话来讲就是模板类型,填入<>里面的类型将会用类似GetComponent的方法从加载上来的GameObject中获取,当然你想加载上来就是GameObject也完全可以在<>里面填GameObject这个类型。

OK,我们直接在编辑器里面填入我们子弹的资源路径Bullet:

可以再跑起来看看,我们也一样可以创建子弹,获得和之前一样的效果。

这样的加载方法有个缺点:放在Resources文件夹下的资源不会管有没有引用,在打包游戏的时候会全部打包进去,毕竟Unity也不知道你到底要用哪个,所以这个办法比较适合小体量的资源。

AssetDatabase

编辑器模式下专用的加载资源方法,主要用于编辑器下的扩展和功能操作,跟正常游戏的运行逻辑是独立开的,由于涉及到了编辑器的游戏运行时的概念,本章不会讲解,会留到专门讲解编辑器扩展开发的时候再讲。

AssetBundle

Unity提供的正统的游戏打包发布后的正规资源加载方式,但是很多概念理解起来相当麻烦,本大章系列文章还只是初步入门的阶段,暂时不讲这部分,会留到后面详细讲解游戏打包时的资源管理再讲。

思考题

  1. Resources.Load会同步加载资源,阻塞代码执行,显然官方的API有异步版本,如果改成异步应该怎么写?

下一章

上面我们讲解了两个资源加载的方式,一个是通过引用自动加载,一个是通过路径来动态加载。虽然Resources.Load比较挫,但是现阶段足够我们初步学习Unity的资源加载。

下一章我们将会简单入门一下编辑器扩展,Unity编辑器并非一尘不变,而是可以通过我们的代码随心所欲的调整,这也是现代商业游戏引擎提供的编辑器扩展能力,通过扩展能力,我们能更好的让引擎服务于我们的定制化需求。当然了,在其中也会学习到编辑器所跑的逻辑和游戏跑的逻辑这两个概念的区别。

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

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

相关文章

为什么Spring和IDEA不推荐使用@Autowired注解?

在Spring开发中&#xff0c;Autowired注解是一个常用的依赖注入方式。但是&#xff0c;你可能会惊奇地发现&#xff0c;Spring和IDEA都不推荐使用Autowired注解。关于这个问题&#xff0c;其实答案相对统一&#xff0c;实际上用大白话说起来也容易理解。 官方答案 首先&#…

使用springboot解释什么是jwt

目录 使用springboot解释什么是jwt简介组成结构在springboot中的作用1. 添加依赖 在pom.xml文件中添加以下依赖2. 配置JWT 在Spring Boot的配置文件中配置JWT的相关参数&#xff0c;例如密钥、过期时间等&#xff1a;3. 创建JWT工具类 创建一个JWT工具类&#xff0c;用于生成和…

数据治理体系建设

01 数据治理建设路径 1. 业务数字化的目的是打造一体化的业务流、信息流与数据流 从企业整体经营管理的角度&#xff0c;战略制定及分解—领域业务目标制定—业务方案设计—业务需求识别 & 信息系统功能及数据库设计—数据汇聚及分析—业务目标监测及改善&#xff0c;这个…

Mysql安装详细教程

数据库相关概念 而目前主流的关系型数据库管理系统的市场占有率排名如下&#xff1a; Oracle&#xff1a;大型的收费数据库&#xff0c;Oracle公司产品&#xff0c;价格昂贵。 MySQL&#xff1a;开源免费的中小型数据库&#xff0c;后来Sun公司收购了MySQL&#xff0c;而Oracle…

PEIS体检管理系统源码,自主知识产权,文档齐全,功能完善

PEIS体检管理系统源码&#xff0c;自主知识产权&#xff0c;文档齐全&#xff0c;有演示。 体检条码化管理&#xff0c;体检数据比对&#xff0c;丰富的诊断模板&#xff0c;自动产生小结、综述和建议。 文末获取联系&#xff01; PEIS体检管理系统对医院体检中心进行系统化和…

java二维数组遍历

在 java中&#xff0c;二维数组是指在二维平面上的一个数组。在二维数组中&#xff0c;数据都是按行排序的。我们通常可以用“从上到下”、“从左到右”、“从后到前”等方法来遍历二维数组。由于二维数组中数据的有序性&#xff0c;我们可以在二维数组中快速地找到我们所需要的…

手机穿戴设备能力共享,提升丰富交互体验

HUAWEI Wear Engine面向手机和穿戴设备的应用与服务开发者&#xff0c;提供华为穿戴设备开放能力。 开发者通过调用Wear Engine开放能力&#xff0c;可以实现手机上的生态应用与服务给华为穿戴设备发消息、发通知、传输数据&#xff0c;并获取穿戴设备状态、读取传感器数据等&…

65W氮化镓(GaN)充电头PD快充方案

2023年数码圈中讨论较多的莫过于65W氮化镓&#xff08;GaN&#xff09;充电头。65W快充是目前快充市场出货的主流规格&#xff1b;氮化镓具有高可靠性&#xff0c;能够承受短时间过压&#xff1b;将GaN用于充电器的整流管后&#xff0c;能降低开关损耗和驱动损耗&#xff0c;提…

超清大屏沉浸音效,用极米H6 4K版看剧更有代入感

近日&#xff0c;由张译主演的悬疑剧《他是谁》开播&#xff0c;该剧主要讲述了以卫国平(张译饰)为首的刑警坚持不懈8年追凶&#xff0c;帮受害者讨回公道的故事。《狂飙》作为现象级爆款剧落幕不久&#xff0c;饰演刑警安欣的影帝张译&#xff0c;又在悬疑剧《他是谁》中主演刑…

本地套接字(domain)

本地套接字是一种特殊类型的套接字&#xff0c;和 TCP/UDP 套接字不同。TCP/UDP 即使在本地地址通信&#xff0c;也要走系统网络协议栈&#xff0c;而本地套接字&#xff0c;严格意义上说提供了一种单主机跨进程间调用的手段&#xff0c;减少了协议栈实现的复杂度&#xff0c;效…

consul集群搭建教程

简言 1. 使用consul单节点有宕机&#xff0c;数据丢失的风险&#xff0c;为了安全&#xff0c;使用consul集群更靠谱 2. consul的各个版本下载地址在 Consul Versions | HashiCorp Releases 3. 本文使用consul的版本是consul1.15.1&#xff0c;所以请下载名字为 consul_1.15…

数据密集型应用存储与检索设计

本文内容翻译自《数据密集型应用系统设计》&#xff0c;豆瓣评分高达 9.7 分。 什么是「数据密集型应用系统」&#xff1f; 当数据&#xff08;数据量、数据复杂度、数据变化速度&#xff09;是一个应用的主要挑战&#xff0c;那么可以把这个应用称为数据密集型的。与之相对的是…

免费文本转语音(在线文本转语音)

个人开发的网站&#xff0c;已经维护快一年了&#xff0c;接口稳定&#xff0c;基于微软官方接口&#xff0c;可在线生成&#xff0c;手机电脑平板通用。每天提供一定额度&#xff08;时而5000时而2000时而500&#xff0c;根据服务器压力调整&#xff09;的免费字数供大家使用。…

数画-AI绘画-免费的人工智能AI绘画网站

文章目录 AIGC什么是AI作画&#xff1f;Prompt数画AIGC的未来发展结语 AIGC AIGC&#xff08;AI Generated Content&#xff09;是指利用人工智能生成内容。是利用人工智能来生成你所需要的内容&#xff0c;GC的意思是创作内容。与之相对应的概念中&#xff0c;比较熟知的还有P…

瑞芯微RK3568对比RK3399性能解析

RK3568核心板简介 ​ RK3568核心板是武汉万象奥科基于瑞芯微Rockchip的RK3568设计的一款高性能核心板。它采用四核Cortex-A55架构&#xff0c;最高主频可达2.0GHz&#xff0c;同时集成Mali-G52 2EE GPU&#xff0c;支持4K60fps H.265/H.264/VP9解码和4K60fps H.265/H.264编码…

北大POJ 1000 ~ 1007

1. AB &#x1f351; POJ1000 ab &#x1f354; 签到题 import java.io.*; import java.util.*; public class Main {public static void main(String args[]) throws Exception{Scanner cinnew Scanner(System.in);int acin.nextInt(),bcin.nextInt();System.out.println(…

【Vue3】Vue项目各个配置文件的相关用途

通过Vue Cli创建好初始代码后&#xff0c;对于各个文件以及配置文件的用途&#xff0c;比较模糊。弄清楚配置文件的大致作用&#xff0c;十分有利于项目整体性的把控&#xff0c;在实际项目中例如修改配色、样式、统一页面结构等&#xff0c;都可以事半功倍。 1、package.json …

分享下这些软件外包公司(2023最新版),程序员有福了

金三银四已经过去一半&#xff0c;再过几个月又将迎来毕业季&#xff0c;大家有没有找到心仪的工作机会呀&#xff1f; 今年找工作的行情确实不行&#xff0c;在网上也能听见很多人在讨论说今年工作实在是太难找了。 如果实在找不到合适的工作&#xff0c;那外包也可以考虑下了…

【LeetCode】102.二叉树的层序遍历

1.问题 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] 示例 2&#xff1a…

Centos7配置静态ip地址

目录 查找配置网络的文件 配置静态ip VMware查找网关ip Windows Mac 查找配置网络的文件 先输入以下命令查看下ip是通过哪个文件来配置的 ip addr 修改网络配置文件&#xff08;注意看我上面查到的是ens32, 所以在ifcfg-后面拼的是这个&#xff09; vi /etc/sysco…