3d学习笔记(十)——多人联机游戏

多人联机游戏

实验要求

利用unity中的多人网络组件与API,设计一个多人联机的游戏

实验内容

本次实验是在课堂的基础上,进行设计的。

  • 游戏内容:联机的几方,可以在系统敌人发射的子弹下进行移动,以期望存活时间最长
  • 游戏视频链接:百度云盘链接
  • 游戏代码下载:CSDN下载链接
  • 第三点中的游戏代码下载之后,直接复制粘贴到unity3d新建项目的assets文件夹中即可进行操作

实验操作

游戏对象

  • 首先需要一个空对象作为NetworkManager
    这里写图片描述
  • 其次是一个Plane
    这里写图片描述
  • 需要一个空对象来作为生产敌人的工厂
    这里写图片描述
  • 需要两个空对象作为游戏角色死亡后复活的点
    这里写图片描述
    这里写图片描述
  • 需要游戏对象预制
    这里写图片描述
    这里写图片描述
  • 需要子弹的预制
    这里写图片描述
    这里写图片描述
  • 需要敌人的预制
    这里写图片描述
    这里写图片描述

游戏脚本

  • PlayerMove脚本
using UnityEngine;
using UnityEngine.Networking;

public class PlayerMove : NetworkBehaviour
{
    public GameObject bulletPrefab;

    public override void OnStartLocalPlayer()
    {
        GetComponent<MeshRenderer>().material.color = Color.red;
    }

    [Command]
    void CmdFire()
    {
        // This [Command] code is run on the server!

        // create the bullet object locally
        var bullet = (GameObject)Instantiate(
             bulletPrefab,
             transform.position - transform.forward,
             Quaternion.identity);

        bullet.GetComponent<Rigidbody>().velocity = -transform.forward * 4;

        // spawn the bullet on the clients
        NetworkServer.Spawn(bullet);

        // when the bullet is destroyed on the server it will automaticaly be destroyed on clients
        Destroy(bullet, 2.0f);
    }

    void Update()
    {
        if (!isLocalPlayer)
            return;

        var x = Input.GetAxis("Horizontal") * 0.1f;
        var z = Input.GetAxis("Vertical") * 0.1f;

        transform.Translate(x, 0, z);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Command function is called from the client, but invoked on the server
            CmdFire();
        }
    }
}
  • Bullet脚本
using UnityEngine;

public class Bullet : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        var hit = collision.gameObject;
        var hitCombat = hit.GetComponent<Combat>();
        if (hitCombat != null)
        {
            hitCombat.TakeDamage(10);
            Destroy(gameObject);
        }
    }
}
  • Combat脚本
using UnityEngine;
using UnityEngine.Networking;

public class Combat : NetworkBehaviour
{
    public const int maxHealth = 100;
    public bool destroyOnDeath;

    [SyncVar]
    public int health = maxHealth;

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;

        health -= amount;
        if (health <= 0)
        {
            if (destroyOnDeath)
            {
                Destroy(gameObject);
            }
            else
            {
                health = maxHealth;

                // called on the server, will be invoked on the clients
                RpcRespawn();
            }
        }
    }

    [ClientRpc]
    void RpcRespawn()
    {
        if (isLocalPlayer)
        {
            // move back to zero location
            transform.position = Vector3.zero;
        }
    }
}
  • HealthBar脚本
using UnityEngine;
using System.Collections;

public class HealthBar : MonoBehaviour
{
    GUIStyle healthStyle;
    GUIStyle backStyle;
    Combat combat;

    void Awake()
    {
        combat = GetComponent<Combat>();
    }

    void OnGUI()
    {
        InitStyles();

        // Draw a Health Bar

        Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);

        // draw health bar background
        GUI.color = Color.grey;
        GUI.backgroundColor = Color.grey;
        GUI.Box(new Rect(pos.x - 26, Screen.height - pos.y + 20, Combat.maxHealth / 2, 7), ".", backStyle);

        // draw health bar amount
        GUI.color = Color.green;
        GUI.backgroundColor = Color.green;
        GUI.Box(new Rect(pos.x - 25, Screen.height - pos.y + 21, combat.health / 2, 5), ".", healthStyle);
    }

    void InitStyles()
    {
        if (healthStyle == null)
        {
            healthStyle = new GUIStyle(GUI.skin.box);
            healthStyle.normal.background = MakeTex(2, 2, new Color(0f, 1f, 0f, 1.0f));
        }

        if (backStyle == null)
        {
            backStyle = new GUIStyle(GUI.skin.box);
            backStyle.normal.background = MakeTex(2, 2, new Color(0f, 0f, 0f, 1.0f));
        }
    }

    Texture2D MakeTex(int width, int height, Color col)
    {
        Color[] pix = new Color[width * height];
        for (int i = 0; i < pix.Length; ++i)
        {
            pix[i] = col;
        }
        Texture2D result = new Texture2D(width, height);
        result.SetPixels(pix);
        result.Apply();
        return result;
    }
}
  • EnemyFire脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class EnemyFire : NetworkBehaviour
{

    public GameObject bulletPrefab;
    // Use this for initialization
    private int num = 0;

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

        num++;
        num = num % 100;

        if(num == 0) CmdFire();
    }

    [Command]
    void CmdFire()
    {
        // This [Command] code is run on the server!

        // create the bullet object locally
        var bullet = (GameObject)Instantiate(
             bulletPrefab,
             transform.position - transform.forward,
             Quaternion.identity);

        bullet.GetComponent<Rigidbody>().velocity = -transform.forward * 4;

        //behind
        var bullet1 = (GameObject)Instantiate(
             bulletPrefab,
             transform.position + transform.forward,
             Quaternion.identity);

        bullet1.GetComponent<Rigidbody>().velocity = transform.forward * 4;

        //left
       var bullet2 = (GameObject)Instantiate(
             bulletPrefab,
             transform.position - transform.right,
             Quaternion.identity);

        bullet2.GetComponent<Rigidbody>().velocity = -transform.right * 4;

        //right
        var bullet3 = (GameObject)Instantiate(
             bulletPrefab,
             transform.position + transform.right,
             Quaternion.identity);

        bullet3.GetComponent<Rigidbody>().velocity = transform.right * 4;

        // spawn the bullet on the clients
        NetworkServer.Spawn(bullet);
        NetworkServer.Spawn(bullet1);
        NetworkServer.Spawn(bullet2);
        NetworkServer.Spawn(bullet3);

        // when the bullet is destroyed on the server it will automaticaly be destroyed on clients
        Destroy(bullet, 2.0f);
        Destroy(bullet1, 2.0f);
        Destroy(bullet2, 2.0f);
        Destroy(bullet3, 2.0f);
    }
}
  • EnemySpawner脚本
using UnityEngine;
using UnityEngine.Networking;

public class EnemySpawner : NetworkBehaviour
{

    public GameObject enemyPrefab;
    public int numEnemies;

    public override void OnStartServer()
    {
        for (int i = 0; i < numEnemies; i++)
        {
            var pos = new Vector3(
                Random.Range(-8.0f, 8.0f),
                0.2f,
                Random.Range(-8.0f, 8.0f)
                );

            //var rotation = Quaternion.Euler(Random.Range(0, 180), Random.Range(0, 180), Random.Range(0, 180));
            var rotation = Quaternion.Euler(0,0,0);

            var enemy = (GameObject)Instantiate(enemyPrefab, pos, rotation);
            NetworkServer.Spawn(enemy);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36312878/article/details/80820229
今日推荐