【总结】Unity:代码动态加载Prefab预设体

本文详细介绍了如何在Unity中将预制体(.prefab)文件从Resources文件夹中动态加载到场景,并对其进行实例化及属性设置的过程。通过实例演示了常见错误及其正确做法。

转自:http://blog.youkuaiyun.com/linshuhe1/article/details/51355198


在进行一些功能开发的时候,我们常常将一些能够复用的对象制作成.prefab的预设物体,然后将预设体存放到Resources目录之下,使用时再动态加载到场景中并进行实例化。例如:子弹、特效甚至音频等,都能制作成预设体。


一、预设动态加载到场景:

        一个预设体要能够通过代码控制在场景中进行显示,需要三个步骤,这里我们以动态加载怪物血条为例子分析一个常见的误区:

1.预设体资源加载:

  1. //加载预设体资源  
  2. GameObject hp_bar = (GameObject)Resources.Load("Prefabs/HP_Bar");  

        

            通过上述操作,实现从资源目录下载入HP_Bar.prefab预设体,用一个GameObject对象来存放,此时该预设物体并未真正载入到场景中,因为还未进行实例化操作。


2.预设体实例化:

        在第一步中我们已经将预设体资源加载完毕,但是为实例化的资源不会出现在场景中,所以第二不我们需要对资源进行实例化,实例化使用的是MonoBehaviour.Instantiate函数来完成的,其实质就是从预设体资源中克隆出一个对象,它具有与预设体完全相同的属性,并且被加载到当前场景中:

  1. //实例化预设体  
  2. Instantiate(hp_bar);  

        完成以上代码之后,在当前场景中会出现一个实例化之后的对象,可以在Hierarchy栏中查看到:

        
        因为我们没有对此实例化后的对象进行任何的属性设置,所以其属性与预设体最初的属性保持一致,并且其父节点默认为当场的场景对外层。


3.实例化对象属性设置(可选):

        完成上述步骤之后,我们已经可以在场景中看到实例化之后的对象,但是通常情况下我们喜欢我们的对象之间层次感分明,而且这样也方便我们进行对象统一管理,而不是在Hierarchy中看到一大堆并排散乱对象,所以我们需要为对象设置名称已经父节点等属性。

常见错误:对未初始化的hp_bar进行属性设置,设置之后的属性在实例化之后无法生效。这是因为我们最后在场景中显示的其实并非实例化前的资源对象,而是一个克隆对象,所以假如希望设置的属性在最后显示出来的对象中生效,我们需要对实例化之后的对象进行设置。)

        正确的设置代码如下,可以看到实例化对象已成功挂在到父节点Canvas上:

  1. GameObject hp_bar = (GameObject)Resources.Load("Prefabs/HP_Bar");  
  2. GameObject mUICanvas = GameObject.Find("Canvas");  
  3. hp_bar = Instantiate(hp_bar);  
  4. hp_bar.transform.parent = mUICanvas.transform;  

        

        其实前两个步骤可以在一起完成,简化后的写法如下:
  1. GameObject hp_bar = (GameObject)Instantiate(Resources.Load("Prefabs/HP_Bar"));  
  2. GameObject mUICanvas = GameObject.Find("Canvas");  
  3. hp_bar.transform.parent = mUICanvas.transform;  

### 实现Unity动态加载并显示滚动信息的预设体的方法 在 Unity 中实现动态加载并显示滚动信息的预设体,通常需要结合 `Scroll View` 和动态生成预设体的技术。以下是具体的实现方法和代码示例。 #### 一、创建 Scroll View 首先,在 Unity 编辑器中创建一个 `Scroll View` 并设置其布局为垂直或水平滚动。确保 `Content` 对象的 `Rect Transform` 设置为适合滚动的方向。 #### 二、动态加载预设体 动态加载预设体的过程包括以下步骤: 1. 创建一个预制体(Prefab),并在其中定义所需的信息显示格式。 2. 在脚本中使用 `Instantiate` 方法动态实例化该预制体,并将其添加到 `Scroll View` 的 `Content` 容器中。 ```csharp using UnityEngine; using System.Collections.Generic; public class ScrollViewManager : MonoBehaviour { public GameObject itemPrefab; // 预设体 public Transform contentPanel; // ScrollView 的 Content 区域 public List<string> data = new List<string>(); // 数据源 void Start() { // 初始化数据 data.Add("Item 1"); data.Add("Item 2"); data.Add("Item 3"); // 动态加载预设体 foreach (var item in data) { GameObject newItem = Instantiate(itemPrefab, contentPanel); newItem.transform.Find("Text").GetComponent<UnityEngine.UI.Text>().text = item; } } } ``` 此代码将根据 `data` 列表中的内容动态生成预设体[^1]。 #### 三、处理滑动事件 为了实现滚动时的动态更新或吸附效果,可以监听 `OnValueChanged` 事件,并根据滑动位置调整内容。 ```csharp using UnityEngine; using UnityEngine.EventSystems; public class ScrollViewListener : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public void OnBeginDrag(PointerEventData eventData) { Debug.Log("Begin Dragging..."); } public void OnDrag(PointerEventData eventData) { Debug.Log("Dragging..."); } public void OnEndDrag(PointerEventData eventData) { Debug.Log("End Dragging..."); } } ``` 上述代码实现了对滑动事件的监听[^2]。 #### 四、解决常见问题 如果在运行时发现预设体无法正确显示,可能是由于以下原因: 1. 缺少 `Canvas Renderer` 组件:确保每个 UI 元素都包含此组件[^2]。 2. 渲染层次问题:检查是否有多余的 `Canvas` 组件,尝试使用多个 `Canvas` 分层渲染。 #### 五、性能优化 为了提高性能,可以采用对象池技术来管理预设体的实例化和销毁。通过复用已存在的游戏对象,减少频繁的 `Instantiate` 和 `Destroy` 操作。 ```csharp using System.Collections.Generic; public class ObjectPool { private Queue<GameObject> pooledObjects = new Queue<GameObject>(); private GameObject prefab; private Transform parent; public ObjectPool(GameObject prefab, int size, Transform parent) { this.prefab = prefab; this.parent = parent; for (int i = 0; i < size; i++) { GameObject obj = Instantiate(prefab, parent); obj.SetActive(false); pooledObjects.Enqueue(obj); } } public GameObject GetPooledObject() { if (pooledObjects.Count > 0) { GameObject obj = pooledObjects.Dequeue(); obj.SetActive(true); return obj; } else { return Instantiate(prefab, parent); } } public void ReturnObjectToPool(GameObject obj) { obj.SetActive(false); pooledObjects.Enqueue(obj); } } ``` 此代码实现了对象池功能,用于优化滚动列表的性能[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值