最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

時間回溯——用Unity實現(xiàn)時空幻境(Braid)中的控制時間效果

2020-04-01 17:43 作者:皮皮關做游戲  | 我要投稿

作者:QXYO


前言

控制時間相信幾乎是每個人都想擁有的能力,也為眾多影視、游戲等提供了靈感,荒木老師在jojo的奇妙冒險中幾乎把控制時間的能力玩了個遍。而在游戲領域,令筆者印象最深的就是本次的主角——時空幻境(Braid),一款把橫板跳躍與時間回溯完美結合的游戲。


注意!由于本教程主要實現(xiàn)時間回溯效果,橫板過關類游戲的場景搭建、移動、動畫等不在本次內容范圍內,有興趣的同學可以先從B站專欄開始學起:
【簡明UNITY教程】教你迅速實現(xiàn)2D角色的移動和跳躍

本次教程也會以該系列視頻的工程為基礎,在原項目上進行修改實現(xiàn)時間回溯的功能。

項目來源:【簡明Unity教程】2D跳躍游戲的踩怪功能

基礎工程:https://pan.baidu.com/share/init?surl=HISQizt0NvCHo8U0KgSCCA
提取碼:jlbx


一、時間回溯實現(xiàn)原理

我們知道視頻是能夠倒放的,那游戲可不可以也像視頻那樣把每一幀記錄下來,需要時再倒著輸出實現(xiàn)時間倒流呢?答案當然是可以的,這種方法稱為“備忘錄模式”。事實上時空幻境的作者也說過該游戲主要是用該方法制作,有興趣、英語好的同學可以看看作者的解釋:https://news.ycombinator.com/item?id=9484197


二、用Unity實現(xiàn)時間回溯

下載好前言中提到的基礎工程,打開之后可能會有幾個不影響的警告,Clear即可。打開Scene文件夾下的SampleScene場景,運行一下,試試操作人物移動、跳躍,應該不會有什么問題。

主要實現(xiàn)操控角色的時間倒流效果,所以先把怪物(opossum-1)從場景中刪除。

1.設置保存數(shù)據類型

首先要確定每幀保存什么數(shù)據,位置數(shù)據、起跳后的速度數(shù)據,由于是2d動畫所以還需要記錄每幀所用的Sprite和臉的朝向。在Scripts文件夾里新建一個c#腳本,取名為ObjectStage。

public class ObjectStage

{

??? public Vector3 Position { get; set; }

??? public Vector3 Velocity { get; set; }

??? public Sprite Sprite { get; set; }

??? public bool IsRight { get; set; }

}

?

2.保存角色狀態(tài)

接下來就要實現(xiàn)時間倒流的效果了,新建腳本TimeBack掛到Player上。由于讀取數(shù)據是從后往前讀取,所以可以使用stack(棧)一個后進先出的容器來保存數(shù)據。同時也需要獲取到player上的<SpriteRenderer>,用于獲取和修改某一幀角色的動作;<Animator>用于在時間倒流時暫停動畫的播放;<CharacterController2D>,原工程的角色控制代碼,用于修改角色臉的朝向;<Rigidbody2D>,獲取、修改速度和時間倒流時關閉物理引擎。

??? void Start()

??? {

??????? TimeBackData = new Stack();

?????? ?SpriteRenderer = GetComponent<SpriteRenderer>();

??????? animator = GetComponent<Animator>();

??????? cc2D = GetComponent<CharacterController2D>();

??????? m_Rigidbody2D = GetComponent<Rigidbody2D>();

??? }

?

首先是保存數(shù)據,cc2D.m_FacingRight在原工程里受保護的(private)這里我們需要公開(public)。



??? void SaveData()

??? {

??????? ObjectStage stage = new ObjectStage();

??????? stage.Position = transform.position;

??????? stage.Sprite = SpriteRenderer.sprite;

??????? stage.IsRight = cc2D.m_FacingRight;

??????? stage.Velocity = m_Rigidbody2D.velocity;

??????? TimeBackData.Push(stage);

??? }

?

3.讀取和顯示狀態(tài)

接下來是讀取數(shù)據,讀取后的數(shù)據就可以刪除了,可以用Stack.Pop(),但是最后一個讀取的數(shù)據,也就是第一個保存的數(shù)據不能刪,可以用 Stack.Peek()。

??? ObjectStage LoadData()

??? {

??????? if (TimeBackData.Count > 1)

??????? {

??????????? return (ObjectStage)TimeBackData.Pop();

??????? }

??????? else

??????? {

??????????? return (ObjectStage)TimeBackData.Peek();

??????? }

??? }

?

然后就是把讀取的數(shù)據反映到Player身上,也就是時間倒流的過程,要注意在這期間角色應該是不受物理引擎的影響,并且不能播放動畫,要在代碼中關閉。

??? void ShowData(ObjectStage stage)

??? {

??????? animator.enabled = false;

??????? transform.position = stage.Position;

??????? SpriteRenderer.sprite = stage.Sprite;

??????? transform.localScale = new Vector3(stage.IsRight ? 1 : -1, 1, 1);

??????? m_Rigidbody2D.simulated = false;

??????? m_Rigidbody2D.velocity = stage.Velocity;

??? }

?

4.調用代碼實現(xiàn)時間回溯

方法寫好了,接下來就是調用了,我們知道update在一秒內執(zhí)行的次數(shù)是不固定的,所以我們保存數(shù)據和讀取數(shù)據只能放在FixedUpdate里。并且只有在按下時間倒流的按鍵時才能讀取數(shù)據,其他時間保存數(shù)據,按鍵抬起的時候要把之前關閉的物理引擎和動畫開啟。

? ObjectStage LoadStageData = new ObjectStage();?

? private void FixedUpdate()

??? {

??????? if (CheckKey)

??????? {

??????????? LoadStageData = LoadData();

??????????? if (LoadStageData != null)

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

??????????????? ShowData(LoadStageData);

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

??????? }

??????? else

??????? {

??????????? SaveData();

??????? }

??? }

?

(注意,按鍵檢測仍然要放在UpDate里。)

??? private void Update()

??? {

??????? CheckKey = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);

??????? CheckKeyUp = Input.GetKeyUp(KeyCode.LeftShift) || Input.GetKeyUp(KeyCode.RightShift);

??????? if (CheckKeyUp)

??????? {

??????????? cc2D.m_FacingRight = LoadStageData.IsRight;

??????????? animator.enabled = true;

??????????? m_Rigidbody2D.simulated = true;

??????? }

??? }

?

運行游戲操作一會,再按下Shift看看你的角色是不是已經是一個無敵的存在,畢竟一個可以無限時間倒流的人是不可能會輸?shù)陌?。(某平凡的上班族點了個贊?。?/p>

如果追求細節(jié)的話能發(fā)現(xiàn),時間回溯到在空中時結束回溯,角色會垂直落下,這時候只需要把CharacterController2D腳本上的canAirControl勾選為false即可繼續(xù)跳躍。但這樣修改也有個問題,角色不能在空中移動了,為了模擬Braid原版游戲的手感,我們可以嘗試修改基礎工程的move方法。

首先把canAirControl勾選為false。

??????? if (m_Grounded || canAirControl)

??????? {

??????????? // 輸入變量move決定橫向速度

??????????? m_Rigidbody2D.velocity = new Vector2(move, m_Rigidbody2D.velocity.y);

??????? }

??????? else if (!m_Grounded)

???? ???{

??????????? if (move > 0 && m_FacingRight)

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

??????????????? m_Rigidbody2D.velocity = new Vector2(Mathf.Max(move, m_Rigidbody2D.velocity.x), m_Rigidbody2D.velocity.y);

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

??????????? else if (move < 0 && !m_FacingRight)

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

??????????????? m_Rigidbody2D.velocity = new Vector2(Mathf.Min(move, m_Rigidbody2D.velocity.x), m_Rigidbody2D.velocity.y);

??????????? }//如果在空中有相反方向的操作則修改水平速度

??????? }

?

修改后的手感就和Braid里面非常相似了。

另外,如果想在時間回溯時音頻也跟著倒放,可以修改AudioSource組件的Pitch參數(shù)為-1。

修改后的工程:https://pan.baidu.com/share/init?surl=tmPDt9Ebq814cbasffOhlA

提取碼: m4pg


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

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


時間回溯——用Unity實現(xiàn)時空幻境(Braid)中的控制時間效果的評論 (共 條)

分享到微博請遵守國家法律
枣阳市| 九龙城区| 淮滨县| 宁国市| 芦溪县| 苍溪县| 亳州市| 津南区| 龙岩市| 伊金霍洛旗| 兰考县| 瑞昌市| 萨迦县| 桐梓县| 新宁县| 大埔县| 滨州市| 盐城市| 新闻| 合水县| 合江县| 龙岩市| 永善县| 靖安县| 罗江县| 汉中市| 两当县| 潞西市| 湖口县| 喜德县| 聊城市| 邳州市| 双辽市| 岳普湖县| 莎车县| 宜春市| 临颍县| 禄劝| 黄石市| 南投市| 万年县|