2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)

2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)

  • 目录
    • UI界面设置
    • 游戏规则制定
    • Player角色(玩家可控制角色相关)(创建playerC#文件)
    • 怪物类(各种怪物相关)(创建MonsterC#文件)
    • 奖励物体类(金币,无敌,攻击等物品)
    • 界面跳转
    • 发布

目录

UI界面设置

通过各种途径获得相关UI元素,在Unity中左侧栏中利用2D Project中元素完成场景。设置好各个物体所需的Box Collider 2d (碰撞)和 rigidBody 2d(物理属性)。设置好不同物体的类型(tag)(例如角色、金币、怪物、子弹等)后续碰撞检测需要使用。
主场景
2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)_第1张图片
进入游戏界面
2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)_第2张图片
失败和成功界面
2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)_第3张图片
2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)_第4张图片
其中还包括设置游戏内怪物和角色动画。角色为UNITY社区中下载的包,已包含动画。怪物使用关键帧动画,创建动画后,在ctri+6呼出的时间轴中添加关键帧。

游戏规则制定

在项目下新建Scriipt(代码)文件夹,创建GameManager的C#文件。在该文件中制定游戏大体规则。

使用单例模式(饿汉子单例模式)创建各种变量。

public class GameManage : MonoBehaviour
{
    
    //单例模式(饿汉子单例模式)

    public static GameManage Index; //静态变量不能被实例化
    GameManage()
    {
        Index = this;
    }
    
    //工厂模式(内部所有组成成员的变量全部都是静态变量)

    [Header("金币值")]
    public int gold = 0;
    [Header("当前关卡")]
    public int Level = 1;

    /// 
    /// 所有的音频管理
    /// 
    public AudioSource[] allAudio;

    /// 
    /// 地面
    /// 
    public GameObject Floor;

    /// 
    /// 金币显示
    /// 
    public Text Gold;

    /// 
    /// 剩余时间显示
    /// 
    public Text TimeShow;


    float times = 300;

    /// 
    /// 主角速度
    /// 
    public float PlayerSpeed = 0.03f;
    
    /// 
    /// 主角
    /// 
    public GameObject KyaRa;

    /// 
    /// 主角状态 0为无防护
    /// 
    public int PlayerState = 0;

    /// 
    /// 显示无敌图标
    /// 
    public GameObject PlayerIsSuper;

    /// 
    /// 显示主角武器
    /// 
    public GameObject PlayerIsAttact;

    // Start is called before the first frame update
    void Start()
    {
        PlayerIsSuper.SetActive(false);

        PlayerIsSuper.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        times -= Time.deltaTime;
        TimeShow.text = times.ToString();
    }
}

Player角色(玩家可控制角色相关)(创建playerC#文件)

总体分为几种功能
1、角色的各种状态(创建各种变量标识主角状态)

//动画控制
    public Animator anime;
    //物理属性
    public Rigidbody2D rigi;
    //检测是否在地面上(false为不在地面上)
    bool IsOnFloor = false;
    //当前人物位置
    float PlayerPrint;
    //是否人物移动
    bool isPlayerRun = true;
    /// 
    /// 武器
    /// 
    public GameObject Attact;

2、角色控制相关(通过键盘按键WASD移动,J攻击操控角色)移动主要使用transform方法改变主角位置。在主角行走至屏幕中间时,改为地图进行相对向后运动,主角位置不变。

void run()
    {
        //点击D键向右移动
        if (Input.GetKey(KeyCode.D))
        {
            if (isPlayerRun)
            {
                //控制跑动速度和位置
                transform.Translate(GameManage.Index.PlayerSpeed* - 1, 0, 0);
            }
            else
            {
                GameManage.Index.Floor.transform.Translate(GameManage.Index.PlayerSpeed * -1, 0, 0);
            }
            //控制人物面朝方向为向右
            transform.eulerAngles = new Vector3(0, 180, 0);
            if (IsOnFloor )
            {
                //播放跑步动画
                anime.Play("run");
            }
           
        }

        //松开前进键播放站立动画
        if (Input.GetKeyUp(KeyCode.D))
        {
            anime.Play("idle");
        }

        //点击A键向左移动
        if (Input.GetKey(KeyCode.A))
        {
            transform.Translate(GameManage.Index.PlayerSpeed * -1, 0, 0);

            //控制人物面朝方向为向左
            transform.eulerAngles = new Vector3(0, 0, 0);

            if (IsOnFloor)
            {
                //播放跑步动画
                anime.Play("run");
            }
            
            
        }

        //松开前进键播放站立动画
        if (Input.GetKeyUp(KeyCode.A))
        {
            anime.Play("idle");
        }

        //点击W键控制跳跃
        if (IsOnFloor)
        {
            
            if (Input.GetKeyDown(KeyCode.W))
            {
                //给定一个向上的力
                rigi.AddForce(new Vector2(0, 400));
                anime.Play("jump");
            }
        }

        //松开上键播放站立动画
        if (Input.GetKeyUp(KeyCode.W))
        {
           anime.Play("idle");
        }
    }

此外还要设定主角在跳跃过程中不能再进行二次跳跃。在开头变量中设置有变量角色是否在地面上(利用碰撞信息进行判定)在角色控制中使用相关控制语句,在下方的碰撞检测中更改相关变量。

3、角色攻击相关
在角色吃到特定物品后,将GamaManager中的主角状态变量更改,在判断主角状态为可攻击状态时,可以进行攻击。
角色攻击方法(创建一个子弹,并利用rigidBody 2d给其一个力使其移动,子弹的消失和碰撞到怪物杀死怪物消失,后续进行解释)创建子弹使用Instantiate方法,在主角当前位置创建。

 void Attacts()
    {
        if (Input.GetKeyDown(KeyCode.J))
        {
            if (GameManage.Index.PlayerState == 1)
            {

                
                GameObject ss = 
                    Instantiate(Attact,  this.transform.position , this.transform.rotation );//在player下创建子弹
                ss.GetComponent<Rigidbody2D>().AddForce(this.transform.right*600*-1);

            }
        }
    }

4、主角死亡的判定
利用碰撞检测和得到的当前主角状态(若为无敌状态则不死亡)进行条件判断,判断角色是否死亡,利用switch判断。

private void OnCollisionEnter2D(Collision2D collision)
    {
        //Debug.Log(collision.collider.tag);
        if (collision.collider.tag == "Monster")
        {
            //主角死亡
            
            switch (GameManage.Index.PlayerState)
            {
                case 0:
                    anime.Play("die");
                    Die();
                        break;
                case 1:
                    anime.Play("die");
                    Die();
                        break;
                case 2:
                    Debug.Log("您现在是无敌状态");
                        break;
                

            }

        }
        
        IsOnFloor = true;

        //anime.Play("idle");
    }

5、角色死亡方法(角色死亡为触碰到怪物)
主体死亡方法为停止播放当前动画,并播放死亡动画和音频,并利用延迟函数invoke调用两个独立的死亡方法。

public void Die()
    {
        
        GameManage.Index.allAudio[0].Stop();
        GameManage.Index.allAudio[4].Play();
        anime.Play("die");
        Invoke("Die1", 0.5f);
        Invoke("Die2", 4f);
    }

主角死亡后向下掉落出地图(通过改变BoxCollider 2D 的isTrigger属性为true,让主角下落)

void Die1()
    {
        this.gameObject.GetComponent<BoxCollider2D>().isTrigger = true;
    }

主角死亡后界面需要跳转

void Die2()
    {
        SceneManager.LoadScene("fail");
    }

怪物类(各种怪物相关)(创建MonsterC#文件)

1、各种变量(包括记录怪物种类,怪物生命值等的各种变量)

public int MonsterState = 0;//0是普通怪物 1是火圈  2是boss

    public Animator anime;

    public GameObject Fees;

    public float times = 2;

    public int BossLive = 10; 

2、设置不同怪物的移动方式和出场方法(普通怪物在和角色相距10f时开始向主角移动,boss在和角色相距10f是开始发射小型怪物)怪物发射小型怪物原理和上方主角发射攻击原理相同。

if (MonsterState == 0)
        {
            if (Vector3.Distance(GameManage.Index.KyaRa.transform.position, this.transform.position) <= 10f)
            {
                this.transform.Translate(-0.03f, 0, 0);
            }
        }
        else if (MonsterState == 2)
        {
            if (Vector3.Distance(GameManage.Index.KyaRa.transform.position, this.transform.position) <= 10f)
            {
                times -= Time.deltaTime;
                if (times < 0)
                {

                    GameObject ss =Instantiate(Fees, this.transform.position, this.transform.rotation);//在player下创建子弹
                    ss.GetComponent<Rigidbody2D>().AddForce(this.transform.right * 100 );

                    times = 3;
                }
            }
        }

3、怪物死亡判定。(根据怪物状态,不同怪物情况不同,利用碰撞信息判定,判定触碰到无敌状态下的player或子弹都会死亡,boss设定攻击次数。)利用tag辅助判断到底触碰到了什么物体。

void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.tag == "Player")
        {
            if (GameManage.Index.PlayerState == 2)
            {
                Debug.Log("自己死亡");
                this.gameObject.GetComponent<BoxCollider2D>().isTrigger = true;
                GameManage.Index.allAudio[3].Play();
            }
        }
        else if (collision.collider.tag == "Attacts" && MonsterState == 0)
        {
            Debug.Log("自己死亡");
            Destroy(this.gameObject);
            GameManage.Index.allAudio[3].Play();
            GameManage.Index.gold += 10;
            GameManage.Index.Gold.text = GameManage.Index.gold.ToString();
        }

        else if (collision.collider.tag == "Attacts" && MonsterState == 2)
        {
            BossLive = BossLive - 1;
            if (BossLive == 0)
            {
                Debug.Log("自己死亡");
                Destroy(this.gameObject);
                GameManage.Index.allAudio[3].Play();
                GameManage.Index.gold += 100;
                GameManage.Index.Gold.text = GameManage.Index.gold.ToString();
            }
        }


        else if (collision.collider.tag == "Player" && MonsterState == 1 && GameManage.Index.PlayerState <= 2)
        {
            anime.Play("die");
            collision.gameObject.GetComponent<Players>().Die();
        }
        
    }
}

奖励物体类(金币,无敌,攻击等物品)

1、设置变量(包括种类标识信息等)

public int state = 0;//0代表金币1代表武器2代表无敌3代表子弹4代表火圈5代表传送门
    int OldState = 0;

2、根据情况设置不同的碰撞出发(OnTriggerEnter2D、OnCollisionEnter2D等,并根据tag辅助判断碰撞物为角色)

private void Start()
    {
        if (state == 3)
        {
            Invoke("Des", 1f);
        }
    }

    void Des()
    {
        Destroy(this.gameObject);
    }


    private void Update()
    {
        if (state == 4)
        {
            transform.Rotate(0, 0, 0.3f);
        }
    }
    
    //碰撞检测中的触发器,进入触发器区域
    private void OnTriggerEnter2D(Collider2D collision)
    {

        if (collision.tag == "Player" && state == 0)
        {
            GameManage.Index.gold += 1;
            GameManage.Index.Gold.text = GameManage.Index.gold.ToString();
            GameManage.Index.allAudio[1].Play();
            Destroy(this.gameObject);
        }
        else if (collision.tag == "Player" && state == 2)
        {
            

            GameManage.Index.allAudio[5].Play();
            
            OldState = GameManage.Index.PlayerState;
            
            GameManage.Index.PlayerState = 2;
            GameManage.Index.PlayerIsSuper.SetActive(true);
            Invoke("SuperPlayerOver", 5f);
            Destroy(this.gameObject.GetComponent<SpriteRenderer>());//在没有删除物体的情况下,不让其显示
            Destroy(this.gameObject.GetComponent<BoxCollider2D>());
            

        }
        else if (collision.tag == "Player" && state == 1)
        {
            GameManage.Index.allAudio[2].Play();
            
            GameManage.Index.PlayerIsAttact.SetActive(true);

            GameManage.Index.PlayerState = 1;

            Destroy(this.gameObject);
        }
        else if (collision.tag == "Player" && state == 5)
        {
            SceneManager.LoadScene("clear");
        }
        
        
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.tag == "Monster")
        {
            Destroy(this.gameObject);
        }
        


    }

   
    

    void SuperPlayerOver()
    {
        GameManage.Index.PlayerState = 2;
        GameManage.Index.PlayerState = OldState;
        GameManage.Index.allAudio[5].Stop();
        GameManage.Index.PlayerIsSuper.SetActive(false);//设置是否显示一个物体
        Destroy(this.gameObject);
    }

界面跳转

按钮界面的跳转使用了代码进行完成

using UnityEngine.SceneManagement;

public class Login : MonoBehaviour
{
    
    //跳转到制定程序
    public void GotoScene(string Name)
    {

        SceneManager.LoadScene(Name);

    }
}

并需要在unity中设置按钮相关的属性来实现跳转。

在代码头加入using UnityEngine.SceneManagement;后即可直接利用下方语句直接跳转至相应界面

游戏内死亡和完成游戏,为一定条件下直接进行页面跳转,
在代码头加入using UnityEngine.SceneManagement;后即可直接利用下方语句直接跳转至相应界面

SceneManager.LoadScene("fail");

注意:页面跳转需要在unity中building 里将所有SCENE添加到列表中才能实现!!!

发布

发布为webgl版本。在building中选择webgl,根据提示下载相关组件,并进行项目的转换。转换完成后选择building即可。
注意:项目所有的文件名和路径名称必须全部为英文。
注意:使用火狐浏览器打开,还需设置其webgl.force-enable为true
security.fileuri.strict_origin_policy为false才可运行。界面如下:
2D横版游戏Demo试做流程(Unity3D+Visual Studio C#)_第5张图片

2d横版游戏demo展示

你可能感兴趣的:(游戏开发,unity,c#)