国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

嘗試用Unity還原蔚藍(lán)(Celeste)—— 真·操控、移動、手感篇

2020-08-21 15:42 作者:皮皮關(guān)做游戲  | 我要投稿

作者:QXYO


前言

大家好,還原蔚藍(lán)最重要的一篇終于來了,真是花費(fèi)了我不少心思。

可能有朋友疑惑,為什么我要在標(biāo)題中加一個“真”字。大家如果對蔚藍(lán)感興趣,并且嘗試過想要還原蔚藍(lán)的同學(xué)一定查閱過各種資料,但是現(xiàn)在網(wǎng)絡(luò)上的大部分“類”蔚藍(lán)項(xiàng)目都幾乎只是做了簡單的移動、跳躍、沖刺、爬墻等。完全沒有還原到蔚藍(lán)的龐大的細(xì)節(jié)。所以本次“真”移動篇就將把蔚藍(lán)中的各種細(xì)節(jié)展示給大家,并且盡我所能地將各種細(xì)節(jié)還原。

本文主要講解移動,動畫、特效等尚未添加,請見諒。

當(dāng)然由于本人技術(shù)有限,雖然有源代碼支持,但我并沒有完全參考,所以并不能完全完美還原原游戲手感,只能用簡陋的方法進(jìn)行嘗試,所以大佬們有什么意見和建議都請不要吝嗇的向我提出,謝謝。完整項(xiàng)目工程在本文最下方。

正片前的最后請讓我感謝對本項(xiàng)目影響最大的視頻,,所以本文會有多處引用到了該視頻中的信息,請留意:

【游戲制作工具箱】《蔚藍(lán)》的手感為何迷人?

感謝視頻作者M(jìn)ark Brown和譯者卡姐Cara。


一、準(zhǔn)備階段

本次項(xiàng)目需要一個完全不能穿墻,并且能夠精確操控的移動方式,所以用AddForce,或者velocity等方法是很難精確控制角色,并且有概率穿墻。全程用 transform相關(guān)的移動方式又需要做太多的判斷,比較難寫,而且容易出問題,所以決定使用Rigidbody.MovePosition(Vector2 position)來進(jìn)行移動,同時修改Rigidbody2D的Collision Detection為Continuous防止高速移動時角色穿墻,用Composite Collider2D將Tilemap合并,使碰撞盒更加平滑。順便一提,現(xiàn)在黑色主題已經(jīng)對所有用戶開放,大家還不趕緊去試試?

角色剛體設(shè)置
環(huán)境碰撞體、剛體設(shè)置

主要用狀態(tài)機(jī)的方式來控制角色在各種狀態(tài)間的切換,另外為了控制篇幅,本文大部分代碼都不是完整代碼,完整代碼詳見文末鏈接。


二、輸入控制

1、左右按鍵輸入優(yōu)化

我們知道通過input.getaxis可以模擬搖桿的輸入,輸入會從0到±1之間變化,就能模擬移動和停止慣性。但是我們卻不能準(zhǔn)確的操控慣性的大小,所以加速和減速需要重寫代碼控制。具體方法詳見3.1,這里輸入只需要返回0,±1即可。所以重點(diǎn)就是需要什么時候返回這三個值。

通常是按下右鍵返回1,按下左鍵返回-1,但如果左右鍵一起按應(yīng)該返回什么?在unity中一起按是返回0,而在蔚藍(lán)中,總是返回后輸入的按鍵。所以在這里需要手動判斷返回的值。


? void CheckHorzontalMove()

??? {

?????????????? //<= 0說明按下左鍵或者沒有案件,判斷這時是否按下了右鍵

????????????? if (Input.GetKeyDown(RightMoveKey) && Input.GetAxisRaw("Horizontal")<= 0)

????????????? {

???????????????????? MoveDir = 1;

????????????? }

????????????? //...同理左鍵判斷

????????????? else if (Input.GetKeyUp(RightMoveKey))? //判斷放開右鍵時檢測左鍵是否按下中

????????????? {

???????????????????? if (Input.GetKey(LeftMoveKey))? //放開右鍵的時候仍按著左鍵

???????????????????? {

??????????????????????????? MoveDir = -1;

??????????????????????????? MoveStartTime = Time.time;

???????????????????? }

???????????????????? else

???????????????????? {

??????????????????????????? MoveDir = 0;

???????????????????? }

????????????? }

????????????? //...同理左鍵判斷

?????? }

?

2、跳躍輸入優(yōu)化

如果在落地前幾幀之內(nèi)按下跳躍鍵,游戲應(yīng)該要記住指令使角色仍能在落地后跳躍,這會讓角色跳躍的更加順滑。為了精確到幀的控制,可以通過把一個int變量放在FixedUpdate里每幀減1來控制。在按下跳躍鍵時開啟一個幀數(shù)倒計(jì)時,如果落地后該int變量還不為0則仍然返回true,即按下跳躍按鍵。

? private void FixedUpdate()

??? {

??????? if(JumpFrame >= 0)

??? ????{

??????????? JumpFrame--;

??????? }

??? }

?? public bool JumpKeyDown {

??????? get

??????? {

??????????? if(Input.GetKeyDown(Jump))

??????????? {

????????????? return true;

??????????? }

??????????? else if(JumpFrame > 0)

??????????? {

????????????? return true;

?????????? ?}

??????????? return false;

??????? }

??? }

?


三、移動

主要移動代碼為如下,velocity的值就相當(dāng)于角色的速度。

rig.MovePosition(transform.position + Velocity * Time.fixedDeltaTime);

?

1、水平移動

從上文中提到的視頻中可知,角色是6幀達(dá)到滿速,然后只用3幀就可以停下,但是這里的1幀是多少秒呢?

我嘗試用1秒30幀,即0.2s到達(dá)滿速,0.1s停止測試了下手感,發(fā)現(xiàn)有明顯的慣性,所以猜測原視頻是以1秒60幀為基礎(chǔ)。為了盡可能還原,我將FixedUpdate的刷新頻率也設(shè)置成了1秒60次。

實(shí)現(xiàn)的方式也很簡單,MoveSpeed 為最大速度,在FixedUpdate中,加速時Velocity += MoveSpeed /6, 減速時Velocity.x-= MoveSpeed /3。要注意方向,方向相反正負(fù)號也要跟著變。

除此之外還有一些細(xì)節(jié),角色在空中加速和減速的時間都是比在陸地上的慢。蹲下時是不允許左右移動,陸地上移動時按下下鍵,也是會進(jìn)入蹲的狀態(tài)不允許移動。都是一些判斷,再次就不詳細(xì)贅述了。

2、落下狀態(tài)

由于沒有用到unity自帶的物理引擎,所以需要模擬重力。以自身碰撞盒為大小向下打射線,同時忽略玩家層。當(dāng)然為了以后的爬墻、手感優(yōu)化等,自身四個方向上都需要打射箭進(jìn)行檢測。

playerLayerMask = ~LayerMask.GetMask("Player"); //忽略玩家層

?DownBox = Physics2D.BoxCast(Position, boxSize, 0, Vector3.down,

?0.05f, playerLayerMask);

?

當(dāng)角色處于可落下的情況,并且射線檢測不到地面時開始添加重力,設(shè)置一個最大墜落速度

Velocity.y -= 150f * Time.deltaTime;

Velocity.y = Mathf.Clamp(Velocity.y, -25, Velocity.y);

?

3、爬墻狀態(tài)

爬墻有兩種情況,一種是有耐力,并且按下爬墻鍵會緊貼在墻上,如果按下墻壁方向的方向鍵,同時不按爬墻鍵或者沒耐力了就會沿著墻壁下滑。

實(shí)現(xiàn)也很簡單,將我上面描述的轉(zhuǎn)換成if語句就行,由于在墻上不會移動x軸,所以移動是修改velocity.y來實(shí)現(xiàn)。詳情可參考完整工程,這里就提一下爬墻的兩個細(xì)節(jié)。

1、如果在墻的邊緣垂直起跳,從進(jìn)入爬墻狀態(tài)起會滑落一段距離。

2、如果在墻的邊緣按上鍵,會自動將玩家移動到平臺上。

1的方法是獲取自身位置與碰撞點(diǎn)y軸的差距,如果大于一定值就滑落,這里我忽略了耐力。

2的方法同樣是獲取獲取自身位置與碰撞點(diǎn)y軸的差距,如果小于一定值并且按了上鍵就自動跳到平臺上,自動跳躍我用協(xié)程的方式實(shí)現(xiàn)。

?????? void Climb()

{

??????????? if (UpBox.Length == 0)

??????????? {

??????????????? if (input.v > 0 && transform.position.y - HorizontalBox[0].point.y > 0.9f)

??????????????? {

? ??????????????????StartCoroutine("ClambAutoJump");

??????????????????? return;

??????????????? }

??????????? }

??????????? //如果爬在墻的最上端要么自動跳到平臺上,要么滑落一段距離

??????????? if (input.v <= 0 && transform.position.y - HorizontalBox[0].point.y > 0.7f

????????????? ????|| !input.ClimbKey)

??????????? {

??????????????? Velocity.y = -ClimbSpeed;????????????? //向下滑落

??????????? }

??????????? else if (transform.position.y - HorizontalBox[0].point.y <= 0.7f || input.ClimbKey)

??????????? {

??????????????? Velocity.y = input.v * ClimbSpeed;???? //根據(jù)輸入判斷是否移動

??????????? }

}

?

??? // 攀爬到墻壁最上沿時如果有可跳躍平臺,則自動跳躍到平臺上

??? IEnumerator ClambAutoJump()

??? {

??????? var posY = Mathf.Ceil(transform.position.y);

??????? isCanControl = false;

??????? Velocity = Vector3.zero;

??????? while (posY + 1f - transform.position.y > 0)

??????? {

??????????? Velocity.y = JumpSpeed;

??????????? Velocity.x = GetDirInt * 15;

??????????? yield return null;

??????? }

??????? Velocity = Vector3.zero;

??????? playState = PlayState.Fall;

??????? isCanControl = true;

??? }

?


4、沖刺狀態(tài)

因?yàn)樘S是本游戲最重要的部分,所以先來介紹一下沖刺。

在蔚藍(lán)中,沖刺的前0.15s是不允許移動的,所以沖刺也是通過協(xié)程來實(shí)現(xiàn)。

在沖刺前我們要獲取到?jīng)_刺方向,這里有幾個小細(xì)節(jié),什么都不按的情況下按沖刺是以角色當(dāng)前方向進(jìn)行沖刺,在地面上按左下或者右下沖刺時是普通的橫向沖刺,

//獲取輸入時的按鍵方向

?????? float verticalDir;

?????? if(isGround && input.v < 0)? //在地面上并且按住下時不應(yīng)該有垂直方向

?????? {

????????????? verticalDir = 0;

?????? }

?????? else

?????? {

????????????? verticalDir = input.v;

?????? }

??????? //沖刺方向注意歸一化

??????? DashDir = new Vector2(input.MoveDir, verticalDir).normalized;

??????? if(DashDir == Vector2.zero)?? //此處為0說明只按下了沖刺鍵。

??????? {

??????????????? //沒有按方向鍵就朝玩家正前方?jīng)_刺?????

????????????? DashDir = Vector3.right * GetDirInt;

??????? }

?

用Time.time來控制時間是很不準(zhǔn)確的,會出現(xiàn)沖刺距離時遠(yuǎn)時近。所以在協(xié)程里想要精確到幀的控制可以使用WaitForFixedUpdate。0.15s在1秒60幀的情況下就是9幀。

??????? isCanControl = false;? //不允許操控

??????? while (i < 9)?

??????? {

?????? ??????? if(playState == PlayState.Dash)

????????????? {

???????????????????? Velocity = DashDir * 30f;

????????????? }

????????????? i++;

????????????? CheckHorizontalMove();?? //橫向移動優(yōu)化,見下文

????????????? yield return new WaitForFixedUpdate();

??????? }

??????? isCanControl = true;

?

雖然在沖刺的0.15s中不允許操控,但有些情況下是可以跳躍的,所以會切換到跳躍狀態(tài),這時不能停止沖刺的協(xié)程,因?yàn)檫€要等循環(huán)結(jié)束把操作權(quán)還給玩家,所以在代碼中加了一個判斷,當(dāng)前在沖刺狀態(tài)時才給角色沖刺速度。

移動優(yōu)化:

沖刺的時候?yàn)榱耸挂苿涌雌饋砀禹樆?,會在碰到各種碰撞的邊緣處進(jìn)行處理,看一下動圖就明白了。

當(dāng)角色在移動中碰到碰撞體的邊緣時應(yīng)該要像果凍一樣劃過去。當(dāng)然不只是在沖刺中會用到,跳躍時也會用到。實(shí)現(xiàn)原理:當(dāng)前玩家位置與碰撞點(diǎn)位置之差來判斷是否應(yīng)該對位移進(jìn)行修正。圖中黃線的一端就是上次碰撞點(diǎn)的位置。由于地圖使用tilemap進(jìn)行繪制,所以瓦片的位置都是能夠確定,在此基礎(chǔ)上進(jìn)行修正。

//檢測正上方的唯一修正

bool CheckUpMove()

?????? {

????????????? if (UpBox.Length == 1)

????????????? {

??????????????????????? //獲取自身與碰撞點(diǎn)的x軸距離

???????????????????? var pointDis = UpBox[0].point.x - transform.position.x;

???????????????????? if (pointDis > 0.34f)? //如果在平臺左側(cè)邊緣

???????????????????? {

??????????????????????????? var offsetPos = Mathf.Floor(transform.position.x); //唯一修正

??????????????????????????? transform.position = new Vector3(offsetPos + 0.48f, transform.position.y, 0);

??????????????????????????? return true;

???????????????????? }

???????????????????? else if (pointDis < -0.34f)

???????????????????? {

??????????????????????????? var offsetPos = Mathf.Floor(transform.position.x);

??????????????????????????? transform.position = new Vector3(offsetPos + 0.52f, transform.position.y, 0);

??????????????????????????? return true;

???????????????????? }

???????????????????? else? //其他情況就是碰撞到墻壁,切換為落下狀態(tài)

???????????????????? {

??????????????????????????? Velocity.y = 0;

??????????????????????????? playState = PlayState.Fall;

??????????????????????????? return false;

???????????????????? }

????????????? }

????????????? return true;

?????? }

? //檢測水平方向位移

void CheckHorizontalMove()

?????? {

????????????? HorizontalBox = playDir == PlayDir.Right ? RightBox : LeftBox;

????????????? if (HorizontalBox.Length == 1)

????????????? {

???????????????????? var pointDis = HorizontalBox[0].point.y - Position.y;

???????????????????? Debug.LogError(pointDis);

???????????????????? if (pointDis > 0.34f)

???????????????????? {

??????????????????????????? var offsetPos = Mathf.Ceil(Position.y);

??????????????????????????? transform.position = new Vector3(transform.position.x, offsetPos - 0.22f, 0);

???????????????????? }

???????????????????? else if (pointDis < -0.42f)

???????????????????? {

??????????????????????????? var offsetPos = Mathf.Ceil(transform.position.y);

??????????????????????????? transform.position = new Vector3(transform.position.x, offsetPos + 0.035f, 0);

???????????????????? }

????????????? }

?????? }

?


5、跳躍

跳躍是蔚藍(lán)的靈魂,也是全篇最復(fù)雜的部分之一,這里我略微的參考了游戲源代碼。

蔚藍(lán)中跳躍是會有一個最小跳躍高度和最大跳躍高度,并且跳躍分成了三個階段:

1、加速上升階段

2、到達(dá)最小跳躍高度后如果仍然按主跳躍鍵則繼續(xù)升高階段

3、到達(dá)最高點(diǎn)或者放開跳躍鍵后的減速上升階段,上升速度為0時切換到落下狀態(tài)。

跳躍也是用協(xié)程進(jìn)行實(shí)現(xiàn),首先來看第一個階段。vel.x為傳入的橫向加速度,maxVel.x為最大橫向加速度,在下文蹬墻跳中實(shí)現(xiàn)橫向加速跳躍。


while (playState == PlayState.Jump && dis <= curJumpMin && Velocity.y < curJumpSpeed)

??????? {

??????????????? //獲取當(dāng)前角色相對于初始跳躍時的高度

????????????? dis = transform.position.y - startJumpPos;?

??????????????? //vel.x為橫向加速度,是為了在蹬墻跳的時候提供一個橫向的加速移動效果

????????????? if (vel.x != 0 && Mathf.Abs(Velocity.x) < maxVel.x)

????????????? {

???????????????????? isMove = false;?? //在蹬墻跳躍中是不允許操控橫向位移的。

???????????????????? Velocity.x += vel.x;

???????????????????? if(Mathf.Abs(Velocity.x) > maxVel.x)

????????????? ??????? {

??????????????????????????? Velocity.x = maxVel.x * GetDirInt;

???????????????????? }

????????????? }

????????????? if (!CheckUpMove())? //正上方移動優(yōu)化檢測,返回false說明撞到墻,結(jié)束跳躍

??????????? {

??????????????? Velocity.y = 0;

??????????????? isIntroJump = false;

????????????? isMove = true;

????????????? yield break;

??????????? }

????????????? if (vel.y <= 0)

????????????? {

???????????????????? Velocity.y += 240 * Time.fixedDeltaTime;? //加速移動

????????????? }

????????????? yield return new WaitForFixedUpdate();

??????? }

?

在這段代碼中加入了蹬墻跳躍的方法,這里就一并說完。

再上圖中我們可以看到4種在墻上的跳躍方式,

1、按住爬墻鍵并且有耐力的情況下只按跳躍鍵會垂直向上跳。

2、在上一條的情況下按反方向鍵和跳躍是蹬墻跳。

3、處于在墻壁上滑落狀態(tài)時按下跳躍鍵也是相同效果。滑落狀態(tài)也分兩種,一是按住爬墻鍵但是沒有耐力,二是不按爬墻鍵時,而是按下墻所在方向的方向按鍵。

4、在空中靠近墻壁時,只按下跳躍鍵,會有一個比蹬墻跳稍近一些的蹬墻跳。順便一提,這種方式跳躍不會消耗體力,所以蔚藍(lán)中有個高級技巧,無(消耗)體力上墻就是通過這種方式實(shí)現(xiàn)。

//蹬墻跳,這里暫時忽略了耐力

//在爬爬墻狀態(tài)下,按下跳躍鍵

?????? if(input.JumpKeyDown)

?????? {

????????????? if(input.ClimbKey)

????????????? {

??????????????????????? //第二種情況

???????????????????? if((input.h > 0 && GetDirInt < 0) || (input.h < 0 && GetDirInt > 0))

???????????????????? {

??????????????????????????? Jump(new Vector2(8 * -GetDirInt, 0), new Vector2(24 , 0));

???????????????????? }

???????????????????? else

???????????????????? {

??????????????????????????? Jump();? //第一種情況

???????????????????? }

????????????? }

????????????? else

????????????? {

??????????????????????? //第三種情況

???????????????????? Jump(new Vector2(8 * -GetDirInt, 0), new Vector2(24 , 0));

????????????? }

?????? }

?

第四種情況只會在落下或者跳躍時觸發(fā),將修改下數(shù)值調(diào)用即可

Jump(newVector2(4 * -GetDirInt,0),newVector2(18,0));

?

第二階段,如果仍然按下跳躍鍵,并且跳躍高度小于最大跳躍高度時。


?????? while (playState == PlayState.Jump && input.JumpKey && dis < curJumpMax)

??????? {

?

????????????? if (!CheckUpMove())? //正上方移動優(yōu)化檢測,返回false說明撞到墻,結(jié)束跳躍

??????????? {

??????????????? Velocity.y = 0;

??????????????? isIntroJump = false;

???????????????????? yield break;

??????????? }

??????????????? //上文所說的第四種蹬墻跳檢測

????????????? if (input.JumpKeyDown && BoxCheckCanClimb() && !input.ClimbKey && !CheckIsClimb())

????????????? {

???????????????????? Velocity.y = 0;

???????????????????? isIntroJump = false;

???????????????????? Jump(new Vector2(4 * -GetDirInt, 0), new Vector2(18 , 0));

???????????????????? yield break;

????????????? }

?

?????? ??????? dis = transform.position.y - startJumpPos;

??????????????? Velocity.y = curJumpSpeed;

??????????????? yield return new WaitForFixedUpdate();

??????? }

?

在這個階段中添加了對蹬墻跳的檢測,此時y軸方向的速度仍然是跳躍速度。

第三階段,減速直到向上的速度為0。


?????? // slow down

????????????? while (playState == PlayState.Jump && Velocity.y > 0 )

???? ???????{

????????????? if (!CheckUpMove())

??????????? {

??????????????? break;

??????????? }

????????????? if (input.JumpKeyDown && BoxCheckCanClimb() && !input.ClimbKey && !CheckIsClimb())

????????????? {

???????????????????? Velocity.y = 0;

???????????????????? isIntroJump = false;

???????????????????? Jump(new Vector2(4 * -GetDirInt, 0), new Vector2(24, 0));

???????????????????? yield break;

????????????? }

??????????? //如果跳躍到最大高度是重力是其他情況的一半

?????? ??? if (dis > JumpMax)

??????????? {

??????????????? Velocity.y -= 100 * Time.fixedDeltaTime;

??????????? }

??????????? else

??????????? {

??????????????? Velocity.y -= 200 * Time.fixedDeltaTime;

??????????? }

??????????? yield return new WaitForFixedUpdate();

??????????? }

?

減速階段也有一個小細(xì)節(jié),跳躍到最高處時重力會減半,這會使玩家更加方便的操控角色。但是由于這段時間比較短,gif并不能展示出比較好的效果,這里就不做展示。


沖刺跳躍

只有以上部分是不足以完全還原蔚藍(lán)的跳躍,因?yàn)樵谟螒蛑型婕业奶S是會疊加的,也就是說如果在沖刺的時候按下跳躍鍵,跳躍時是會疊加沖刺時的速度。橫向上比較簡單,垂直方向上我們也只需要把最小跳躍高度和最大跳躍高度計(jì)算一下即可。

?????? float curJumpMin = JumpMin * (vel.y + JumpSpeed)/ JumpSpeed;

?????? float curJumpMax = JumpMax * (vel.y + JumpSpeed) / JumpSpeed;

?????? float curJumpSpeed = JumpSpeed + vel.y;

?

最后就是各種沖刺和跳躍的疊加操作了,充能大跳、低空充能大跳、蹭墻跳(7B技巧)、“凌波微步”等操作技巧最多就是修改下傳入?yún)?shù)即可。


在蹭墻跳躍中還有一個細(xì)節(jié),因?yàn)樵揪褪且粋€比較難的操作,所以制作人為了優(yōu)化將此時的墻壁檢測放大了一下,即平常離墻壁比較遠(yuǎn)不能蹬墻跳的位置,蹭墻跳可以觸發(fā)。

土狼跳(Coyotetime)

最后就用一個在平臺跳躍游戲里比較常見的細(xì)節(jié)來結(jié)束吧,在人物離開平臺的后幾幀時間里,玩家仍然能跳躍,當(dāng)然實(shí)現(xiàn)方式也非常簡單,在從普通移動狀態(tài)切換到落下狀態(tài)時記錄一個int變量,同樣的在FixedUpdate每次減1來控制在幾幀內(nèi)仍可以跳躍。只需要注意此時要把垂直方向上的速度清零。

代碼就不展示了,直接上效果, 為了展示的更加清楚我將這個時間設(shè)置的比較長,蔚藍(lán)中設(shè)置的是3幀。

展示效果,實(shí)際只有3幀

三、結(jié)語

當(dāng)然游戲細(xì)節(jié)尚不止如此,還有許多諸如沖刺時碰撞體縮小,在空中按住下加速下落,關(guān)于刺的細(xì)節(jié)等等。引用上一篇評論,那5000行代碼標(biāo)志著目前橫版跳躍類游戲的天花板。我也只能盡力模仿,努力學(xué)習(xí)。

內(nèi)容不多,但是為了實(shí)現(xiàn)反反復(fù)復(fù)的修改了很多遍,而且由于蔚藍(lán)源碼所使用的像素比例和本項(xiàng)目中用的不一致,所以各種參數(shù)也不能完全參考,修改參數(shù)也是修改的我心力交瘁。最后雖然是完成了一部分的移動和手感,但離我理想仍有不少的差距。接下來的一篇應(yīng)該就是,動畫、特效、鏡頭添加,死亡狀態(tài)添加,現(xiàn)有的移動繼續(xù)完善等,不過這部分就比較簡單,應(yīng)該會比較快吧。


項(xiàng)目鏈接:https://pan.baidu.com/share/init?surl=76fnkQOSnp--SAPbTf2uFA

提取碼:23i8


對游戲開發(fā)學(xué)習(xí)感興趣的盆友,歡迎訪問:levelpp.com/

同時,也歡迎加入游戲開發(fā)群攪基:1082025059

嘗試用Unity還原蔚藍(lán)(Celeste)—— 真·操控、移動、手感篇的評論 (共 條)

分享到微博請遵守國家法律
来凤县| 奉新县| 英德市| 和田市| 开封县| 夏邑县| 项城市| 修水县| 东乌珠穆沁旗| 云南省| 柳林县| 昌黎县| 湘西| 蒙山县| 杨浦区| 多伦县| 汉阴县| 安乡县| 永和县| 犍为县| 肥西县| 玉门市| 杭州市| 惠水县| 金山区| 亳州市| 米泉市| 岱山县| 长武县| 阿巴嘎旗| 剑阁县| 隆尧县| 云梦县| 古丈县| 托克逊县| 蚌埠市| 瓮安县| 儋州市| 临夏县| 综艺| 卢湾区|