2D游戲拾荒者開發(fā)##
一仗处、預(yù)支物的制作##
1.獲取資源: https://pan.baidu.com/s/1qYAozV2
2.圖片的截取.
3.Player和Enemy的動畫制作.
1.把主角的6張圖片同時拖入到Hierarchy面板中顶霞,制動創(chuàng)建Animator蒲每,有Controller畅蹂,和對應(yīng)的動畫.
2.在把攻擊的圖片拖上去俭驮,自動創(chuàng)建攻擊動畫.同理把收到傷害的圖片拖上去陶贼,得到受到傷害的動畫.
Enemy敵人的制作
和Player的制作一樣翘悉,但是我們在制作Enemy2的時候茫打,可以不用從新創(chuàng)建一個Controller了.可以創(chuàng)建一個
Animator Override Controller,通過Enemy1創(chuàng)建Enemy2的動畫妖混,改變圖片從新創(chuàng)建一個新的預(yù)支物就可以.
3.Floor老赤,OutWall的Prefab的制作.
二制市、創(chuàng)建地圖##
這里涉及到層的概念:我們要設(shè)計好層次關(guān)系抬旺,不然系統(tǒng)識別不了那個在前面.
我們吧外墻(OutWall),地板(Floor)設(shè)置為最底層(Background).
食物(friut息堂,soda)設(shè)置為Item嚷狞,敵人和Player設(shè)置為Role層.
腳本代碼管理:
public class MapManager : MonoBehaviour {
public GameObject[] OutWalls;
public GameObject[] Floors;
public GameObject[] walls;
public GameObject[] foods;
public GameObject[] enemys;
public GameObject exitPrefab;
public int line = 10;
public int row = 10;
Transform mapHolder;
private List<Vector2> positionList = new List<Vector2>();//用來保存在敵人,障礙物生成區(qū)域的位置信息
private GameManger gameManager;
int minCountWall = 2;//最少內(nèi)墻個數(shù)
int maxCountWall = 8;//最多內(nèi)墻個數(shù)荣堰,隨機生成
void Awake () {
gameManager = this.GetComponent<GameManger>();
//InitMap();
}
void Update () {
}
public void InitMap()
{
mapHolder = new GameObject("Map").transform;//穿件一個空物體用來管理生成的地圖
//創(chuàng)建外圍墻和地板
for (int i = 0; i < line; i++)
{
for (int j = 0; j < row; j++)
{
if (i == 0 || i == line - 1 || j == 0 || j == row - 1)
{
int index = Random.Range(0, OutWalls.Length);
GameObject go=Instantiate(OutWalls[index], new Vector3(i, j, 0), Quaternion.identity)as GameObject;
go.transform.SetParent(mapHolder);
}
else
{
int index = Random.Range(0, Floors.Length);
GameObject go=Instantiate(Floors[index],new Vector3(i,j,0),Quaternion.identity)as GameObject;
go.transform.SetParent(mapHolder);
}
}
}
positionList.Clear();//承儲敵人床未,障礙物區(qū)域的信息到list里面。
for (int i = 2; i < line-2; i++)
{
for (int j = 2; j < row-2; j++)
{
positionList.Add(new Vector2(i,j));
}
}
//創(chuàng)建障礙物
int wallCount = Random.Range(minCountWall, maxCountWall + 1);
InstantiateItem(wallCount,walls);
//創(chuàng)建食物2-level*2
int foodCount = Random.Range(2, GameManger.level*2+1);//創(chuàng)建的敵人個數(shù)與關(guān)卡有關(guān)系
InstantiateItem(foodCount,foods);
//創(chuàng)建敵人level/2
int enemyCount = GameManger.level/ 2;
InstantiateItem(enemyCount,enemys);
//創(chuàng)建出口
GameObject go1= Instantiate(exitPrefab, new Vector2(line - 2, row - 2), Quaternion.identity) as GameObject;
go1.transform.SetParent(mapHolder);
}
private Vector2 RandomPosition()
{
int positionIndex = Random.Range(0, positionList.Count);
Vector2 pos = positionList[positionIndex];//隨機拿到一個位置List里面的地點信息
positionList.RemoveAt(positionIndex);//在把這個地點信息移除振坚,避免在同一個地點出現(xiàn)多個物體薇搁。
return pos;
}
private GameObject RandomPrefab(GameObject[]prefabs)
{
int index = Random.Range(0, prefabs.Length);
return prefabs[index];
}
private void InstantiateItem(int count,GameObject[] prefabs)
{
for (int i = 0; i < count; i++)
{
Vector2 pos = RandomPosition();
GameObject enemyPrefab = RandomPrefab(prefabs);
GameObject go = Instantiate(enemyPrefab, pos, Quaternion.identity);
go.transform.SetParent(mapHolder);
}
}
}
三、Player和Enemy的動畫完善##
四渡八、主角(Player)的移動邏輯##
腳本展示:
public class Player : MonoBehaviour {
public float smoothing = 1;
public float restTime = 1;
//聲音文件
public AudioClip chop1Audio;
public AudioClip chop2Audio;
public AudioClip step1Audio;
public AudioClip step2Audio;
public AudioClip soda1Audio;
public AudioClip soda2Audio;
public AudioClip fruit1Audio;
public AudioClip fruit2Audio;
private float restTimer = 0;
public Animator animator;
[HideInInspector]public Vector2 targetPos = new Vector2(1, 1);//主角開始的位置
private Rigidbody2D rigibody;
private BoxCollider2D collider;
void Start () {
rigibody = GetComponent<Rigidbody2D>();
collider = GetComponent<BoxCollider2D>();
animator=GetComponent<Animator>();
}
void Update () {
rigibody.MovePosition(Vector2.Lerp(transform.position, targetPos, smoothing * Time.deltaTime));
// if (GameManger.Instance.food <= 0) return;
restTimer += Time.deltaTime;
if (restTimer < restTime) return;
float h = Input.GetAxisRaw("Horizontal");//只會返回-1啃洋,0传货,1
float v = Input.GetAxisRaw("Vertical");
//print(h);
//print(v);
if (h>0)
{
v = 0;
}
if (h != 0 || v != 0)
{
GameManger.Instance.ReduceFood(1);
//檢測
collider.enabled = false;//設(shè)置為不可用,不然會檢測到自己
RaycastHit2D hit=Physics2D.Linecast(targetPos,targetPos+new Vector2(h,v));
collider.enabled = true;
if (hit.transform == null)
{
targetPos += new Vector2(h, v);
AudioManager._instance.RandomPlay(step1Audio,step2Audio);
}
else
{
switch (hit.collider.tag)
{
case "OutWall":
break;
case "Wall":
animator.SetTrigger("Attack");
AudioManager._instance.RandomPlay(chop1Audio, chop2Audio);
hit.collider.SendMessage("TakeDamage");
break;
case "Food":
GameManger.Instance.AddFood(10);
targetPos += new Vector2(h, v);
AudioManager._instance.RandomPlay(step1Audio, step2Audio);
Destroy(hit.transform.gameObject);
AudioManager._instance.RandomPlay(fruit1Audio,fruit2Audio);
break;
case "Soda":
GameManger.Instance.AddFood(20);
targetPos += new Vector2(h, v);
AudioManager._instance.RandomPlay(step1Audio, step2Audio);
Destroy(hit.transform.gameObject);
AudioManager._instance.RandomPlay(soda1Audio, soda2Audio);
break;
case "Enemy":
break;
}
}
GameManger.Instance.OnPlayerMove();//沒幀檢測有沒有到達終點
restTimer = 0;
}
if (GameManger.Instance.food==0||GameManger.Instance.isEnd==true)
{
this.enabled = false;
}
}
public void TakeDamage(int lossFood)
{
GameManger.Instance.ReduceFood(lossFood);
animator.SetTrigger("Damager");
}
}
五宏娄、控制敵人的移動##
代碼展示:
public class Enemy : MonoBehaviour {
private Vector2 targetPosition;
private Transform player;
private Rigidbody2D rigidbody;
public float smoothing = 3;
private BoxCollider2D collider;
private Animator animator;
public int lossFood = 10;
public AudioClip attackAudio;
void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
targetPosition = transform.position;
rigidbody = GetComponent<Rigidbody2D>();
collider = GetComponent<BoxCollider2D>();
animator = GetComponent<Animator>();
GameManger.Instance.enemyList.Add(this);//保存敵人到集合里面
}
void Update()
{
rigidbody.MovePosition(Vector2.Lerp(transform.position,targetPosition,smoothing*Time.deltaTime));
}
public void Move()
{
Vector2 offset = player.position - transform.position;
if (offset.magnitude < 1.1f)
{
//攻擊
animator.SetTrigger("Attack");
AudioManager._instance.RandomPlay(attackAudio);
player.SendMessage("TakeDamage",lossFood);
}
else
{
float x = 0;
float y = 0;
if (Mathf.Abs(offset.y) > Mathf.Abs(offset.x))//按照y軸移動
{
if (offset.y < 0)//向反向
{
y = -1;
}
else//正向
{
y = 1;
}
}
else//按照x軸移動
{
if (offset.x > 0)
{
x = 1;
}
else
{
x = -1;
}
}
//設(shè)置目標位置之前问裕,先做檢測;
collider.enabled = false;
RaycastHit2D hit = Physics2D.Linecast(targetPosition, targetPosition+ new Vector2(x, y));
collider.enabled = true;
if (hit.transform == null)
{
targetPosition += new Vector2(x, y);
}
else
{
if (hit.collider.tag=="Food"||hit.collider.tag=="Soda")
{
targetPosition += new Vector2(x, y);
}
}
}
}
}
六孵坚、游戲管理腳本(對整個游戲進行管理)##
public class GameManger : MonoBehaviour {
public static int level = 1;//當(dāng)前關(guān)卡
public int food = 100;
public AudioClip dieClip;
private static GameManger _instance;
public static GameManger Instance
{
get
{
return _instance;
}
}
[HideInInspector]public bool isEnd = false;
public List<Enemy> enemyList = new List<Enemy>();
private bool sleepStep = true;//控制敵人移動的限定粮宛;
private Text foodText;
private Text failText;
private Image dayImage;
private Text dayText;
private Player player;
private MapManager mapManager;
void Awake()
{
_instance = this;
//DontDestroyOnLoad(gameObject);
InitGame();
}
void InitGame()
{
//初始化地圖
mapManager = GetComponent<MapManager>();
mapManager.InitMap();
food = PlayerPrefs.GetInt("Food", 10);
//初始化UI
foodText = GameObject.Find("FoodText").GetComponent<Text>();
UpdateFoodText(0);
failText = GameObject.Find("FailText").GetComponent<Text>();
failText.enabled = false;
player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
mapManager = GetComponent<MapManager>();
dayImage = GameObject.Find("DayImage").GetComponent<Image>();
dayText = GameObject.Find("DayText").GetComponent<Text>();
dayText.text = "Day" + " " + level;
Invoke("HideBlack", 1);
//初始化參數(shù)
isEnd = false;
enemyList.Clear();
}
void UpdateFoodText(int foodChange)
{
if (foodChange == 0)
{
foodText.text = "Food:" + food;
}
else
{
string str = "";
if (foodChange<0)
{
str = foodChange.ToString();
}
else
{
str = "+" + foodChange;
}
foodText.text = str+" " + "Food:" + food;
}
}
public void ReduceFood(int count)
{
food -= count;
UpdateFoodText(-count);
if(food<=0)
{
failText.enabled = true;
AudioManager._instance.StopBgMusic();
AudioManager._instance.RandomPlay(dieClip);
}
}
public void AddFood(int count)
{
food += count;
UpdateFoodText(count);
}
public void OnPlayerMove()//通知敵人行走,邏輯卖宠,主角走2步巍杈,敵人走一步
{
if (sleepStep == true)
{
sleepStep = false;
}
else
{
foreach (var enemy in enemyList)
{
enemy.Move();
}
sleepStep = true;
}
//檢測有沒有到達終點
if (player.targetPos.x==mapManager.line-2&&player.targetPos.y==mapManager.row-2)
{
PlayerPrefs.SetInt("Food", food);
isEnd = true;
//加載下一個關(guān)卡
SceneManager.LoadScene(0);
//Application.LoadLevel(Application.loadedLevel);//從新加載本關(guān)卡
}
}
void OnLevelWasLoaded()
{
//PlayerPrefs.GetFloat("level", 1);
level++;
//PlayerPrefs.SetFloat("level", level);
// InitGame();
}
void HideBlack()
{
dayImage.gameObject.SetActive(false);
}
}
七、Player對敵人扛伍,食物筷畦,和墻里面障礙物的處理##
對內(nèi)墻的攻擊處理:
public class Wall : MonoBehaviour {
public int hp = 2;
public Sprite damageSprite;//受到攻擊的圖片
public void TakeDamage()
{
hp -= 1;
GetComponent<SpriteRenderer>().sprite = damageSprite;
if(hp==0)
{
Destroy(this.gameObject);
}
}
}
八、食物的UI處理##
九刺洒、聲音文件的添加##
聲音文件很重要鳖宾,在適當(dāng)?shù)臅r候,合適的位置添加聲音文件.
腳本管理:
public class AudioManager : MonoBehaviour {
public float minPitch = 0.9f;
public float maxPitch = 1.1f;
public static AudioManager _instance;
public AudioSource efxSouce;
public AudioSource bgSource;
void Awake()
{
_instance = this;
}
public void RandomPlay(params AudioClip[]clips)//播放聲音文件
{
float pitch = Random.Range(minPitch,maxPitch);
int index = Random.Range(0,clips.Length);
AudioClip clip = clips[index];
efxSouce.clip = clip;
efxSouce.pitch = pitch;//播放速度
efxSouce.Play();
}
public void StopBgMusic()//游戲結(jié)束時作媚,結(jié)束背景音樂的播放
{
bgSource.Stop();
}
}