麦田物语学习笔记:保存和加载场景中的物品
目录
基本流程
现在在切换场景后,场景中的物品即使被拾取了,也还是会被重新加载出来,所以本篇文章的任务是在切换场景前后能保留当前场景的数据
1.代码思路
(1)为了保留处在地上的物品数据,就需要保存物品的坐标,以及这个物品是什么,所以在卸载场景之前读取要卸载的场景中的物品都有什么,重新加载场景的时候,按照之前的进度把物品再生成出来
(2)创建一个存储数据的字典,这个字典需要把场景的名字和物品的信息存储在一起,由于一个场景里有多个物品,那么就需要一个列表来保存
2.代码实现
新增和修改ItemManager.cs的代码
private Dictionary<string, List<SceneItem>> sceneItemDict = new Dictionary<string, List<SceneItem>>();
private void OnEnable()
{
EventHandler.InstantiateItemInScene += OnInstantiateItemInScene;
EventHandler.BeforeSceneUnloadEvent += OnBeforeSceneUnloadEvent;
EventHandler.AfterSceneLoadedEvent += OnAfterSceneLoadedEvent;
}
private void OnDisable()
{
EventHandler.InstantiateItemInScene -= OnInstantiateItemInScene;
EventHandler.BeforeSceneUnloadEvent -= OnBeforeSceneUnloadEvent;
EventHandler.AfterSceneLoadedEvent -= OnAfterSceneLoadedEvent;
}
private void OnBeforeSceneUnloadEvent()
{
GetAllSceneItems();
}
private void OnAfterSceneLoadedEvent()
{
itemParent = GameObject.FindWithTag("ItemParent").transform;
RecreateAllItems();
}
/// <summary>
/// 获得当前场景所有Item
/// </summary>
private void GetAllSceneItems()
{
List<SceneItem> currentSceneItems = new List<SceneItem>();
foreach (var item in FindObjectsOfType<Item>())
{
SceneItem sceneItem = new SceneItem
{
itemID = item.itemID,
position = new SerializableVector3(item.transform.position)
};
currentSceneItems.Add(sceneItem);
}
if (sceneItemDict.ContainsKey(SceneManager.GetActiveScene().name))
{
//找到数据就更新Item数据列表
sceneItemDict[SceneManager.GetActiveScene().name] = currentSceneItems;
}
else //如果是新场景
{
sceneItemDict.Add(SceneManager.GetActiveScene().name, currentSceneItems);
}
}
/// <summary>
/// 刷新重建当前场景的物品
/// </summary>
private void RecreateAllItems()
{
List<SceneItem> currentSceneItems = new List<SceneItem>();
if (sceneItemDict.TryGetValue(SceneManager.GetActiveScene().name, out currentSceneItems))
{
if (currentSceneItems != null)
{
//清场
foreach (var item in FindObjectsOfType<Item>())
{
Destroy(item.gameObject);
}
foreach (var item in currentSceneItems)
{
Item newItem = Instantiate(itemPrefab, item.position.ToVector3(), Quaternion.identity, itemParent);
newItem.Init(item.itemID);
}
}
}
}
DataCollection新增可序列化坐标和场景中的物品
[System.Serializable]
//可序列化的坐标
public class SerializableVector3
{
//坐标
public float x, y, z;
public SerializableVector3(Vector3 pos)
{
this.x = pos.x;
this.y = pos.y;
this.z = pos.z;
}
public Vector3 ToVector3()
{
return new Vector3(x,y,z);
}
public Vector2Int ToVector2Int()
{
return new Vector2Int((int)x, (int)y);
}
}
[System.Serializable]
public class SceneItem
{
public int itemID;
public SerializableVector3 position;
}
对调TransitionManager中呼叫加载场景之后的事件以及场景淡出效果的顺序
private IEnumerator Transition(string sceneName, Vector3 targetPosition)
{
//呼叫卸载场景之前要做的事
EventHandler.CallBeforeSceneUnloadEvent();
yield return Fade(1);
yield return SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());
yield return LoadSceneSetActive(sceneName);
//移动人物坐标
EventHandler.CallMoveToPosition(targetPosition);
//呼叫加载场景之后的事件
EventHandler.CallAfterSceneLoadedEvent();
yield return Fade(0);
}
最终效果
拾取物品切换场景后,场景中的物品并不存在
补充知识点
1.序列化
序列化,简单来说就是将对象转化为可传输的字节序列的过程叫做序列化,
这里的对象指的任意脚本或Unity文件,
可以将对象转换为字节序列后,存储在数据库,内存或者文件中
2.委托
虽然在该专栏里的其他文章中补充过该知识,但是该视频是我遇到过的把委托讲的最通透的
因此再次提出并记录在这个文章中
up主的其他视频也非常高质量,推荐观看
原文地址:https://blog.csdn.net/2301_77491688/article/details/145282850
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!