> 如果您需要一個項目才能練習,請以下是我們在上一個教程中完成的項目的版本。它已經使用了一對源自產生的物品的遊戲內相互作用的對象進行升級 - 一把藥水和一把劍。它們可以產生並
拾取>(
下載項目啟動文件
>項目github頁面
項目zip下載
鑰匙要點
>利用委託事件系統來通知對象何時保存其狀態,增強保存/加載系統的模塊化和靈活性。
>使用可序列化類來保存對象屬性(例如位置),可以輕鬆地擴展或修改針對不同類型的對象。 >
確保正確訂閱和取消訂閱以將事件保存在對像腳本中以避免錯誤並有效地管理遊戲狀態。
- 開發一個可靠的系統,用於使用二進制格式來保存和加載,以處理複雜的數據結構並確保數據完整性。
- 測試並擴展系統以包括新的對像類型和功能,證明了系統的適應性和針對不同遊戲開發需求的可伸縮性。
- 實施理論
- >我們需要在實現該對象之前分解保存和加載對象的系統。首先,我們需要某種將產生和絕望對象的對象
- 級別的主體。它需要在級別中保存對象(如果我們正在加載級別而不是重新啟動),Despawn拾取對象,通知對象需要保存自己並管理對象列表。聽起來很多,所以讓我們將其放入流程圖中:
-
>基本上,整個邏輯都將對象列表保存到硬盤驅動器中 - 下次加載級別時,將在我們開始播放時產生的所有對象。聽起來很容易,但是魔鬼在細節中:我們如何知道要保存哪些對象,以及我們如何將它們產生回去?
>>委託和事件
>在上一篇文章中,我提到我們將使用委託事件系統通知對象需要保存自己的對象。讓我們首先解釋什麼是代表和事件。
>>您可以閱讀官方代表文檔和官方事件文檔。但請放心:即使我也不了解官方文檔中的很多技術,所以我會用簡單的英語說:
委託> public delegate void SaveDelegate(object sender, EventArgs args);
這個委託描述了一個函數,該函數什麼都沒有返回(void),並接受.NET/MONO框架的兩個標準參數:代表事件發送者的通用對象,以及最終可以使用的參數,您可以使用這些數據傳遞各種數據。您真的不必擔心這一點,我們可以將(Null,Null)作為爭論,但必須在那裡。>
>事件。它僅接受與委託(藍圖)匹配的函數,並且您可以在運行時刪除並刪除函數。 然後,您可以隨時觸發事件,這意味著運行當前框中的所有功能 - 立即運行。考慮以下事件聲明: >訂閱並取消訂閱
public event SaveDelegate SaveEvent;
訂閱事件基本上意味著“將功能放在框中”。語法很簡單。讓我們假設我們的事件在我們著名的全球視頻類別中聲明,並且我們有一些名為> potiondroppobable
的藥水對像類,需要訂閱事件:> >
>當我們擁有它時,我們只是在腳本開始或清醒時將該功能放在框中,然後在被銷毀時將其刪除。 (取消訂閱非常重要:如果您嘗試調用被破壞對象的函數,則在運行時會得到null引用異常)。我們通過訪問已聲明的事件對象,然後使用添加操作員然後使用功能名稱來做到這一點。
>注意:我們沒有使用括號或參數調用函數;我們只是使用該函數的名稱,別無其他。
>因此,讓我們解釋一下這一切最終在遊戲的某個示例流中的作用。
>邏輯流> >
這四個對像在保存事件中註冊其功能:> >然後,假設玩家決定保存遊戲 - 也許他們確實需要回答現在響了三遍的手機(嘿,您做了一個很棒的遊戲):
基本上,發生的事情是框中的功能一個一個一個一個一個一個一個觸發的功能,並且在所有功能完成之前,遊戲才能運行到任何地方。每個“保存自身”的對象基本上都在列表中寫下自己 - 在下一個遊戲負載上,將由級別的主對象進行檢查,列表中的所有對像都將進行實例化(產生)。就是這樣:如果您到目前為止遵循了這篇文章,那麼您基本上就可以立即開始實施它。但是,我們將在這裡進行一些具體的代碼示例,一如既往,如果您想看看整個事物應該如何看,就會有一個完成的項目在文章結束時等待您。
>
f5/f9
來保存/加載,則產生的對象將消失。
盒子產卵器和產卵的對象本身使用了一個簡單的可交互接口機械師,該機制使我們能夠識別到這些對象,在屏幕上寫入文本,然後使用[e]鍵與它們進行交互。
沒有更多的存在。我們在這裡的任務是:
- 列出藥水 的列表
- 列出劍對象的列表
- 實施全局保存事件
- >使用保存功能訂閱事件
- 實現級別主對象 如果我們加載了遊戲,則
- 使級別主產生所有保存的對象。 >
>
>對像類列表>以類似的方式,我們需要一些代表我們對象的可序列化類。要編寫它們,我們需要知道我們需要保存的屬性 - 對於我們的玩家,我們有很多東西要保存。幸運的是,對於對象,您很少需要比他們的世界地位更多。在我們的示例中,我們只需要保存對象的位置,而無需保存。
為了很好地構建我們的代碼,我們將從一個簡單的類開始,從我們的序列化末尾開始:
>public delegate void SaveDelegate(object sender, EventArgs args);
>到目前為止,您可能已經註意到我使用了很多詞> droppable
。這是因為我們需要區分可輟學的(產生)對象和可放置的對象,這些對象遵循不同的保存和產卵規則。我們稍後再解決。>
現在,與玩家的數據不同,我們知道在任何給定時間實際上只有一個玩家,我們可以擁有多個諸如藥水之類的對象。我們需要列出一個動態列表,並表示此列表所屬的場景:我們不能在Level1中spawn Level2的對象。這很容易做到,再次在序列化中。在我們的最後一堂課下面寫這篇文章:
public delegate void SaveDelegate(object sender, EventArgs args);
列出這些列表實例的最佳場所將是我們的全球控制類別:
public event SaveDelegate SaveEvent;
>現在我們的列表非常好:稍後我們將在需要產卵項目時從LevelMaster對象訪問它們,並從GlobalControl內部的硬盤驅動器中保存/加載,就像我們已經使用Player Data一樣。
>委託和事件
啊,終於。讓我們實施著名的活動。
在GlobalControl中>
//In PotionDroppable's Start or Awake function: GlobalObject.Instance.SaveEvent += SaveFunction; //In PotionDroppable's OnDestroy() function: GlobalObject.Instance.SaveEvent -= SaveFunction; //[...] public void SaveFunction (object sender, EventArgs args) { //Here is code that saves this instance of an object. }
如您所見,我們正在使活動成為靜態參考,因此以後更邏輯且更易於工作。>
>有關事件實施的最後一個說明:只有包含事件聲明的類才能解僱事件。任何人都可以通過訪問globalcontrol.saveevent = ...來訂閱它,但是只有GlobalControl類才能使用SaveEvent(null,null)觸發它。嘗試使用globalcontrol.saveevent(null,null);從其他地方導致編譯器錯誤!>
就是事件實施!讓我們訂閱一些東西!>
>事件訂閱開始聆聽
我們需要一個在事件觸發時運行的函數 - 對於每個對象。讓我們在在觸發事件時進行反應。
>pickups
在PotionDroppable中,添加以下內容: 我們正確地進行了訂閱並取消訂閱活動。現在,問題仍然存在,>文件夾中轉到PotionDroppoppable腳本。注意:Sword還沒有設置其腳本;我們將稍後完成!
>[Serializable] public class SavedDroppablePotion { public float PositionX, PositionY, PositionZ; } [Serializable] public class SavedDroppableSword { public float PositionX, PositionY, PositionZ; }
如何將此對象保存在列表中? > 我們首先需要確保我們有針對當前場景初始化的對象列表。 在GlobalControl.cs中: 此功能需要每個級別觸發一次。問題是,我們的全球控制範圍及其開始和清醒功能僅發射一次。我們將通過簡單地從我們的級別主對象調用此函數來解決這個問題,我們將在稍後創建。 我們將需要一個小的輔助功能來返回當前的活動場景列表。在GlobalControl.cs中:[Serializable] public class SavedDroppableList { public int SceneID; public List<saveddroppablepotion> SavedPotions; public List<saveddroppablesword> SavedSword; public SavedDroppableList(int newSceneID) { this.SceneID = newSceneID; this.SavedPotions = new List<saveddroppablepotion>(); this.SavedSword = new List<saveddroppablesword>(); } }</saveddroppablesword></saveddroppablepotion></saveddroppablesword></saveddroppablepotion>
現在,我們確定我們始終有一個列表可以保存我們的物品。讓我們回到我們的藥水腳本:public List<saveddroppablelist> SavedLists = new List<saveddroppablelist>(); </saveddroppablelist></saveddroppablelist>
public delegate void SaveDelegate(object sender, EventArgs args); public static event SaveDelegate SaveEvent;
這是我們所有句法糖塗層真正發光的地方。當您需要時,這是非常可讀,易於理解且易於改變的需求!簡而言之,我們創建了一個新的“藥水”表示,並將其保存在實際列表中。創建一個級別的主對象
首先,一小部分準備工作。在我們現有的項目中,我們有一個全局變量,可以告訴我們是否正在加載場景。但是,我們沒有這樣的變量來告訴我們是否使用門過渡。我們希望當我們返回上一個房間時,所有掉落的對象仍然存在,即使我們沒有在兩者之間的任何位置保存/加載遊戲。 為此
在TransitionScript中>
public delegate void SaveDelegate(object sender, EventArgs args);
我們已經準備好製作一個正常工作的levelmaster對象。
>public event SaveDelegate SaveEvent;
>現在,我們只需要讀取列表並在加載遊戲時從它們中產生對象。這就是級別主體對象所做的。讓我們創建一個新腳本,並將其稱為levelmaster
:> 這是很多代碼,所以讓我們將其分解。
>//In PotionDroppable's Start or Awake function: GlobalObject.Instance.SaveEvent += SaveFunction; //In PotionDroppable's OnDestroy() function: GlobalObject.Instance.SaveEvent -= SaveFunction; //[...] public void SaveFunction (object sender, EventArgs args) { //Here is code that saves this instance of an object. }
>如果我們
是加載場景,我們需要獲取我們的本地副本保存的對象列表(只是為了在重複訪問GlobalControl,
>和 的重複訪問時節省一些性能使語法更可讀)。 接下來,我們只需遍歷列表,並在其中催生所有藥水對象。產卵的確切語法基本上是實例化方法過載之一。我們必須將實例化方法的結果投入到> gameObject(由於某種原因,默認返回類型是簡單的對象),以便我們可以訪問其轉換並更改其位置。 >這是對象產生的地方:如果您需要在產卵時間更改任何其他值,那麼這是這樣做的地方。 >
我們需要將我們的級別主體放在每個場景中,並為其分配有效的預製:>
>現在我們只缺少一個關鍵作品:我們需要實際啟動活動,將列表序列化為硬盤驅動器並從中讀取。我們將在GlobalControl中的現有保存和加載功能中簡單地做到這一點:這似乎也有很多代碼,但是其中大多數已經存在。 (如果您遵循我以前的教程,您將識別二進制序列化命令;這裡唯一的新事物是FiresaveEvent函數,還有一個保存我們列表的附加文件。就是這樣!
>初始測試
如果您現在運行項目,則每次點擊> f5
andf9 [Serializable] public class SavedDroppablePotion { public float PositionX, PositionY, PositionZ; } [Serializable] public class SavedDroppableSword { public float PositionX, PositionY, PositionZ; }
>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>這樣)。但是,還有一個問題要解決:我們沒有保存劍。
這僅僅是為了演示如何在建立類似基礎的基礎後向項目中添加新的可保存的對象。
擴展系統
>因此,假設您已經有了一個新的對象覆蓋系統,就像我們已經對劍對象所做的一樣。它們目前的交互不多(基本物理學之外),因此我們需要編寫一個類似於藥水的腳本,這將使我們能夠“撿起”劍並使其正確保存。
>當前要產生的劍的預製可以在資產> prefabs文件夾中找到。
>讓它起作用。轉到資產>腳本>拾音器,在那裡您會看到
potiondroppable
腳本。旁邊,創建一個新的SwordDroppoppable腳本:public delegate void SaveDelegate(object sender, EventArgs args);
不要忘記“可相互作用”的接口實現。非常重要的是:如果沒有它,您的劍將不會被攝像機射線廣播所識別,並且將保持不可分割效果。另外,請仔細檢查劍前是否屬於項目層。否則,Raycast將再次忽略它。現在,將此腳本添加到劍前的第一個孩子(實際上具有網狀渲染器和其他組件):
>現在,我們需要產生它們。在級別的大師中,在我們的循環下產生了藥水:
public event SaveDelegate SaveEvent;
…就是這樣。每當您需要保存的新項目類型時:
- 添加Serializables類
- 創建訂閱以保存事件 的項目腳本
- 在級別主持人中添加實例化邏輯。 >
結論
>目前,系統很粗糙:硬盤上有多個保存文件,對象的旋轉未保存(劍,玩家等),並且在場景過渡期間定位播放器的邏輯(但沒有)加載)有點古怪。
一旦實心系統到位,這些現在都是要解決的小問題,我邀請您嘗試修改本教程和完成的項目,以查看您是否可以改善系統。>示例
項目有很大不同。
如所承諾的,這是完成的項目,如果您需要參考,或者是因為您被卡在某個地方。根據本教程的說明和相同的命名計劃,將實現保存系統。下載完成的項目:
Project GitHub頁面
項目zip下載
>在Unity中掌握保存和加載功能的常見問題(常見問題解答)5
>在Unity 5中實現保存系統的最佳方法是什麼? PlayerPrefs是一種在遊戲會話之間存儲和檢索數據的簡單方法。它使您可以以整數,浮點和字符串的形式保存和加載數據。但是,重要的是要注意,PlayerPrefs不安全,不應用於敏感數據。對於更複雜或安全的數據,您可能需要考慮使用二進制格式或JSON Serialializer。在Unity 5中,可以使用PlayerPrefs,JSON序列化或二進制格式來實現。 PlayerPrefs是最簡單的方法,允許您保存和加載整數,浮點和字符串。 JSON序列化更為複雜,但可以提高靈活性和安全性。二進制格式是最安全的方法,但也是最複雜的方法。
>執行順序如何影響Unity 5?
> >如何在Unity 5?
中保護保存數據5可以通過使用二進制格式或加密來實現。二進制格式將您的數據轉換為不容易讀取的二進制格式。加密通過以一種只能用特定鍵來解碼的方式來編碼您的數據來添加額外的安全性。>
>在Unity 5中使用PlayerPrefs用於保存和加載功能的局限性是什麼? 🎜>雖然PlayerPrefs是在Unity 5中實現和加載功能的一種簡單便捷的方法,但它具有多個限制。首先,它僅支持整數,浮子和字符串。其次,它不安全,很容易被操縱。最後,playerPrefs具有尺寸限制,這對於具有大量數據的遊戲可能是一個問題。 >我如何保存和加載Unity 5?保存和加載中的複雜數據結構使用JSON序列化或二進制格式可以實現Unity 5中的複雜數據結構。 JSON序列化使您可以將復雜的數據結構轉換為可以輕鬆保存和加載的字符串格式。二進制格式是一種更安全的方法,可將您的數據轉換為二進制格式。 >我可以在Unity 5中的不同平台上保存和加載數據嗎?跨平台兼容性。例如,playerpRefs是跨平台兼容的,但是二進制格式可能並非在所有平台上兼容。
>我如何在Unity 5?
中加載問題的問題對問題進行故障排除。可以通過檢查腳本的執行順序,確保您的數據正確序列化或格式化並進行測試,從而在Unity 5中保存和加載功能。您打算在平台上發布的遊戲。可以通過最大程度地減少保存和加載的數據量,使用有效的數據結構,並確保您的腳本被良好地實現。
如何實現Unity中的AutoSave功能5?
可以通過創建一個腳本來自動保存遊戲的腳本,以定期或在特定事件中自動保存您的遊戲,可以在Unity 5中實現AutoSave功能。該腳本應使用相同的方法來保存數據與您的手動保存系統。
>
以上是掌握Unity中的保存和加載功能5的詳細內容。更多資訊請關注PHP中文網其他相關文章!

中国女性科技力量在AI领域的崛起:荣耀与DeepSeek合作背后的女性故事女性在科技领域的贡献日益显著。中国科技部数据显示,女性科技工作者数量庞大,在AI算法开发中展现出独特的社会价值敏感性。本文将聚焦荣耀手机,探究其率先接入DeepSeek大模型背后的女性团队力量,展现她们如何推动科技进步,重塑科技发展价值坐标系。2024年2月8日,荣耀正式上线DeepSeek-R1满血版大模型,成为安卓阵营首家接入DeepSeek的厂商,引发用户热烈反响。这一成功背后,女性团队成员在产品决策、技术攻坚和用户

DeepSeek公司在知乎發布技術文章,詳細介紹了其DeepSeek-V3/R1推理系統,並首次公開關鍵財務數據,引發業界關注。文章顯示,該系統單日成本利潤率高達545%,創下全球AI大模型盈利新高。 DeepSeek的低成本策略使其在市場競爭中佔據優勢。其模型訓練成本僅為同類產品的1%-5%,V3模型訓練成本僅為557.6萬美元,遠低於競爭對手。同時,R1的API定價僅為OpenAIo3-mini的1/7至1/2。這些數據證明了DeepSeek技術路線的商業可行性,也為AI大模型的高效盈利樹立了

網站建設只是第一步:SEO與反向鏈接的重要性 建立網站只是將其轉化為寶貴營銷資產的第一步。您需要進行SEO優化,以提高網站在搜索引擎中的可見度,吸引潛在客戶。反向鏈接是提升網站排名的關鍵,它向谷歌和其他搜索引擎表明您的網站權威性和可信度。 並非所有反向鏈接都有利:識別並避免有害鏈接 並非所有反向鏈接都有益。有害鏈接會損害您的排名。優秀的免費反向鏈接檢查工具可以監控鏈接到您網站的來源,並提醒您注意有害鏈接。此外,您還可以分析競爭對手的鏈接策略,從中學習借鑒。 免費反向鏈接檢查工具:您的SEO情報員

美的即将发布搭载DeepSeek大模型的首款空调——美的鲜净感空气机T6,发布会定于3月1日下午1点30分举行。这款空调配备先进的空气智驾系统,可根据环境智能调节温度、湿度和风速等参数。更重要的是,它集成了DeepSeek大模型,支持超过40万条AI语音指令。美的此举引发业界热议,尤其关注白电产品与大模型结合的意义。不同于传统空调简单的温度设定,美的鲜净感空气机T6能够理解更复杂、更模糊的指令,并根据家庭环境智能调节湿度等,显著提升用户体验。

DeepSeek-R1賦能百度文庫與網盤:深度思考與行動的完美融合短短一個月內,DeepSeek-R1已迅速融入眾多平台。百度憑藉大膽的戰略佈局,將DeepSeek作為第三方模型夥伴,整合進自身生態系統,這標誌著其“大模型 搜索”生態戰略的重大進展。百度搜索和文心智能體平台率先接入DeepSeek及文心大模型的深度搜索功能,為用戶提供免費的AI搜索體驗。同時,“百度一下,你就知道”的經典slogan回歸,新版百度APP也整合了文心大模型和DeepSeek的能力,推出“AI搜索”、“全網信息提煉”

AI及時的代碼生成工程:開發人員指南代碼開發的景觀已準備好進行重大轉變。 掌握大型語言模型(LLM)和及時工程對於未來幾年對開發人員至關重要。 Th

此基於GO的網絡漏洞掃描儀有效地確定了潛在的安全弱點。 它利用了GO的並發功能的速度功能,包括服務檢測和漏洞匹配。讓我們探索它的能力和道德


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。