猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/51007512
使用Multiplayer Networking做一个简单的多人游戏例子-1/3
使用Multiplayer Networking做一个简单的多人游戏例子-2/3
使用Multiplayer Networking做一个简单的多人游戏例子-3/3
上一篇中,玩家操作移动会同时控制同屏内的所有Player,且只有自己的屏幕生效。因为咱们还没有同步Transform信息。
下面我们通过UnityEngine.Networking组件来实现玩家控制各自Player
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour
if (!isLocalPlayer)
{
return;
}
最后你的PlayerController内容如下:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour
{
void Update()
{
if (!isLocalPlayer)
{
return;
}
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, z);
}
}
NetworkTransform用于在网络中同步所有Client信息。加上isLocalPlayer判断,只让当前客户端操作。
上面中两个Player外观一致,我们修改自己Player的颜色
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.blue;
}
最终PlayerController:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour
{
void Update()
{
if (!isLocalPlayer)
{
return;
}
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, z);
}
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.blue;
}
}
创建子弹
下面修改PlayerController添加发射子弹
public GameObject bulletPrefab;
public Transform bulletSpawn;
if (Input.GetKeyDown(KeyCode.Space))
{ Fire(); }
void Fire()
{
// Create the Bullet from the Bullet Prefab
var bullet = (GameObject)Instantiate (
bulletPrefab,
bulletSpawn.position,
bulletSpawn.rotation);
// Add velocity to the bullet
bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;
// Destroy the bullet after 2 seconds
Destroy(bullet, 2.0f);
}
最终PlayerController如下:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour
{
public GameObject bulletPrefab;
public Transform bulletSpawn;
void Update()
{
if (!isLocalPlayer)
{
return;
}
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, z);
if (Input.GetKeyDown(KeyCode.Space))
{
Fire();
}
}
void Fire()
{
// Create the Bullet from the Bullet Prefab
var bullet = (GameObject)Instantiate(
bulletPrefab,
bulletSpawn.position,
bulletSpawn.rotation);
// Add velocity to the bullet
bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;
// Destroy the bullet after 2 seconds
Destroy(bullet, 2.0f);
}
public override void OnStartLocalPlayer ()
{
GetComponent<MeshRenderer>().material.color = Color.blue;
}
}
下面开始针对变化过的PlayerController修改Player Prefab
最后Player效果:
你会发现空格键可以在各自场景中发射子弹,但是子弹没有出现在对方场景中。
下面我们会将Bullet prefab注册到NetworkManager
子弹不会中途改变方向,所以我们不需要每帧更新位置,每个客户端自己计算Bullet坐标信息,所以将Network Send Rate设置为0,网络不需要同步坐标信息。
打开PlayerController脚本
注意[Command]可以声明一个函数可以本客户端调用,但是会在服务端(主机)执行。
[Command]
void CmdFire()
CmdFire();
NetworkServer.Spawn(bullet);
最终PlayerController如下:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour
{
public GameObject bulletPrefab;
public Transform bulletSpawn;
void Update()
{
if (!isLocalPlayer)
{
return;
}
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, z);
if (Input.GetKeyDown(KeyCode.Space))
{
CmdFire();
}
}
// This [Command] code is called on the Client …
// … but it is run on the Server!
[Command]
void CmdFire()
{
// Create the Bullet from the Bullet Prefab
var bullet = (GameObject)Instantiate(
bulletPrefab,
bulletSpawn.position,
bulletSpawn.rotation);
// Add velocity to the bullet
bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;
// Spawn the bullet on the Clients
NetworkServer.Spawn(bullet);
// Destroy the bullet after 2 seconds
Destroy(bullet, 2.0f);
}
public override void OnStartLocalPlayer ()
{
GetComponent<MeshRenderer>().material.color = Color.blue;
}
}
此时应该可以看到子弹同步到了每个玩家场景中
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
void OnCollisionEnter(Collision collision)
{
Destroy(gameObject);
}
}
此时子弹碰撞到Player之后自动销毁
添加玩家生命值
- 给Player prefab添加一个新脚本“Health”
Health脚本如下:
using UnityEngine;
public class Health : MonoBehaviour
{
public const int maxHealth = 100;
public int currentHealth = maxHealth;
public void TakeDamage(int amount)
{
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
}
}
在Bullet中增加击中受伤
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
void OnCollisionEnter(Collision collision)
{
var hit = collision.gameObject;
var health = hit.GetComponent<Health>();
if (health != null)
{
health.TakeDamage(10);
}
Destroy(gameObject);
}
}
添加一个简易的玩家头顶血条
将Healthbar Canvas拖到Player中作为Child
整个Player结构如下:
选中Foreground
将Foreground 中心点和锚点修改为Middle Left(用于血条从左到右填充)
选中Healthbar Canvas
修改Health脚本,控制血条
最终Health脚本如下:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class Health : MonoBehaviour {
public const int maxHealth = 100;
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}
}
最后,修改Healthbar永远朝向主摄像机
- 给Player prefab中的Healthbar Canvas添加新脚本“Billboard”
Billboard脚本如下:
using UnityEngine;
using System.Collections;
public class Billboard : MonoBehaviour {
void Update () {
transform.LookAt(Camera.main.transform);
}
}
你会发现血条只在本地变化了,没有同步到所有玩家。