【Unity】 2D贪吃豆开发流程

贪吃豆主要是用SpriteRenderer进行开发,是2D的,其中有豆子、玩家黄豆、敌人四个豆子(不同颜色),一张贪吃豆的地图。

贪吃豆地图的碰撞体设置会有些许麻烦,那就是要在它身上挂载很多个碰撞体来实现整张地图的碰撞体。

豆子需要一个碰撞体(勾选Trigger)和一个脚本进行管理豆子,一般都是处理豆子的消亡和加分逻辑等,脚本如下。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Pacdot : MonoBehaviour {

    public bool isSuperPacdot = false;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.name=="Pacman")
        {
            if (isSuperPacdot)
            {
                //吃豆后把吃掉的豆子所记录在pacdotGos列表中的豆子删除
                GameManager.Instance.OnEatPacdot(gameObject);
                //吃掉超级豆子后执行的各种效果
                GameManager.Instance.OnEatSuperPacdot();
                //删除该豆子
                Destroy(gameObject);
            }
            else
            {
                GameManager.Instance.OnEatPacdot(gameObject);
                Destroy(gameObject);
            }
        }
    }
}

玩家黄豆需要一个碰撞体、一个2D刚体(将重力设置为0)、一个Animator用于控制玩家黄豆动画播放的,例如:上、下、左、右都是有一个张嘴合嘴的序列帧动画,也就是四个动画,在动画管理器里面设置2个变量来进行控制这四个动画在何时播放,具体代码在下面给出,下面的代码是挂在玩家黄豆身上的,以用于控制玩家移动、动画播放等。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move : MonoBehaviour
{
    public float speed = 0.35f;//速度
    private Vector2 dest = Vector2.zero;//目的地位置

    private void Start()
    {
        dest = transform.position;//初始位置设置
    }

    private void FixedUpdate()
    {
        //插值获取到达dest位置的下一个位置temp
       Vector2 temp = Vector2.MoveTowards(transform.position, dest, speed);
        //移动到temp位置
        GetComponent<Rigidbody2D>().MovePosition(temp);
        //必须到达上一次dest位置,才可以重新开始新的dest目的地位置
        if ((Vector2)transform.position == dest)
        {
            if ((Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))&& Valid(Vector2.up))
            {
                dest = (Vector2)transform.position + Vector2.up;
            }
            if ((Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S)) && Valid(Vector2.down))
            {
                dest = (Vector2)transform.position + Vector2.down;
            }
            if ((Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A)) && Valid(Vector2.left))
            {
                dest = (Vector2)transform.position + Vector2.left;
            }
            if ((Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))&& Valid(Vector2.right))
            {
                dest = (Vector2)transform.position + Vector2.right;
            }
            //获取移动方向 
            Vector2 dir = dest - (Vector2)transform.position;
            //把获取到的移动方向设置给动画状态机
            GetComponent<Animator>().SetFloat("DirX", dir.x);
            GetComponent<Animator>().SetFloat("DirY", dir.y);
        }
    }
    //检测将要去的位置是否可到达
    private bool Valid(Vector2 dir)
    {
        Vector2 pos = transform.position;
        //hit 是接收到碰到的物体
        RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);//从到达的位置发射一条射线到自身位置
        return (hit.collider == GetComponent<Collider2D>());//若能碰到自身,那么说明可以移动到那个位置,若不可以则说明不能到达
    }
}

敌人四个豆子需要一个碰撞体(需要勾选Trigger)、一个2D刚体(重力为0)、一个Animator和上面一样,动画也是有4个,也是有一样意义的2个参数,所以我们可以在创建Animator的时候,点击Animator Override Controller,然后把玩家黄豆的Animator拖过去,就能生成基本一样的Animator(即条件、动画个数一样),然后将里面的四个动画改为敌人的四个动画即可,最后需要挂载一个脚本控制敌人移动、动画播放等,代码如下。其中,四个敌人都是在2、3、4、5层级(SpriteRenderer组件的Order in layer)的,玩家黄豆在6层级,豆子在1层,地图本身在0层。此外,敌人的移动是固定路径的,也就是路径点是分配好了的,敌人只需一个点一个点地走就OK了,那个wayPointsGos是保存了4个物体,这些物体的子物体们都是路径点,也就是一些空物体,主要是我们要获取position就好,这些物体都是在开发前制作好的路径点物体预制体,直接用public方式传递给脚本的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GhostMove : MonoBehaviour {
    //存储所有路径点的Transform
    public GameObject[] wayPointsGos;
    public float speed = 0.2f;
    private List<Vector3> wayPoints = new List<Vector3>();
    private int index = 0;//当前在前往哪个路径点中
    private Vector3 startPos;
    public GameObject canvas; 
    private void Start()
    {
        startPos = transform.position + new Vector3(0, 3, 0);
        LoadPath(wayPointsGos[GameManager.Instance.usingIndex[GetComponent<SpriteRenderer>().sortingOrder-2]]);
    }
    private void FixedUpdate()
    {
        //鬼移动方法:
        //若鬼没有到达目的地则继续移动
        if (transform.position != wayPoints[index])
        {
            //插值获取到达wayPoints[index].position位置的下一个位置temp
            Vector2 temp = Vector2.MoveTowards(transform.position, wayPoints[index], speed);
            //移动到temp位置
            GetComponent<Rigidbody2D>().MovePosition(temp);
        }
        else//若到达目的地,则选择新的目的地
        {
            index++;
            if(index>=wayPoints.Count)
            {
                index = 0;
                LoadPath(wayPointsGos[Random.Range(0, 4)]);
            }
        }
       
        //获取移动方向 
        Vector2 dir = wayPoints[index] - transform.position;
        //把获取到的移动方向设置给动画状态机
        GetComponent<Animator>().SetFloat("DirX", dir.x);
        GetComponent<Animator>().SetFloat("DirY", dir.y);
    }
 
    /// <summary>
    /// 鬼碰到玩家,则销毁玩家
    /// </summary> 
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.name == "Pacman")
        {
            if (GameManager.Instance.isSuperPacman)
            {               
                //碰到超级吃豆人,该怪物回家
                transform.position = startPos - new Vector3(0, 3, 0);
                index = 0;//从路径头部开始
                //吃了鬼 给奖励分
                GameManager.Instance.score += 500;
            }
            else//如果碰到的是普通吃豆人,则销毁玩家(吃豆人)
            {
                collision.gameObject.GetComponent<Collider2D>().enabled = false;
                collision.gameObject.SetActive(false);
                
                GameManager.Instance.gamePanel.SetActive(false);
                GameObject go = Instantiate(GameManager.Instance.gameOverPrefab,canvas.transform);
                go.transform.SetParent(canvas.transform);   
                Invoke("ReStart", 3f);
            }
        }
    }

    private void LoadPath(GameObject go)
    {
        //加载路径点前,先清空存放的列表
        wayPoints.Clear();
        //遍历wayPointsGo物体身上所有子物体的Transform
        foreach (Transform t in go.transform)
        {
            wayPoints.Add(t.position);//把子物体的Position存放入List中
        }
        wayPoints.Insert(0, startPos);
        wayPoints.Add(startPos);
    }

    private void ReStart()
    {
        SceneManager.LoadScene(0);
    }
}

UI部分的脚本就不说了,基本如上所述一个2D贪吃豆游戏就基本完成了,其中,豆子是有一个叫超级豆子的玩意的,玩家吃了后能把敌人吃回家,不会受到敌人的攻击而死亡,加速之类的。超级豆子是在一开始就从一堆豆子中随机选一个把它变为超级豆子的,其实代码也就是一个bool变量的事情,为false是普通,为true是超级豆子,超级豆子的图片变大点就能让玩家知道这个豆子是超级豆子,你也可以特别地为超级豆子选个牛逼点的图片。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity2D/3D开发流程主要包括以下几个步骤: 1. 确定游戏类型和玩法:在开始开发前,需要确定游戏类型和玩法,包括游戏的主题、场景、角色、关卡、道具等,以及游戏的操作方式、规则、目标等。 2. 设计游戏关卡和场景:在确定游戏类型和玩法后,需要设计游戏的关卡和场景,包括地图、道具、障碍、敌人等。在设计时需要考虑游戏的难度、节奏、流畅度和趣味性等因素。 3. 创建游戏对象和元素:在设计游戏关卡和场景后,需要创建游戏对象和元素,包括角色、道具、敌人、场景元素等。可以使用Unity的编辑器来创建和编辑游戏对象和元素,也可以使用第三方工具来创建和导入。 4. 添加组件和脚本:在创建游戏对象和元素后,需要添加相应的组件和脚本来控制其行为和动作。可以使用Unity的组件和脚本来实现常见的游戏行为,也可以使用C#脚本来编写自定义的游戏逻辑。 5. 调试和测试:在添加组件和脚本后,需要进行调试和测试,以确保游戏的功能和表现符合设计要求。可以使用Unity的调试工具来检查游戏对象和脚本的状态和行为,也可以使用第三方工具来进行测试和调试。 6. 优化和打包发布:在完成测试和调试后,需要对游戏进行优化和打包发布。可以使用Unity的优化工具来优化游戏性能和资源占用,也可以使用Unity的打包工具来打包和发布游戏到不同的平台和设备。 以上是Unity2D/3D开发流程的主要步骤,每个步骤都需要认真考虑和实践,以确保游戏的质量和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值