当前位置:   article > 正文

笔记23 Unity项目:超级玛丽_3d马里奥编程代码

3d马里奥编程代码

拖放地图,裁剪精灵,形成跑步动画,精灵渲染器

在这里插入图片描述

摄像机跟随+代码CameraControl

在这里插入图片描述

    //跟随的物体
    public Transform target;

    //最小边界(能到的最左边)
    public float minX;
    //最大边界(能到的最右边)
    public float maxX;

	void Update () {
        //获取当前位置
        Vector3 pos = transform.position;
        //将它的x改成目标的x
        pos.x = target.position.x;
        //边界判断。需要传入两个边界
        if(pos.x > maxX)
        {
            pos.x = maxX;
        }
        if(pos.x < minX)
        {
            pos.x = minX;
        }
        //再赋值回去
        transform.position = pos;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

玛里奥动画

在这里插入图片描述

给马里奥、地面等添加碰撞器、刚体(注意是2D的!)

在这里插入图片描述

添加音乐播放器+代码AudioManager

在这里插入图片描述

   //音频播放器有了,首先写成单例类。
    public static AudioManager Instance;

    //写出两个播放器(背景音、音效)。然后到unity里关联(背景音,循环打钩)。
    public AudioSource bgmPlayer;
    public AudioSource sePlayer;

    void Awake()
    {
        //单例类一定要在Awake里面赋值。因为这个方法调用的时机比Start靠前。
        //这样可以保证在第一时间把这个单例做成。
        Instance = this;
    }

    // 下面给三个方法
    //一个播放bgm。传进来一个name,就是你播放的文件名称
    public void PlayMusic(string name)
    {
        //如果当前没有播放,再去播放
        if (bgmPlayer.isPlaying == false)
        {
            /*加载音频资源。类型AudioClip。
            从哪个位置加载?直接把name(外界传进来的)放那就可以了。*/
            AudioClip clip = Resources.Load<AudioClip>(name);
            //更换当前播放的声音片段
            bgmPlayer.clip = clip;
            //播放Play
            bgmPlayer.Play();
        }
    }
    //停止播放
    public void StopMusic()
    {
        bgmPlayer.Stop();
    }
    //播放音效
    public void PlaySound(string name)
    {
        /*加载音频资源。类型AudioClip。
        从哪个位置加载?直接把name(外界传进来的)放那就可以了。*/
        AudioClip clip = Resources.Load<AudioClip>(name);
        //播放音效
        sePlayer.PlayOneShot(clip);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

检测是否与地面碰撞(有两种方法)

法一:利用射线检测是否碰到地面(适用此游戏)

       //利用射线检测是否碰到地面(法一)
        //画出射线。从中心点出发,向下*0.1米。
        Debug.DrawRay(transform.position, Vector2.down * 0.1f);
        /*创建2d射线。特点:可以直接返回。3d返回的是布尔值,hit在上面,利用out给hit值。
        而且在括号里可以直接填写射线的起点,方向,距离,检测的层(此处是第8层)。*/
        RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down ,0.1f,1<<8);
        if(hit.collider != null)
        {
            //说明碰到地面了
            isGround = true;
            //把跳跃的动画关闭
            ani.SetBool("Jump", false);
        }
        else
        {
            //没碰到地面(在空中)
            isGround = false;
            ani.SetBool("Jump", true);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在这里插入图片描述

法二:不通过射线(不适用此游戏)

   //判断是否碰撞到地面(法二)。此处不适用,比如碰到左边碰撞体,可以二段跳。
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.tag == "Ground")
        {
            isGround = true;
        }
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.collider.tag == "Ground")
        {
            isGround = false;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

敌人蘑菇+代码EnemyControl

拖放,添加碰撞器、刚体,添加动画,编写代码,形成预设体。
在这里插入图片描述

    //血量
    public int Hp = 1;
    //刚体
    private Rigidbody2D rBody;
    //动画
    private Animator ani;

    //保存方向。方向分为1(正方向)和-1(负方向)。
    private int dir = 1;

	void Start () {
        //在这里得到
        rBody = GetComponent<Rigidbody2D>();
        ani = GetComponent<Animator>();		
	}
	
	void Update () {
		if(Hp <= 0)
        {
            return;
        }
        /*移动(方向*速度)。
        为了使敌人碰到物体后向相反方向移动,此处乘以方向(上面设置了默认是正方向)。*/
        //老师写的是Vector3.left
        transform.Translate(Vector2.left * 0.2f * dir * Time.deltaTime);
	}
    //不管碰到什么物体,都向反方向移动
    private void OnCollisionEnter2D(Collision2D collision)
    {
        dir = -dir;
        //判断玩家碰到自己。注意给玩家标签。
        if(collision.collider.tag == "Player")
        {
            //contacts[0]碰撞的点,point代表拿到这一点的位置。
            //contacts[0].normal它还有一个法线,就是和碰撞点垂直的单位向量。
            //比如玩家从上面踩了蘑菇,会产生从碰撞点向下的法线。
            if (collision.contacts[0].normal == Vector2.down)
            {
                //也就是说玩家从上方踩到,敌人死亡
                //拿到玩家身上的刚体组件,给它添加一个向上的力。
                collision.collider.GetComponent<Rigidbody2D>().AddForce(Vector2.up * 100f);
                //死亡方法写在外面,此处调用。
                Die();
            }
            else
            {
                //玩家从其他方向碰到敌人,玩家死亡
                //拿到玩家的代码,调用里面的Die方法。
                collision.collider.GetComponent<PlayControl>().Die();
            }
        }
    }
    //死亡
    void Die()
    {
        Hp--;
        if(Hp <= 0)
        {
            //死亡
            //一秒之后销毁
            Destroy(gameObject, 1f);
            //动画
            ani.SetBool("Die", true);
            //声音
            AudioManager.Instance.PlaySound("踩敌人");
            /*碰撞器失效(因为死亡了,玩家踩到的时候不能再触发事件。
            而之所以能产生事件,是因为碰撞器的存在)*/
            GetComponent<Collider2D>().enabled = false;
            //删除刚体(碰撞器也可以用此方法。如果删除了碰撞器,而没有删除刚体,那么蘑菇会掉下去。)
            Destroy(GetComponent<Rigidbody2D>());
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

代码:马里奥PlayControl

    //人物的血量
    public int Hp = 1;
    //是否在地面
    private bool isGround = false;
    //刚体
    private Rigidbody2D rBody;
    //动画
    private Animator ani;
    //获取精灵图片(为了后面翻转图片)
    private SpriteRenderer sr;


	void Start () {
        //在此处拿到这两个组件
        rBody = GetComponent<Rigidbody2D>();
        ani = GetComponent<Animator>();
        sr = GetComponent<SpriteRenderer>();
	}
	
	void Update () {
		if (Hp <= 0)
        {
            return;
        }
        //因为人物只是左右跑,所以拿水平轴
        float horizontal = Input.GetAxis("Horizontal");
        //如果水平轴不为0
        if (horizontal != 0)
        {
            //前进
            transform.Translate(transform.right * Time.deltaTime * 1 * horizontal);
            //翻转图片(模拟转头)
            if (horizontal > 0)
            {
                //说明是往右边走所以不翻转
                sr.flipX = false;
            }
            if (horizontal < 0)
            {
                sr.flipX = true;
            }
            //移动动画
            ani.SetBool("Run", true);
        }
        else
        {
            ani.SetBool("Run", false);
        }
        //跳跃。按了I键,并且人物是站在地上的。
        if (Input.GetKeyDown(KeyCode.I) && isGround == true)
        {
            //跳跃力(向上,作用在刚体上)
            rBody.AddForce(Vector2.up * 200);
            //播放跳的声音
            AudioManager.Instance.PlaySound("跳");
        }
       
        //利用射线检测是否碰到地面(法一)
        //画出射线。从中心点出发,向下*0.1米。
        Debug.DrawRay(transform.position, Vector2.down * 0.1f);
        /*创建2d射线。特点:可以直接返回。3d返回的是布尔值,hit在上面,利用out给hit值。
        而且在括号里可以直接填写射线的起点,方向,距离,检测的层(此处是第8层)。*/
        
       RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.1f, 1<<8);
       if(hit.collider != null)
       {
           //说明碰到地面了
           isGround = true;
           //把跳跃的动画关闭
           ani.SetBool("Jump", false);
       }
       else
       {
           //没碰到地面(在空中)
           isGround = false;
           ani.SetBool("Jump", true);
       }     
    }

    //玩家的死亡方法,因为在敌人的代码里调用,所以此处是public
    public void Die()
    {
        Hp--;
        if (Hp <= 0)
        {
            //死亡
            ani.SetTrigger("Die");
            //删除碰撞器。(因为玩家死亡时,是从场景中掉落的,所以只要删除碰撞器,不删刚体)。
            Destroy(GetComponent<Collider2D>());
            //停止播放背景音乐
            AudioManager.Instance.StopMusic();
            //播放死亡音乐
            AudioManager.Instance.PlaySound("死亡");
            //让玩家静止
            rBody.velocity = Vector2.zero;
            //让玩家静止,即将它的速度设为0。为了避免玩家在不同情况下死亡后,向上跳的高度不同)
            rBody.velocity = Vector2.zero;
            //跳跃。给一个向上的力
            rBody.AddForce(Vector2.up * 150f);
            //延时。1秒之后播放
            Invoke("Die2", 1f);
        }
    }
    void Die2()
    {
        AudioManager.Instance.PlaySound("死亡2");
    } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107

补充

使用字符串(即动画名字)播放动画

    //
            //移动动画
            ani.SetBool("Run", true);
  • 1
  • 2
  • 3

将名称(字符串)转成ID后使用

每个动画都有一个ID。
因为系统开辟字符串比开辟整形更加费性能,如果一个动作需要多次使用,优化方法:
在最开始的时候(Start里),把动作都转成int类型,用的时候,只要用int类型就好。

    //移动动画
    int run = Animator.StringToHash("Run");
    //Debug.Log(run);打印ID
    ani.SetBool(run,true);
    
    //获取数值
    bool res = ani.GetBool(run);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

静态金币+代码CoinStatic

在这里插入图片描述

    //触发
    private void OnTriggerEnter2D(Collider2D collision)
    {
         if(collision.tag == "Player")
         {
            //播放声音
            AudioManager.Instance.PlaySound("金币");
            //销毁自己
            Destroy(gameObject);
         }
     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

砖块+代码RockControl

在这里插入图片描述

    //大砖块
    public GameObject Rock;
    //小砖块
    public GameObject[] Rocks;
    //写完上面的代码,需要到unity里面关联一下。

	// Use this for initialization
	void Start () {
		
	}
	

    private void OnCollisionEnter2D(Collision2D collision)
    {
        //如果玩家碰了我,并且碰撞点的法线向上(说明玩家是从线面碰到的)
        if (collision.collider.tag == "Player" && collision.contacts[0].normal == Vector2.up)
        {
            //播放音乐
            AudioManager.Instance.PlaySound("顶破砖");
            //小砖块会四散开来。首先遍历一下
            foreach(GameObject rock in Rocks)
            {
                //把父物体(大砖块)设置为空,小砖块就没有父物体了,会显示在前面
                rock.transform.parent = null;
                //3D有爆炸力,2D没有。首先,添加刚体。rock是4个小砖块
                Rigidbody2D rbody = rock.AddComponent<Rigidbody2D>();
                //得到从整体的中心点到各个小砖块中心点的向量。
                Vector2 dir = rock.transform.position - transform.position;
                //给力。dir沿着这个向量的方向*100的力
                rbody.AddForce(dir * 900f);
                //1秒之后销毁
                Destroy(rock, 1f);
            }
            //销毁大砖块
            Destroy(gameObject);
        }
    } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

箱子、顶出动态金币+二者代码

在这里插入图片描述

代码:箱子BoxControl

    //血量。(顶几次)
    public int Hp = 5;
    //顶出来的物体
    public GameObject goPre;
    //音效名称(传进来)
    public string sound; 

	void Start () {
		
	}
	
	private void OnCollisionEnter2D(Collision2D collision)
    {
        //如果玩家从下面顶撞
        if (collision.collider.tag == "Player" && collision.contacts[0].normal == Vector2.up)
        {
            if(Hp > 0)
            {
                Hp--;
                //顶出物品
                //声音
                AudioManager.Instance.PlaySound(sound);
                //实例化物品
                Instantiate(goPre, transform.position, Quaternion.identity);
                if(Hp <= 0)
                {
                    //变成砖块(就是下面的“没了”)
                    //获得动画
                    GetComponent<Animator>().SetTrigger("Die");
                }
            }else
            {
                //箱子已经没了。
                //播放没了的声音
                AudioManager.Instance.PlaySound("顶砖石块");
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

代码:动态金币CoinControl

   void Start () {
        //获得刚体
        GetComponent<Rigidbody2D>().AddForce(Vector2.up * 150f);
        //销毁金币
        Destroy(gameObject, 1f);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

顶箱子,顶出其他东西

在这里插入图片描述

老师说要进行拓展练习(暂空)

小记:《马里奥、〈白夜行〉、我》

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/109242
推荐阅读
相关标签
  

闽ICP备14008679号