新建一个图层
选中bg这一对象 点击右上角Layer AddLayer 新建一个图层将Layer设置为新建的图层
在scence 中添加player png 设置合适大小 添加BoxCollide 2D 设置合适size
控制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))
来转化坐标(屏幕坐标转化为世界坐标)
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
小球运动着运动着某一时间就会上下运动触碰不到两个平板了
或者飞就出去了
碰撞检测
首先,给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
新建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()方法。