遊戲開發中的資料池問題和改進

2021-06-23 09:06:44 字數 3588 閱讀 4592

之前開發遊戲的時候,為了能夠在任意地方都能訪問到資料,一般的做法是建立乙個資料池,然後把想要的資料全部放到資料池類中。資料池的寫法一般是建乙個名為datapool的單例類,通常情況下對單例的實現一般是這樣的

datapool.h

#pragma once

class datapool;

datapool.cpp

#include #include "datapool.h"

datapool* g_instance = null;

datapool* datapool::getinstance()

return g_instance;

}

為了方便演示資料池的工作方式,以下用遊戲中常會涉及到使用者賬戶資訊和登入資訊進行舉例。通常情況下會建立兩個類,這邊暫時定為accountinfo和logininfo。簡單實現一下,類似下面:

使用者資訊類accountinfo

accountinfo.h

#pragma once

class accountinfo

;

accountinfo.cpp

#include "accountinfo.h"

accountinfo::accountinfo(void)

accountinfo::~accountinfo(void)

登入資訊類logininfo

logininfo.h

#pragma once

class logininfo

;

logininfo.cpp

#include "logininfo.h"

logininfo::logininfo(void)

logininfo::~logininfo(void)

既然這兩個類建好了,那麼下一步就是把它們丟到datapool中,所以datapool的**也相應的更改

#pragma once

#include "accountinfo.h"

#include "logininfo.h"

class datapool;

這邊說的丟到datapool中,其實就是把這兩個類的例項作為datapool的成員變數,並且把訪問方式定位public,以後要訪問的時候一般是

datapool* pool = datapool::getinstance();

accountinfo& account = pool->m_accountinfo;

logininfo& login = pool->m_logininfo;

也就是說所有的資料都要通過datapool的單例訪問,這樣accountinfo和logininfo作為datapool的成員變數,也就擁有了單例的性質。同時也不用去管accountinfo和logininfo的記憶體釋放,因為他們的是以棧上物件的方式來宣告的,其生命週期是隨著datapool的單例來管控的。datapool什麼時候釋放,它們也跟著什麼時候釋放。

當然這樣做法問題也是非常多的,比方說如果乙個不小心把引用符號&去掉了,那麼資料就會被拷貝乙份。想象一下下面的寫法:

logininfo login = pool->m_logininfo;//這邊logininfo不是宣告為logininfo&方式的,所以logininfo的資料就被拷貝
還有乙個更讓人頭疼的問題是,由於把所有的資料都丟到datapool中,那麼相應的也得把這些資料類的標頭檔案也包含到datapool的標頭檔案中,像上面的

#pragma once

//看到了沒,需要這兩個標頭檔案

#include "accountinfo.h"

#include "logininfo.h"

class datapool;

包含標頭檔案本身沒什麼問題。問題是datapool在開發過程中會被很多人修改,一般會有3到5個人在改它。而遊戲中基本上每個業務邏輯類都要用到它,這樣就造成了乙個問題,datapool隨便一修改,相應的會有上百個檔案也一起被編譯。在沒用聯合編譯工具的情況下,最可觀的等待編譯的時間是半個小時吧。

這些都是以前用在遊戲開發的實現方案,一般是誰用誰苦逼。為此,需要對其進行改進。改進的技巧是用到了類成員模板函式以及typeid這個執行時運算子。

typeid這個運算子能夠根據型別來返回型別的名稱,舉個例子

const char* name = typeid(accountinfo).name();

printf(name);//輸出結果將是class accountinfo

name = typeid(logininfo).name();

printf(name);//輸出結果將是class logininfo

接著看看datapool改進後的樣子 

#pragma once

#include #include #include #include using namespace std;

class datapool

else

return null;

}protected:

std::mapm_mapinstance;

};

它的用法是

datapool* pool = datapool::getinstance();	

logininfo* info = pool->get();

logininfo* info2 = pool->get();

accountinfo* account = pool->get();

在上面例子中info和info2這兩個指標所指的物件是一樣的,因為datapool中對相同型別的資料進行了快取。這樣就可以在不改動datapool的情況下來全域性訪問自己想要的資料,只要你通過get這個類成員模板函式。

現在看看get()模板函式的實現,這個函式的用途就是根據模板引數t以及typeid來取得該模板引數的型別名稱

const char* name = typeid(t).name();//正如前面對typeid講解的那樣,這邊將根據t的型別來返回t所對應的型別名稱
然後再在map中尋找之前這個模板引數的是否有快取過,有的話直接用之前的例項。也就是這段**

std::map::iterator target = m_mapinstance.find(name);

if(target != m_mapinstance.end())

如果沒有的,那麼就建立乙個例項,然後把它加入到map中

else
通過以上改進之後,datapool就不在依賴於特定資料的標頭檔案了,同時也讓datapool固定下來,不會有大改動。自此,改進完成,有需要的各位可以試試。

小資料池和編碼問題

1.小資料池 為了快 避免重複建立 1.塊 每次執行的乙個單元 函式 類 command互動命令 eval 2.is 和 記憶體位址 id 變數名 記憶體的開闢是由直譯器決定的 is比較的是記憶體位址 判斷值是否相等 我們一直在用 在python裡面,缺省會把數字 字串 bool 進行快取,這樣不需...

python中的 小資料池 is 和

一種資料快取機制,也被稱為駐留機制 小資料池針對的是 整數 字元 布林值 其他的資料型別不存在駐留機制 在python中對 5 到256之間的整數會被駐留在記憶體中,將一定規則的字串快取.在使用的時候,記憶體中只會建立乙個該資料的物件.儲存在小資料池中.當使用的時候直接從小資料池中獲取物件的記憶體引...

遊戲開發中 Sprite 和 Image 的區別

在開發中,有的時候會遇到一些奇奇怪怪的問題,比如說在3d遊戲開發中需要製作乙個 主角血條或者 敵人血條的時候,一般來說有兩種方式,乙個是 使用 canvas 製作一張 image 進行渲染,乙個是使用 spriterenderer 進行渲染,如果使用 image進行渲染的話每乙個敵人都得引用乙個 i...