從零開始的星露谷-用Unity還原星露谷物語:移動,界面篇(1)

作者:對馬騎馬使用炎拳吧
大家好,我是再無悲喜的炎拳。
作為爆賣1000萬份的模擬農(nóng)場RPG,星露谷自然吸引了我這樣的休閑玩家,本期待能愉悅的搭建自己的小農(nóng)場,結(jié)果卻沉迷釣魚下礦無法自拔,過起了007的日子,最后只能大嘆西八!

當(dāng)然,這些只是玩笑話,星露谷中豐富的人物互動事件,有趣的耕種建造系統(tǒng),以及春夏秋冬獨(dú)有節(jié)日和大量的彩蛋,讓玩家剛?cè)氡隳苎杆偃谌脒@個可愛的小鎮(zhèn)。聽著小曲,結(jié)束一天的冒險后,帶著路邊摘得野花回家,路上遇到喜歡的人,順手將花送給她,知道她對你的愛心又多了一個。晚上在家門口釣釣魚,回家摸摸寵物入睡。。這樣充實(shí)愉悅的生活,不由讓我感嘆,比起城里和鄉(xiāng)下,還是做一只星露谷中的老鼠好啊~

廢話不多說,進(jìn)入主題,原作者Eric Barone花費(fèi)了四年時間,獨(dú)立開發(fā)了星露谷物語,可見里面看似簡單的功能還是工作量蠻大的。實(shí)際上在復(fù)刻星露谷的過程中,我也逐漸察覺到了許多在玩的時候,并未在意的豐富的細(xì)節(jié)。嘗試還原自己喜愛的游戲,是一個有趣的過程,你能更為透徹的感受這個世界的肌理,以及制作者的心情~
作為一款2D像素游戲,首先自然是移動,網(wǎng)上找的星露谷素材包里人物的精靈圖分割的挺有條理,我選擇了阿比蓋爾作為主角。
使用前需要對素材進(jìn)行設(shè)置,過濾模式設(shè)置為Point,默認(rèn)選項(xiàng)設(shè)置為不壓縮圖片質(zhì)量,同時修改圖集參數(shù)Pixels Per Unit為16(具體根據(jù)圖集的人物長度決定)。 最后用SpriteEditor中Grid By Cell Size的方法將圖集分割成16 * 16像素大小的圖片,阿比蓋爾的素材就準(zhǔn)備完成了:

接下來制作人物的移動動畫,星露谷中人物的移動有八個方向:上下左右,左上,左下,右上右下,實(shí)際上展示的動畫只有上下左右四個方向,素材中已經(jīng)包含了這一套動作,我們直接使用unity 的動畫系統(tǒng)制作各個方向的移動動畫即可:

同時在代碼中寫個方向的枚舉類做準(zhǔn)備,這里看起來比較繁瑣,但星露谷中幾乎所有的操作都和方向有關(guān),需要獲得人物當(dāng)前精準(zhǔn)的方向,所以還是選擇了這個比較笨重的辦法來控制動畫:
public enum Direction
{
???Down,Up,Left,Right,DownLeft,DownRight,UpLeft,UpRight,Stand
}
?
然后開始制作動畫狀態(tài)機(jī),星露谷中人物的日常狀態(tài)為站立和行走,同時每種狀態(tài)包含四個方向,所以我們可以選擇混合樹來管理這些方向的轉(zhuǎn)換:


星露谷人物移動沒有加速的過程,直接勻速運(yùn)動,所以我們直接設(shè)置類型為1D,通過檢測按鍵按下+長按事件,控制動畫轉(zhuǎn)換即可:

? ? public void UniformMove()
????{
????????Vector2 position = transform.position;
?
????????switch (GetDirection())
????????{
????????????case Direction.Down:
????????????????position.y = position.y + -Speed * Time.deltaTime;
????????????????break;
????????????case Direction.Up:
????????????????position.y = position.y + Speed * Time.deltaTime;
????????????????break;
????????????case Direction.Left:
????????????????position.x = position.x + -Speed * Time.deltaTime;
????????????????break;
????????????case Direction.Right:
????????????????position.x = position.x + Speed * Time.deltaTime;
????????????????break;
????????????case Direction.DownLeft:
????????????????position.y = position.y + -Speed * Time.deltaTime * TurnSpeed;
????????????????position.x = position.x + -Speed * Time.deltaTime * TurnSpeed;
????????????????break;
????????????case Direction.DownRight:
????????????????position.y = position.y + -Speed * Time.deltaTime * TurnSpeed;
????????????????position.x = position.x + Speed * Time.deltaTime ?* TurnSpeed;
????????????????break;
????????????case Direction.UpLeft:
????????????????position.y = position.y + Speed * Time.deltaTime * TurnSpeed;
????????????????position.x = position.x + -Speed * Time.deltaTime * TurnSpeed;
????????????????break;
????????????case Direction.UpRight:
????????????????position.y = position.y + Speed * Time.deltaTime * TurnSpeed;
????????????????position.x = position.x + Speed * Time.deltaTime * TurnSpeed;
????????????????break;
????????????case Direction.Stand:
????????????????break;
????????????default:
????????????????break;
????????}
????????rigidbody2D.MovePosition(position);
????}
?
游戲中人物選中物品,會有一個舉起物品一起走的動作,物品也會有一個一上一下的動畫,在狀態(tài)機(jī)里新建一層layer執(zhí)行物品動畫即可,最終效果如下:

這樣人物的移動暫時就完成了,后續(xù)要添加新的動畫也比較方便,接下來完成人物的狀態(tài)欄背包,首先同樣從精靈圖集中找到面板素材,面板需要增刪物品時自動排列,所以我選擇用Unity自帶的UI控件Scrollview來完成,物品是在橫向逐漸增加,所以我們直接刪除滾動條,給Viewport增加一個Horizontal組件:

然后再根據(jù)需求建立物品的模板預(yù)制體,并在Horizontal中測試出物品之間的合適的間距,當(dāng)涉及到物品的增刪操作,就不需要自己再調(diào)整布局了,效果如下:

這里可能有朋友注意到不同物品的信息面板大小也有所不同,星露谷中物品繁多,對應(yīng)的描述文字?jǐn)?shù)量也不同,所以當(dāng)我們生成不同的物品的時候,需要根據(jù)文字的數(shù)量來決定面板的寬度,具體代碼如下:
?//構(gòu)造信息展示面板 ,傳入?yún)?shù)的info中包含描述信息
????public void ?SetDesPanel(ItemInfo info )
????{
????????//載入字體,獲取描述文字
????????Font font = Resources.Load<Font>("Font/Arial");
????????int fontsize = 18;
????????string text = info.description;
?
????????//獲取這段文字的總字符長度
????????font.RequestCharactersInTexture(text, fontsize, FontStyle.Normal);
????????CharacterInfo characterInfo;
????????float width = 0f;
????????for (int i = 0; i < text.Length; i++)
????????{
???????????// Debug.Log("字符長度");
????????????font.GetCharacterInfo(text[i], out characterInfo, fontsize);
????????????width += characterInfo.advance;
????????}
?
????????//設(shè)置信息面板長寬
????????if (width <=253 && width > 173)
????????{
????????????DisplayPanel.rectTransform.sizeDelta = new Vector2(width, 245);
????????}
????????else if (width < 173)
????????{
????????????DisplayPanel.rectTransform.sizeDelta = new Vector2(173, 245);
????????}
????????else
????????{
????????????int line =(int)(width /253);
????????????//Debug.Log("行數(shù)"+line );
????????????DisplayPanel.rectTransform.sizeDelta = new Vector2(300, 245+line*27);
????????}
????}
?
同時要保證信息面板始終渲染在物品的后面,這樣才不會被物品圖標(biāo)遮擋,所以將其父級設(shè)置為Inventory_Tabs,和Viewport同一層級:
DisplayPanel.transform.SetParent(inventory_Tabs.transform,false );
?
最后一個關(guān)鍵點(diǎn)是選中物品并對其進(jìn)行操作,這里要結(jié)合數(shù)據(jù)的讀取來說,我把這部分內(nèi)容放在下一篇,最后放一張目前實(shí)現(xiàn)的進(jìn)度:包括從Excel表格和json中分別載入物品信息,數(shù)據(jù)的存儲,基于Tilemap的單獨(dú)每塊地上植物的小動畫(有點(diǎn)小麻煩),施工還沒完成,就先不放工程了,敬請期待~


歡迎加入游戲開發(fā)群歡樂攪基:1082025059
對游戲開發(fā)感興趣的童鞋可戳這里進(jìn)一步了解:http://www.levelpp.com/
我們的公眾號:“皮皮關(guān)"
B站:“皮皮關(guān)做游戲”