Lua遊戲開發教程之時區問題詳解

2022-09-20 12:21:14 字數 3655 閱讀 7043

前言

什麼是lua?

lua 是乙個小巧的指令碼語言,巴西里約熱內盧天主教大學裡的乙個研究小組於2023年開發,其設計目的是為了嵌入應用程式中,從而為應用程式提供靈活的擴充套件和定製功能。lua由標準c編寫而成,幾乎在所有作業系統和平台上都可以編譯,執行。乙個完整的lua直譯器不過200k,在目前所有指令碼引擎中,lua的速度是最快的。這一切都決定了lua是作為嵌入式指令碼的最佳選擇。相比python和per的核心,lua的核心小於120kb,而python的核心大約860kb,perl的核心大約1.1mb。lua語言支援物件導向程式設計和函式式程式設計,它提供了乙個通用型別的表table,可以實現陣列、雜湊表、集合、物件的功能。lua支援協同程序機制。作為一門可擴充套件的語言,lua提供簡單而穩定的互動介面,如lua和c程式可通過乙個堆疊交換資料,這使得lua語言可以快速地xiscdfcxhe和其它語言實現整合。

總體來說,lua語言具備以下優點:

(1)語言優美、輕巧

(2)效能優良、速度快

(3)可擴充套件性強。

正因為lua語言具備了這樣的特點,使得它能和遊戲開發領域的需求完美地結合起來,因為我們需要這樣的一門語言,它能夠和c/c++進行完美地互動,因為我們需要它對底層進行封裝。它需要足夠地簡單,因為我們需要簡單、靈活、快速地編寫**。那麼顯然lua就是我們一直在尋找地這種語言。

目前大部分遊戲都採用了lua語言進行功能開發,在進行多語種發行的時候就會遇到時區顯示的問題。以南韓版本為例,場景如下:

1、伺服器處於固定的位置,比如放在首爾機房;

2、玩家所處的位置不確定,可能在南韓,或者是出差在其它國家或地區;

需求:無論在哪個國家或地區,統一顯示伺服器的當前時間。在pc上檢視,即便在國內測試的時候也顯示南韓首爾的時間(比北京時間快1個小時)。

實現:-- 北京時間

local servertime = 1536722753 -- 2018/09/12 11:25

function gettimezone()

local now = os.time()

return os.difftime(now, os.time(os.date("!*t", now)))

end-- 8 hour * 3600 seconds = 28800 seconds

local timezone = gettimezone()/ 3600

print("timezone : " .xiscdfcxhe. timezone)

local timeinterval = os.time(os.date("!*t", servertime)) + timezone * 3600 + (os.date("*t", time).isdst and -1 or 0) * 3600

local timetable = os.date("*t", timeinterval)

--[[

for k, v in pairs(timetable) do

print(k .. ":" .. tostring(v))

end]]

print(timetable.year .. "/" .. timetable.month .. "/" .. timetable.day .. " " .. timetable.hour .. ":" .. timetable.min .. ":" .. timetable.sec)

關注是這個方法: os.date("!*t", now),其中以!為關鍵。

lua 原始碼, loslib.c line 283 行

static int os_date (lua_state *l)

else

stm = l_localtime(&t, &tmr);

if (stm == null) /* invalid date? */

lual_error(l, "time result cannot be represented in this installation");

if (strcmp(s, "*t") == 0)

else

} lual_pushresult(&b);

} return 1;

}從原始碼可以看到 ! 呼叫了

#define l_gmtime(t,r) gmtime_r(t,r)

gmtime_r 函式是標準的posix函式,它是執行緒安全的,將日曆時間轉換為用utc時間表示的時間。

注:utc —— 協調世界時,又稱世界統一時間、世界標準時間

也就是說 「!*t」 得到的是乙個 utc 時間,為0度的經線(子午線),亦稱本初子午線,通常將它與gmt視作等同(但是utc更為科學和精確)。

首爾位於東9區,所以實際的時間應該是 utc + 9,9就是時區差 —— 9個小時。北京位於東8區,即 utc + xiscdfcxhe8。

如何保證遊戲內全部統一為伺服器的時間呢?

伺服器需要返回給客戶端當前的時區的差值,比如南韓就返回 9,國內就返回 8,越南返回 7,北美返回 –16,記為 servertimezone。

服務端返回當前伺服器時間servertime(即首爾當前時間),我們只需要將伺服器時間轉為 utc 的時間,然後再加上 servertimezone即可。

os.time(os.date("!*t", serve程式設計客棧rtime)) + servertimezone * 3600

這樣無論在哪個地區或國家,都將顯示首爾的時候,與伺服器顯示的時間就同步上了。

為什麼要一直顯示伺服器的時間呢?

遊戲中有很多功能是有時間限制的,比如運營活動,或者功能開啟。如果用本地時間就不好控制,統一用伺服器時間避免了很多問題。

可是也容易遇到乙個坑,運營配置的活動時間都是針對當前伺服器的時間,例如某個活動的截止時間是:2018-10-08 00:00:00,遊戲需要顯示活動截止倒計時。

通常的做法: ployendtime – servertime,得到乙個秒數,然後將秒轉成:xx天xx小時xx分xx秒

servertime 是固定的,可是ployendtime就容易出錯,為什麼?

servertime 是在東9區 —— 首爾的時間,而 os.time() 是根據本地時間來算時間的,這中間就存在問題。有乙個時差的問題,之前計算一直用的是servertimezone —— 乙個固定值,而我當前處於地區或國家,它相對於utc的時區不確定的,怎麼辦?

用 (currtimezone – servertimezone) * 3600 / 秒,os.time()之後再加上這個時區差就是首爾當前的時間戳了。國內東8 - 東9  = -1,也就是要減去乙個1時區,最終將得到首爾地區的時間戳,再減去 servertime 就是剩下的秒數了,然後將它轉為 xx 天 xx 小時 xx 分 xx 秒。

最後小結一下:

1)os.time(),這個時間算出來的是針對當前所處時區的那個時間戳。

2)os.date(「!*t」, 時間戳) 得到的是utc(時區為0)的時間戳。

3)獲取當前時區的值,可以通過文章開頭的 gettimezone 方法

4)想顯示固定時區的時間(例如無論在哪都顯示伺服器的時間),只需要將(伺服器)時間戳(秒),通過第2步的方法,得到 utc 再加上固定的時區差

5)計算倒計時的時候,需要考慮到 os.time 是取當前時區,需要再將當前時區減去目標時區,再計畫時間戳

6)夏令時,本身已經撥快了乙個小時,當需要顯示為固定時區的時間,則需要減去乙個小時

總結本文標題: lua遊戲開發教程之時區問題詳解

本文位址:

C 開發Unity遊戲教程之遊戲物件的屬性變數

通過對上一章的學習,讀者應該了解到了,遊戲物件上的屬性與指令碼中的變數,建立聯絡的方式就是將指令碼賦予遊戲物件。上一章只是簡單的介紹了指令碼中的變數,讀者一定不過癮,現在好了,作者將使用一整章的篇幅介紹變數與屬性。在unity中,遊戲場景中遊戲物件的屬性,可以在inspector檢視裡檢視,想看哪個...

C 開發Unity遊戲教程之Unity中方法的引數

出現在指令碼中的方法,無論是在定義的時候,還是使用的時候,後面都跟著一對括號 有意義嗎?看起來最多也就是起個快速識別方法的作用吧。既然c 的語法規定方法就應該這麼寫,肯定是有一定道理的。如果是上公升到戰略意義的道理,連作者也不是很明白,但是作者知道這對括號裡可以新增 引數 要說明引數的作用,就必須從...

C 開發Unity遊戲教程之使用指令碼變數

本章前面說了那麼多關於變數的知識,那麼在指令碼中要如何編寫關於變數的 有規章可循嗎?答案是有的。本節會依次講解變數的宣告 初始化 賦值和運算。要想在指令碼中使用變數,就必須先宣告 declare 這就意味著,需要先告訴unity,有這樣乙個變數存在,然後才可以在unity中使用這個變數。那麼,該如何...