找回密码
 立即注册
查看: 148|回复: 0

1.13 从0开始学习Unity游戏开发--动态创建物体

[复制链接]
发表于 2024-7-15 18:25 | 显示全部楼层 |阅读模式
在之前的篇章里面,我们已经学习到了编纂场景就直接在编纂器里面新建一个GameObject,非论是立方体也好,还是一个球体也罢,我们也都可以通过代码里面新建一个可以序列化的GameObject变量后,在编纂器面板上赋值引用到这个物体。
但是很显然作为法式员,我们更但愿了解到,如何脱离这样的机制来自行创建物体和操控物体,这样操作虽然对艺术创作很有辅佐,但是对一些业务逻辑来说就很难搞了,比如游戏中常见的刷怪,就需要按照游戏逻辑来动态的创建怪物,我们总不成能在场景里面编纂好所有可能的情况吧。
那么本章我们就会讲解如何通过代码来动态创建物体,以及如何组件化的打点我们的物体和逻辑。
代码动态创建GameObject

其实代码创建GameObject很简单:
  1. GameObject myNewGameObject = new GameObject();
复制代码
直接new就可以了,随便找个组件,比如找一个我们之前写的CameraController的Start函数,加上这个代码,然后跑起来游戏,看看:


可以看到多了一个叫New Game Object的东西,当然你可以通过设置GameObject的name来给个名字:
  1. GameObject myNewGameObject = new GameObject();
  2. myNewGameObject.name = ”Dynamic Game Object”;
复制代码

但是我们此刻这个物体还是个空的,啥都没有,我们但愿给这个物体加上组件,那没啥问题
  1. GameObject myNewGameObject = new GameObject();
  2. myNewGameObject.name = ”Dynamic Game Object”;
  3. myNewGameObject.AddComponent<DemoTest>();
复制代码
这样我们就通过代码来实时动态的添加物体的组件。
那么动态创建GameObject的逻辑就是这样的,是不是很简单明了?
如果不需要这个GameObject了,记得销毁它,这是一个好习惯。
  1. GameObject myNewGameObject = new GameObject();
  2. myNewGameObject.name = ”Dynamic Game Object”;
  3. myNewGameObject.AddComponent<DemoTest>();
  4. Destroy(myNewGameObject);
复制代码
那么这个动态创建出来的GameObject就会被销毁了。
这个Destroy函数是来自UnityEngine.Object类型,也就是说在任何组件类里面都可以调用的到。当然如果在本身写的纯C#类里面也可以使用,毕竟是个静态函数,直接换成Object.Destroy()就可以了。需要注意的是C#的System下也有一个Object类,如果没有指明using哪个,在同时using System和UnityEngine的时候会冲突,不知道你要用哪个Object类,这个时候要么写全:
  1. UnityEngine.Object.Destroy(myNewGameObject);
复制代码
要么指定using的是哪个:
  1. using Object = UnityEngine.Object;
复制代码
此外既然我们提到了如何给GameObject动态添加组件,而动态删除组件也是Object.Destroy函数:
  1. DemoTest newlyAddedComponent = myNewGameObject.GetComponent<DemoTest>();
  2. UnityEngine.Object.Destroy(newlyAddedComponent);
复制代码
这个在使用的时候其实挺容易搞混,本来是想着删除GameObject,但是传入了一个组件类,导致删的是组件。
那么到这里,其实可以想象到,我们可能会为了动态创建一个物体,需要写一大串的代码,新建一个GameObject,然后组件一个个添加,搞得跟手动写UI界面一样。很显然Unity也会提供一个组件化的功能给我们使用,让我们创建一个类似模板的东西,以后可以通过直接创建模板的新实例,避免反复编写大量代码,而这个模板叫做Prefab。
Prefab

Prefab翻译过来叫预制体,顾名思义就是预先制作好的物体,非常像我们写代码要先定义一个Class的定义,然后再实例化这个定义的各个实例。
那么我们如何创建Prefab呢?
假设我们有一个需要做成Prefab供以后复用的GameObject,我们先在场景里面创建它,就叫PrefabTest:


然后我们可以给它加点组件,例如加个DemoTest组件。
然后我们可以如上图一样选中后,按住左键拖拽到Project窗口中的任意目录下,当然可以选择你但愿Prefab存放的目录:


然后可以看到Project窗口里面多出了一个PrefabTest的资源,而且图标是个蓝色的立方体,注意不雅察看Hierarchy窗口里面的PrefabTest也变成蓝色立方体的图标了。
这里发生了两个事情:

  • 当你拖拽场景物体到Project窗口的时候,Unity认为你是但愿将这个场景物体转换成一个Prefab,所以Project窗口中呈现了转换后的资源
  • 场景中本来的物体被这个Prefab创建的实例所替代了
此刻我们选中一下Project窗口里面的PrefabTest,是不是跟我们创建的内容一模一样,那么为什么会叫Prefab呢?我们测验考试改削一下DemoTest组件里面的值,然后再去看场景中这个PrefabTest的DemoTest组件的值,你会发现Project窗口里面PrefabTest的改削会同步参加景里面关联的物体。
这样其实就可以理解,Project窗口里面阿谁PrefabTest资源其实就是我们理解的Class的定义,而场景里面的则是我们用这个定义实例化出来的一个实例。
那么熟悉代码的我们应该就能很简单的触类旁通:

  • 我们可以拖拽Project窗口里面的PrefabTest资源参加景中,每次拖拽城市创建一个新的实例
  • 我们改削Project窗口里面的PrefabTest资源的数据,会同步到每个由它创建在场景里面的实例
  • 我们在实例里面的改削是每个实例独立的,不会反馈回Project窗口里面的PrefabTest资源本身
我相信各位法式员应该是不需要讲解这些跟Class一样的概念的。
那么其实针对3,Unity是提供了一个回写的功能,也就是说我们可以将实例的改削写回到母体本身。
比如说我们改削了场景里面PrefabTest实例的数据:


这里我们改削了Test Value1,那么左边会有一个蓝色的条状,暗示这个值被改削了,不是默认值,那么我们可以右键Test Value 1这个标签,可以看到Apply to Prefab &#39;PrefabTest&#39;


点击的话,我们的改削Test Value 1=3这个值,就会写到Project窗口阿谁PrefabTest里面,同时我们场景里面这个PrefabTest这里的蓝色条会消掉。
其实就是改削了Class的定义这样一个事情。
这么做有什么好处呢?很显然我们写代码的时候都经常需要改削Class本身的定义,做游戏开发的时候,由于创意的调整,我们经常需要改削各种东西,包罗已经做好的Prefab资源,但是改削的时候往往我们是拖拽参加景里面跟其他物体一起看效果,所以当我们在场景里面联动调整好后,通过这样一个Apply的功能,就能斗劲便利的改削原先的Prefab资源。
当我们有很多处所进行了改削,可以直接点击Inspector上的Overrides查看所有改削,进行批量撤销或者批量Apply:


当然,我们也可以直接改削Project里面的Prefab本身,而且如果Prefab本身内部有内容的话,双击Prefab资源即可打开内部进行改削。
下一章

本章我们讲解了如何动态的创建GameObject和动态添加组件,然后同时讲解了如何使用Prefab来达成我们的资源和逻辑复用的目的,而且详细的讲解了Prefab和其示例的关系。
了解完这些后,其实我们已经可以实现一些基础的逻辑,比如点击鼠标左键动态创建一个子弹,而且Update函数里面改削子弹的位置来完成子弹发射的功能。
那么如何让子弹更加真实,比如拥有重力下坠的能力,如何计算子弹击中了方针,下一章我们会讲解Unity中常用的物理引擎的组件和使用方式,而且也会讲解如何实现一个人物的行走逻辑,当学习完毕后,你将能够制作一个小型的射击游戏demo。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-21 20:45 , Processed in 0.313409 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表