unity 2D pingpongGame

添加背景

新建一个图层
选中bg这一对象 点击右上角Layer AddLayer 新建一个图层将Layer设置为新建的图层

在scence 中添加player png 设置合适大小 添加BoxCollide 2D 设置合适size

设计Player 预制体

控制player
添加ridebody 2D
没有重力 所以设置Gravity scale ==0
并且锁定旋转 Constraints-》选中Freeze rotation z x
为了控制Player 移动 给他添加newscript PlayerController.cs
把该脚本拖到Scripts文件夹里面
最后一步把灰色的player对象拖到Prefabs文件夹里面 对象变成蓝色

设立围墙边界

设置四面刚体 boxclollides

设置upWall 的boxCollide来阻挡player越界
gameManagerScript.cs

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

public class gameManagerScripts : MonoBehaviour

{

	private BoxCollider2D rightWall;
	private BoxCollider2D leftWall;
	private BoxCollider2D upWall;
	private BoxCollider2D downWall;

    // Start is called before the first frame update
    void Start()
    {
        ResetWall();//引用下面设置围墙的这个方法
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void ResetWall()
    {
    	//初始化墙的对象为之前在Scence里创建的对象
    	rightWall=transform.Find("rightWall").GetComponent<BoxCollider2D>();
    	leftWall=transform.Find("leftWall").GetComponent<BoxCollider2D>();
    	upWall=transform.Find("upWall").GetComponent<BoxCollider2D>();// x=Screen.width/2 y=Screen.hight
    	downWall=transform.Find("downWall").GetComponent<BoxCollider2D>();
		//新建一个三维坐标来确定upWall的坐标
    	Vector3 upWallPositon=Camera.main.ScreenToWorldPoint(new Vector3(Screen.width/2,Screen.height));
    	//将上墙的y坐标位置设置为屏幕顶端加上上墙宽度的一半
           upWall.transform.position=upWallPositon+new Vector3(0,0.5f,0);
           //获取屏幕宽度
           float width=Camera.main.ScreenToWorldPoint(new Vector2(Screen.width,Screen.height)).x*2;
           //设置上墙的长度宽度尺寸
           upWall.size=new Vector2(width,1);

    	

    }
}

优化
四面墙的位置和尺寸

           Vector3 tempPosition=Camera.main.ScreenToWorldPoint(new              Vector3(Screen.width,Screen.height));

           upWall.transform.position=new Vector3(0,tempPosition.y+0.5f,0);
           upWall.size=new Vector2(tempPosition.x*2,1);

    	
           downWall.transform.position=new Vector3(0,-tempPosition.y-0.5f,0);
           downWall.size=new Vector2(tempPosition.x*2,1);

           rightWall.transform.position=new Vector3(tempPosition.x+0.5f,0,0);
           rightWall.size=new Vector2(1,tempPosition.y*2);

        
           leftWall.transform.position=new Vector3(-tempPosition.x-0.5f,0,0);
           leftWall.size=new Vector2(1,tempPosition.y*2);

因为屏幕大小不确定
因此墙和player的位置和尺寸都要重新用代码生成
借用
Camera.main.ScreenToWorldPoint(new Vector3(Screen.width,Screen.height))
来转化坐标(屏幕坐标转化为世界坐标)

控制player的位置生成

gameManagerScript.cs中添加下面代码


public Transform player1;
public Transform player2;
    // Start is called before the first frame update
    void Start()
    {
        ResetWall();
        ResetPlayer();
    }

    void ResetPlayer()
    {
        Vector3 player1Position=Camera.main.ScreenToWorldPoint(new Vector3(100,Screen.height/2,0));
        player1Position.z=0;
        player1.position=player1Position;

        Vector3 player2Position=Camera.main.ScreenToWorldPoint(new Vector3(Screen.width-100,Screen.height/2,0));
        player2Position.z=0;
        player2.position=player2Position;      

    }

添加运动的小球

选中小球
给小球添加碰撞体circle collide2D
添加刚体rigidbody2D
创建新材质physics material 2D
Friction摩擦力设置为0
Bounciness弹力设置为1
刚体质量设小点0.2
Angular drug 摩擦力设置为0
重力设置为0
添加脚本ball.cs

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

public class Ball : MonoBehaviour
{
	private Rigidbody2D rigidbody2D;//声明一个刚体引用

    // Start is called before the first frame update
    void Start()
    {
        rigidbody2D=GetComponent<Rigidbody2D>();//把前面声明的对象初始化为ball的刚体对象
        int number=Random.Range(0,2);//生成随机数0,1
        if (number==1)
        {
        	rigidbody2D.AddForce(new Vector2(100,0));//是1的话,向右边运动
        }
        else
        {
        	rigidbody2D.AddForce(new Vector2(-100,0));//是0的话,向左边运动
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

目前的BUG
小球运动着运动着某一时间就会上下运动触碰不到两个平板了
或者飞就出去了

控制playe平板的侧边运动产生的摩擦对小球的影响

碰撞检测
首先,给player12加上“Player”标签
然后,写碰撞检测代码
控制小球在碰到平板player的时候速度改变

    void OnCollisionEnter2D(Collision2D col)//当小球遇到碰撞提col时,执行以下
    {
        if(col.collider.tag=="Player")//判断碰撞体是否为player
        {
        	Vector2 velocity=rigidbody2D.velocity;//获取小球速度
        	velocity.y=velocity.y+col.rigidbody.velocity.y/2;
        	rigidbody2D.velocity=velocity;//小球新的y方向速度为原始速度加上平板palyer的y方向速度的一半
        }
    }

在优化下X方向的速度
当速度小于9的时候将小球速度恢复成10,这样小球水平方向就不会越来越慢了

    void Update()
    {
    	Vector2 velocity=rigidbody2D.velocity;
    	if (velocity.x<9 && velocity.x>-9 && velocity.x!=0)
    	{
    		if(velocity.x>0)
    		{
    			velocity.x=10;
    		}
    		else
    		{
    			velocity.x=-10;

    		}
    		rigidbody2D.velocity=velocity;
    	}
    }

不过现在出现了个bug
球的速度一高就飞出去了
解决方法
把小球的rigidbody2D设置中的Collision detection设置为continues

设置画面积分UI

新建text

然后在ball脚本里检测小球碰撞左右墙的次数
碰左墙 右边玩家2加一分
碰右墙 左边一号玩家加一分
先在ball.cs的碰撞检测方法里判断小球碰到的对象名字是rightWall或者leftWall时。。。
分值处理的部分放在gameManagerScript.cs里面(用单例模式)
添加以下代码

using UnityEngine.UI;
public class gameManagerScripts : MonoBehaviour

{
      private static gameManagerScripts _instance;//单例模式

      public static gameManagerScripts Instance//单例模式
      {
        get 
        {
          return _instance;
        }
      }

     private int score1;
     private int score2;

     public static Text score1Text;
     public static Text score2Text;


    void Awake()//单例模式
    {
      _instance=this;
    }
public void ChangeScore(string wallName)
    {
      if(wallName=="leftWall")
      {
        score2++;
      }
      else if(wallName=="rightWall")
      {
        score1++;
      }

   //   Debug.Log(score1.ToString());
      //Debug.Log(score2.ToString());
      score1Text= GameObject.Find("Canvas").transform.GetChild(0).gameObject.GetComponent<Text>();

      score1Text.text=score1.ToString();
     // Debug.Log(score1Text.text);
      score2Text= GameObject.Find("Canvas").transform.GetChild(1).gameObject.GetComponent<Text>();
      
      score2Text.text=score2.ToString();
    }

ball.cs 脚本里碰撞检测器部分加入以下代码

        if(col.gameObject.name=="rightWall" || col.gameObject.name=="leftWall")
        {
        	gameManagerScripts.Instance.ChangeScore(col.gameObject.name);
        }

出现问题 得分数值score不更新
Object reference not set to an instance of an object
解决方法
初始化对象(注意获取的是Canvas的子对象)
后再复制

score1Text= GameObject.Find("Canvas").transform.GetChild(0).gameObject.GetComponent<Text>();
score1Text.text=score1.ToString();

添加音效

载入Audio文件
在player对象上添加Audio source组件,然后把音频文件click拖进AudioClip ,然后取消选中Audio on Awake
在PlayerController.cs脚本里添加下面代码

	private AudioSource audio;
    void Start()
    {
        
        rigidbody2D=GetComponent<Rigidbody2D>();
        audio=GetComponent<AudioSource>();
    }
    void OnCollisionEnter2D()
    {
    	audio.pitch=Random.Range(0.8f,1.2f);//随机产生一个数字表示语音播放的速度
    	audio.Play();
    }

在下面给两边的墙添加生效,小球碰到墙的时候产生音效
给rightWall 添加wall.cs脚本,然后添加AudioSource组件,play on awake取消勾选

    private AudioSource audio;

        // Start is called before the first frame update 
    void Start()
    {
        
        audio=GetComponent<AudioSource>();
    }
    void OnCollisionEnter2D()
    {
    	audio.pitch=Random.Range(0.8f,1.2f);
    	audio.Play();
    }
    

背景音乐的话,给GameManager添加一个AudioSource组件,吧Music.MP3拖进去,play on awake和Loop勾选,Volume设置0.8

添加游戏重置按钮

新建一个Button,手动修改text为“Reset”,在gameManagerScripts.cs脚本里添加如下方法

    public void ReSet()
    {
       GameObject.Find("Ball").SendMessage("Reset");
       ResetPlayer();


       score1=0;
       score2=0;
       score1Text= GameObject.Find("Canvas").transform.GetChild(0).gameObject.GetComponent<Text>();
       score1Text.text=score1.ToString();

       score2Text= GameObject.Find("Canvas").transform.GetChild(1).gameObject.GetComponent<Text>();
       score2Text.text=score2.ToString();


   //    Debug.Log(score1Text.text);

    }

手动将Button重命名为“ResetButton",将GameManager对象拖进On Click里,然后在On Click里选择在gameManagerScripts的ReSet()方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
故事简介丑小鸭生来就很丑,谁都不喜欢它,从小被其他鸭子欺负。它无奈离开了妈妈,拿上一把猎枪,独自流浪,风餐露宿。每当遇到各种怪物而子弹不够用时,丑小鸭只能通过自己的血肉之躯踩死怪物。路上只能靠水果和蔬菜维持体力,无聊时也能抬头数星星。翻山越岭,逢水架桥,勇闯空中栈道和独木桥,踩过蹦床,躲过电锯,钻过加农炮,坐过火箭,穿过枪林弹雨,在极度艰苦的条件下大战终极BOSS。最终,丑小鸭占领了一座豪华城堡,里面住着它心仪的白富美(其实也是个丑小鸭),它在夜色降临之前,轻轻关上门,打开灯,结束了流浪生涯,此时天空绽放绚烂的烟花,拉开幸福生活的序幕......这个故事告诉我们:只要你肯奋斗,我命由我不由天 时长课程分为上下两部,共64节课(21.1小时)其中,上部29节课(8.5小时),下部35节课(12.6小时)课程特色对初学者友好,初次遇到新技术会详细讲解全程直播,坚决不在直播外偷偷修改展示所有细节,手把手教学游戏元素完整丰富,共3张地图18个关卡代码和文档开源,github托管地址 https://github.com/sailings/DuckAdventure完善的售后支持涵盖实战中常用的知识点Physics,刚体,碰撞,弹簧体Mecanim,动画状态机,动画融合,动画层Animation,动画编辑与录制单例模式协程Dotween粒子特效射线检测键盘和移动端输入Cinemachine相机跟随,Confiner扩展UGUI常见控件,HUD屏幕自适应地图与关卡解锁关卡滑动背景滚动子弹轨迹计算音效管理场景编辑数据及上下文存储大纲丑小鸭历险记——趣味玩转unity2d游戏开发(下)  1.背景设置原理解析2.背景设置以及云彩,山,树的滚动3.游戏状态菜单4.暂停、恢复、重新开始5.主菜单的状态切换,地图选择6.地图解锁7.关卡列表展示8.关卡列表左右滑动9.关卡进入,解锁,关卡的最佳成绩设置10.通关界面UI设计以及显示11.通关界面的数值更新、加载下一关12.通关界面动画效果13.移动端输入控制14.音效(上)15.音效(下)16.场景整理与规划,总分计算,地形编辑17.关卡W1-1(丛林)18.关卡W1-219.关卡W1-320.关卡W1-421.关卡W1-522.关卡W1-623.关卡W1-724.关卡W1-825.关卡W1-926.关卡W1-1027.关卡W1-1128.关卡W1-1229.关卡W2-1(荒漠)30.关卡W2-231.关卡W2-332.关卡W3-1(冰雪)33.关卡W3-234.关卡W3-335.游戏打包、课程总结
故事简介丑小鸭生来就很丑,谁都不喜欢它,从小被其他鸭子欺负。它无奈离开了妈妈,拿上一把猎枪,独自流浪,风餐露宿。每当遇到各种怪物而子弹不够用时,丑小鸭只能通过自己的血肉之躯踩死怪物。路上只能靠水果和蔬菜维持体力,无聊时也能抬头数星星。翻山越岭,逢水架桥,勇闯空中栈道和独木桥,踩过蹦床,躲过电锯,钻过加农炮,坐过火箭,穿过枪林弹雨,在极度艰苦的条件下大战终极BOSS。最终,丑小鸭占领了一座豪华城堡,里面住着它心仪的白富美(其实也是个丑小鸭),它在夜色降临之前,轻轻关上门,打开灯,结束了流浪生涯,此时天空绽放绚烂的烟花,拉开幸福生活的序幕......这个故事告诉我们:只要你肯奋斗,我命由我不由天 时长课程分为上下两部,共64节课(21.1小时)其中,上部29节课(8.5小时),下部35节课(12.6小时)课程特色对初学者友好,初次遇到新技术会详细讲解全程直播,坚决不在直播外偷偷修改展示所有细节,手把手教学游戏元素完整丰富,共3张地图18个关卡代码和文档开源,github托管地址 https://github.com/sailings/DuckAdventure完善的售后支持涵盖实战中常用的知识点Physics,刚体,碰撞,弹簧体Mecanim,动画状态机,动画融合,动画层Animation,动画编辑与录制单例模式协程Dotween粒子特效射线检测键盘和移动端输入Cinemachine相机跟随,Confiner扩展UGUI常见控件,HUD屏幕自适应地图与关卡解锁关卡滑动背景滚动子弹轨迹计算音效管理场景编辑数据及上下文存储大纲丑小鸭历险记——趣味玩转unity2d游戏开发(上)  1.游戏简介及演示2.怎样画一匹骏马3.千里之行始于足下4.修复连续跳跃以及Jump动画融合和播放5.匍匐前进6.星星碰撞以及游戏管理中增加积分7.吃水果蔬菜、游戏结束、制作水果蔬菜预设8.相机跟随、口水怪动画9.踩死怪物10.喷火怪11.钢管怪12.飞翔的小鸟怪13.食人鱼14.从天而降怪15.落水逻辑16.空中栈道和独木桥17.蹦床和电锯18.加农炮19.强力磁铁20.坐着火箭旅行21.漫天飞舞的电锯22.枪林弹雨23.丑小鸭的反击24.定点保存25.Boss动画、移动、释放怪物、生命值管理26.Boss无敌以及特效27.Boss血条以及坠机冒烟28.Boss射击以及子弹轨道计算29.梦幻城堡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值