引言:人生无处不代码,无代码处不人生。今天给大家分享双人打乒乓游戏的主要开发流程。
开发版本:unity 5.3.5f
适合人群:初学Unity者
源文件链接请见文末!
开启学习之旅吧!
游戏效果预览:

玩法:两人使用W/S键,上下键来分别控制左右的挡板,当一方没有接到球时,另一方加一分
创建2D工程PingPong,并创建新场景MainScene,导入素材,完成初始场景搭建
注意工程路径最好不要有中文

注意Order in Layer可以控制sprite渲染先后顺序,数值越大,后渲染,显示在其他sprite的上面
例如:上图中间线数值为0,显示在背景数值为-1的上面

新建四个空对象,分别添加BoxCollider2D组件,并设置父对象WallGroup

使用代码控制Collider的大小和位置,新建脚本GameManager.cs
将GameManager设置为单例模式
在我们的整个游戏生命周期当中,有很多对象从始至终有且只有一个。这个唯一的实例只需要生成一次,并且直到游戏结束才需要销毁。
单例模式一般应用于管理器类,或者是一些需要持久化存在的对象。
- private static GameManager _instance;
- public static GameManager Instance
- {
- get
- {
- return _instance;
- }
- }
-
- private void Awake()
- {
- _instance = this;
- }
csharp运行

a点为世界坐标中心点,A点为屏幕坐标中心点
新建方法ResetWallPos(),在Start()里调用一次即可
- void ResetWallPos()
- {
- //分别获取各个墙的collider组件
- _upWallBoxCollider2D = _upWall.GetComponent<BoxCollider2D>();
- _downWallBoxCollider2D = _downWall.GetComponent<BoxCollider2D>();
- _rightWallBoxCollider2D = _rightWall.GetComponent<BoxCollider2D>();
- _leftWallBoxCollider2D = _leftWall.GetComponent<BoxCollider2D>();
-
- //new Vector2(Screen.width, Screen.height) 该点是屏幕的右上角
- //Camera.main.ScreenToWorldPoint将屏幕坐标点转化为世界坐标点
- //_screenToWorldPointPos就是图中的(x,y)
- Vector3 _screenToWorldPointPos = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, Screen.height));
-
- //_screenToWorldPointPos.y + 0.5f的偏差是为了让上面的墙向上偏移0.5m,以下同理
- _upWall.transform.position = new Vector3(0, _screenToWorldPointPos.y + 0.5f, 0);
- //设置Collider的Size属性,长度为_screenToWorldPointPos.x * 2
- _upWallBoxCollider2D.size = new Vector2(_screenToWorldPointPos.x * 2, 1);
-
- _downWall.transform.position = new Vector3(0, -_screenToWorldPointPos.y - 0.5f, 0);
- _downWallBoxCollider2D.size = new Vector2(_screenToWorldPointPos.x * 2, 1);
-
- _rightWall.transform.position = new Vector3(_screenToWorldPointPos.x + 0.5f, 0, 0);
- _rightWallBoxCollider2D.size = new Vector2(1, _screenToWorldPointPos.y * 2);
-
- _leftWall.transform.position = new Vector3(-_screenToWorldPointPos.x - 0.5f, 0, 0);
- _leftWallBoxCollider2D.size = new Vector2(1, _screenToWorldPointPos.y * 2);
- }
csharp运行
新建一个2D精灵对象,标签设置为Player,设置为预制体,然后创建两个Player,即Player_Left和Player_Right

挂载Rigidbody2D和Box Collider2D组件,设置Gravity Scale为0,冻结Z轴旋转,X轴位移

Collision Detection也可以设置为continuous,防止因为速度过快而穿越player的现象
添加PlayerController.cs脚本
首先利用添加刚体速度控制挡板的上下移动
- //Public 用于外部设置控制键
- public KeyCode _upKey;
- public KeyCode _downKey;
- public float speed = 10;
-
- private void Update()
- {
- //Input.GetKey()当按键不放时,一直返回true
- //通过if else if来判断按键情况,并设置player运动状态
- if (Input.GetKey(_upKey))
- {
- //通过修改Rigidbody2D.velocity刚体速度,来模拟逐渐加速的过程,可以理解为加速度
- //该命令会使物体向Y轴上方移动
- _rigidbody2D.velocity = new Vector2(0, speed);
- }
- else if (Input.GetKey(_downKey))
- {
- //该命令会使物体向Y轴下方移动
- _rigidbody2D.velocity = new Vector2(0, -speed);
- }
- else
- {
- //不按上下键时,刚体速度设为0
- _rigidbody2D.velocity = new Vector2(0, 0);
- }
- }
csharp运行
Player上下移动地按键可以在Inspector面板设置

左边的Player设置为W/S键,右边的设置为S上下键

代码控制Player的位置,使得挡板分别位于左右两边的中间,距离边缘10 像素 距离
在GameManager.cs中添加ResetPlayer()方法,在Start()方法中调用一次
- private void ResetPlayer()
- {
- rightPlayerPos = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width - 10, Screen.height / 2));
- _rightPlayer.position = rightPlayerPos;
- leftPlayerPos = Camera.main.ScreenToWorldPoint(new Vector2(10, Screen.height / 2));
- _leftPlayer.position = leftPlayerPos;
- }
csharp运行
04 开发Ball
制作小球Ball,可以将其位置放在画面中点,并设置其标签为Ball

右键Creat一个Physics2D material ,弹性设置为1

Ball上挂载脚本Wall.cs
首先实现Ball随机左右发球,InitForce()在Start()中只调用一次
- private void InitForce()
- {
- //Random.Range随机取整值,但取不到右边的值2,可以取值0,1
- int number = Random.Range(0, 2);
- if (number == 1)
- {
- //AddForce对刚体添加一个方向的力
- //Vector2.right等于new Vector2(1,0)
- _rigidbody2D.AddForce(Vector2.right * 100);
- }
- else
- {
- _rigidbody2D.AddForce(-Vector2.right * 100);
- }
- }
csharp运行
当小球碰撞到挡板后,获取上下移动的速度
- private void OnCollisionEnter2D(Collision2D collision)
- {
- if (collision.collider.CompareTag("Player"))
- {
- //获取Ball的Rigidbody2D组件的速度
- Vector2 velocity = _rigidbody2D.velocity;
- //给Ball添加一个y轴方向的刚体速度
- //为了防止Ball速度,无限增加,减半增加
- velocity.y = velocity.y / 2f + collision.rigidbody.velocity.y /2f;
- _rigidbody2D.velocity = velocity;
- }
- }
csharp运行
控制小球运动速度,防止其速度过低,影响游戏体验
- private void Update()
- {
- Vector2 velocity = _rigidbody2D.velocity;
-
- if (velocity.x < 10 && velocity.x > -10 && velocity.x != 0)
- {
- if (velocity.x > 0)
- {
- velocity.x = 10;
- }
- else
- {
- velocity.x = -10;
- }
- _rigidbody2D.velocity = velocity;
- }
- }
csharp运行
用UGUI创建两个 Text 用来计分,需要引入命名空间using UnityEngine.UI;
在GameManager中添加以下代码
- public Text leftText;
- public Text rightText;
- private int leftScore;
- private int rightScore;
-
- public void ChangeScore(string name)
- {
- if (name == "leftWall")
- {
- rightScore++;
- }
- else if (name == "rightWall")
- {
- leftScore++;
- }
- //分数更改后,更新Text
- leftText.text = leftScore.ToString();
- rightText.text = rightScore.ToString();
- }
csharp运行
在Ball.cs中调用ChangeScore方法
- private void OnCollisionEnter2D(Collision2D collision)
- {
- if (collision.collider.CompareTag("Player"))
- {
- Vector2 velocity = _rigidbody2D.velocity;
- velocity.y = velocity.y / 2f + collision.rigidbody.velocity.y /2f;
- _rigidbody2D.velocity = velocity;
- }
- //当小球碰撞到左右两边的墙时,进行加分
- if (collision.collider.name == "rightWall" || collision.collider.name == "leftWall")
- {
- //GameManager.Instance调用Gamemanager的唯一实例
- GameManager.Instance.ChangeScore(collision.collider.name);
- }
- }
csharp运行
在MainCamera上添加组件AudioSource,audioclip设置背景音乐ChillMusic,勾选play on awake,loop选项
为四面墙添加AudioSource组件,并为AudioClip添加Click音效,挂载Wall.cs脚本
- public class Wall : MonoBehaviour
- {
- private AudioSource _audio;
- 、
- private void Start()
- {
- _audio = GetComponent<AudioSource>();
- }
-
- private void OnCollisionEnter2D(Collision2D collision)
- {
- if (collision.collider.CompareTag("Ball"))
- {
- //修改音量
- _audio.volume = 0.6f;
- //获取随机播放音效的音调
- _audio.pitch = Random.Range(0.8f, 1.2f);
- _audio.Play();
- }
- }
- }
csharp运行
同理为PlayerController.cs 添加如下方法 并添加hit音效
- //OnCollisionEnter2D方法用于碰撞检测,is trigger不能勾选
- //当发生碰撞时,将碰撞到的物体Collider信息存储在Collision中
- private void OnCollisionEnter2D(Collision2D collision)
- {
- if (collision.collider.CompareTag("Ball"))
- {
- _audio.pitch = Random.Range(0.8f, 1.2f);
- _audio.Play();
- }
- }
csharp运行
File-BuildSettings 点击Build完成打包,注意打包出的文件要放在同一个文件夹内

做完后,叫上你的小伙伴一起来玩吧!喜欢我的分享就关注我吧!以后会陆续分享案例教程的!
素材及工程文件百度云链接:链接:https://pan.baidu.com/s/1eT5iCcM 密码:s5w5