Unity3D基础案例-双人乒乓

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

游戏效果预览:
玩法:两人使用W/S键,上下键来分别控制左右的挡板,当一方没有接到球时,另一方加一分

01 场景搭建

创建2D工程PingPong,并创建新场景MainScene,导入素材,完成初始场景搭建
注意工程路径最好不要有中文
注意Order in Layer可以控制sprite渲染先后顺序,数值越大,后渲染,显示在其他sprite的上面
例如:上图中间线数值为0,显示在背景数值为-1的上面

02 开发围墙

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

private void Awake()
    {
        _instance = this;
    }
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);
    }

03 开发Player

新建一个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);
        }
    }
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;
    }

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);
        }
    }

当小球碰撞到挡板后,获取上下移动的速度
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;
        }
    }

控制小球运动速度,防止其速度过低,影响游戏体验
  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;
        }
    }

05 设计分数

用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();
    }
在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);
        }
    }

06 添加音效

在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();
        }
    }
}

同理为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();
        }
    }

07 发布PC端

File-BuildSettings 点击Build完成打包,注意打包出的文件要放在同一个文件夹内

做完后,叫上你的小伙伴一起来玩吧!喜欢我的分享就关注我吧!以后会陆续分享案例教程的!

素材及工程文件百度云链接:链接:https://pan.baidu.com/s/1eT5iCcM 密码:s5w5

猜你喜欢

转载自blog.csdn.net/qq_35361471/article/details/79318164