使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)
2016-03-29 17:08
861 查看
猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/51007512
使用Multiplayer Networking做一个简单的多人游戏例子-1/3
使用Multiplayer Networking做一个简单的多人游戏例子-2/3
使用Multiplayer Networking做一个简单的多人游戏例子-3/3
下面我们通过UnityEngine.Networking组件来实现玩家控制各自Player
打开PlayerController脚本
添加命名空间UnityEngine.Networking
修改MonoBehaviour为NetworkBehaviour
在Update函数中添加如下方法
最后你的PlayerController内容如下:
保存脚本
回到Unity中
选中Player prefab在Project面板中
保持Player prefab为选中状态
添加组件Network > NetworkTransform
保存工程
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/f3249273cc5989ba89272aa5ce5848fd)
NetworkTransform用于在网络中同步所有Client信息。加上isLocalPlayer判断,只让当前客户端操作。
点击LAN Host作为主机开始游戏
运行Unity,点击LAN Client作为另一个客户端加入游戏
点击各自的WASD移动各自Player
打开PlayerController脚本
添加OnStartLocalPlayer方法
最终PlayerController:
Build新的Mac版本,测试效果
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/a27d3ce91948e64f2576d0cefa992411)
关闭Mac版本,停止运行Unity,回到编辑状态
创建一个Sphere GameObject
修改名称为“Bullet”
选中Bullet对象
修改Transform (0.2, 0.2, 0.2)
添加组件Physics > Rigidbody
在Rigidbody属性中取消Use Gravity
拖拽Bullet到Project面板中,制作为Prefab
删除场景中Bullet
保存场景
下面修改PlayerController添加发射子弹
打开PlayerController脚本
添加public变量bulletPrefab
添加子弹local发射点
在Update中加入输入源
添加Fire方法
最终PlayerController如下:
保存脚本
回到Unity
下面开始针对变化过的PlayerController修改Player Prefab
将Player Prefab拖拽到场景中
保持Player prefab选中
创建一个Cylinder圆柱体作为其Child
修改Cylinder名称为“Gun”
保持Gun被选中
移除Capsule Collider组件
设置Transform Position (0.5, 0.0, 0.5)
设置Transform Rotation (90.0, 0.0, 0.0)
设置Transform Scale (0.25, 0.5, 0.25)
设置Material为Black Material
最后Player效果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/eca227441049a4c95794387411ae6899)
保持Player选中状态
创建一个empty GameObject作为Child
修改empty GameObject名称为“Bullet Spawn”
设置Bullet Spawn Position (0.5, 0.0, 1.0)
主要是将子弹发射点Bullet Spawn设置到枪口处
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/063c02333ea55f4ce8700f56d754eb60)
保持Player Prefab选中
将Bullet prefab拖到PlayerController中的Bullet Prefab 框
将Player的Child Bullet Spawn拖到PlayerController中的Bullet Spawn 框
保存工程
Build新的Mac版本,并测试
你会发现空格键可以在各自场景中发射子弹,但是子弹没有出现在对方场景中。
关闭Mac版本
停止Unity,回到编辑模式
选中Bullet prefab在Project面板中
保存Bullet prefab选中
添加组件Network > NetworkIdentity
添加组件Network > NetworkTransform
设置NetworkTransform中Network Send Rate为0
子弹不会中途改变方向,所以我们不需要每帧更新位置,每个客户端自己计算Bullet坐标信息,所以将Network Send Rate设置为0,网络不需要同步坐标信息。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/23d26644db11a7c55e98073b75eb8284)
选中NetworkManager在Hierarchy面板中
保持NetworkManager选中
展开Spawn Info
点击Registered Spawnable Prefabs右下角+
将Bullet Prefab加入到Registered Spawnable Prefabs中
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/7f5789909ef1a15825ed2770ea461089)
打开PlayerController脚本
注意[Command]可以声明一个函数可以本客户端调用,但是会在服务端(主机)执行。
添加[Command]给Fire函数
修改Fire函数名称为“CmdFire”
Update函数中修改调用为CmdFire
在CmdFire函数中添加NetworkServer.Spawn方法来创建bullet
最终PlayerController如下:
保存脚本
回到Unity
Build新版本Mac,测试
此时应该可以看到子弹同步到了每个玩家场景中
关闭Mac版本
停止运行Unity,回到编辑模式
打开Bullet脚本
添加碰撞函数
此时子弹碰撞到Player之后自动销毁
添加玩家生命值
- 给Player prefab添加一个新脚本“Health”
Health脚本如下:
保存脚本
在Bullet中增加击中受伤
修改Bullet中的OnCollisionEnter函数
添加一个简易的玩家头顶血条
在场中中创建一个UI Image
修改Canvas名称为“Healthbar Canvas”
修改Image名称为“Background”
保存Background选中
设置RectTransform Width 100
设置RectTransform Height 10
修改Source Image 为 built-in InputFieldBackground
修改 Image Color 为红色
不要修改Background的中心点和锚点
复制一份Background
修改复制出来的Background名称为Foreground
将Foreground设置为Background的Child
将Player prefab拖到场景中
将Healthbar Canvas拖到Player中作为Child
整个Player结构如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/9023926b276ceeda7f0d425b3ffa7878)
选中Foreground
设置Foreground Image为绿色
将Foreground 中心点和锚点修改为Middle Left(用于血条从左到右填充)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/328a4112bcddf0f8ba48a62525cb1be1)
选中Healthbar Canvas
点击RectTransform设置按钮(小齿轮)中的Reset
设置RectTransform Scale (0.01, 0.01, 0.01)
设置RectTransform Position (0.0, 1.5, 0.0)
选中Player,点击apply,保存Player Prefab
保存场景
修改Health脚本,控制血条
最终Health脚本如下:
保存脚本
回到Unity
保持Player选中
将Foreground拖到Healthbar输入框中
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/26e6e0fb7775873171540f493c89dfbb)
apply Player prefab
删除场景中的Player
保存场景
最后,修改Healthbar永远朝向主摄像机
- 给Player prefab中的Healthbar Canvas添加新脚本“Billboard”
Billboard脚本如下:
编译新Mac版本,测试
你会发现血条只在本地变化了,没有同步到所有玩家。
原文地址: http://blog.csdn.net/cocos2der/article/details/51007512
使用Multiplayer Networking做一个简单的多人游戏例子-1/3
使用Multiplayer Networking做一个简单的多人游戏例子-2/3
使用Multiplayer Networking做一个简单的多人游戏例子-3/3
7. 在网络中控制Player移动
上一篇中,玩家操作移动会同时控制同屏内的所有Player,且只有自己的屏幕生效。因为咱们还没有同步Transform信息。下面我们通过UnityEngine.Networking组件来实现玩家控制各自Player
打开PlayerController脚本
添加命名空间UnityEngine.Networking
using UnityEngine.Networking;
修改MonoBehaviour为NetworkBehaviour
public class PlayerController : NetworkBehaviour
在Update函数中添加如下方法
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);
}
}
保存脚本
回到Unity中
选中Player prefab在Project面板中
保持Player prefab为选中状态
添加组件Network > NetworkTransform
保存工程
NetworkTransform用于在网络中同步所有Client信息。加上isLocalPlayer判断,只让当前客户端操作。
8. 测试网络中多玩家移动
同样Build一个Mac standalone application作为主机运行点击LAN Host作为主机开始游戏
运行Unity,点击LAN Client作为另一个客户端加入游戏
点击各自的WASD移动各自Player
9. 区分各自的Player
上面中两个Player外观一致,我们修改自己Player的颜色打开PlayerController脚本
添加OnStartLocalPlayer方法
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; }
}
Build新的Mac版本,测试效果
关闭Mac版本,停止运行Unity,回到编辑状态
10. 给Player添加射击武器
创建子弹创建一个Sphere GameObject
修改名称为“Bullet”
选中Bullet对象
修改Transform (0.2, 0.2, 0.2)
添加组件Physics > Rigidbody
在Rigidbody属性中取消Use Gravity
拖拽Bullet到Project面板中,制作为Prefab
删除场景中Bullet
保存场景
下面修改PlayerController添加发射子弹
打开PlayerController脚本
添加public变量bulletPrefab
public GameObject bulletPrefab;
添加子弹local发射点
public Transform bulletSpawn;
在Update中加入输入源
if (Input.GetKeyDown(KeyCode.Space)) { Fire(); }
添加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;
}
}
保存脚本
回到Unity
下面开始针对变化过的PlayerController修改Player Prefab
将Player Prefab拖拽到场景中
保持Player prefab选中
创建一个Cylinder圆柱体作为其Child
修改Cylinder名称为“Gun”
保持Gun被选中
移除Capsule Collider组件
设置Transform Position (0.5, 0.0, 0.5)
设置Transform Rotation (90.0, 0.0, 0.0)
设置Transform Scale (0.25, 0.5, 0.25)
设置Material为Black Material
最后Player效果:
保持Player选中状态
创建一个empty GameObject作为Child
修改empty GameObject名称为“Bullet Spawn”
设置Bullet Spawn Position (0.5, 0.0, 1.0)
主要是将子弹发射点Bullet Spawn设置到枪口处
保持Player Prefab选中
将Bullet prefab拖到PlayerController中的Bullet Prefab 框
将Player的Child Bullet Spawn拖到PlayerController中的Bullet Spawn 框
保存工程
Build新的Mac版本,并测试
你会发现空格键可以在各自场景中发射子弹,但是子弹没有出现在对方场景中。
关闭Mac版本
停止Unity,回到编辑模式
11. 增加多人射击
下面我们会将Bullet prefab注册到NetworkManager选中Bullet prefab在Project面板中
保存Bullet prefab选中
添加组件Network > NetworkIdentity
添加组件Network > NetworkTransform
设置NetworkTransform中Network Send Rate为0
子弹不会中途改变方向,所以我们不需要每帧更新位置,每个客户端自己计算Bullet坐标信息,所以将Network Send Rate设置为0,网络不需要同步坐标信息。
选中NetworkManager在Hierarchy面板中
保持NetworkManager选中
展开Spawn Info
点击Registered Spawnable Prefabs右下角+
将Bullet Prefab加入到Registered Spawnable Prefabs中
打开PlayerController脚本
注意[Command]可以声明一个函数可以本客户端调用,但是会在服务端(主机)执行。
添加[Command]给Fire函数
修改Fire函数名称为“CmdFire”
[Command] void CmdFire()
Update函数中修改调用为CmdFire
CmdFire();
在CmdFire函数中添加NetworkServer.Spawn方法来创建bullet
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;
}
}
保存脚本
回到Unity
Build新版本Mac,测试
此时应该可以看到子弹同步到了每个玩家场景中
关闭Mac版本
停止运行Unity,回到编辑模式
添加玩家生命值
给Bullet Prefab添加一个新脚本“Bullet”打开Bullet脚本
添加碰撞函数
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中增加击中受伤
修改Bullet中的OnCollisionEnter函数
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); } }
添加一个简易的玩家头顶血条
在场中中创建一个UI Image
修改Canvas名称为“Healthbar Canvas”
修改Image名称为“Background”
保存Background选中
设置RectTransform Width 100
设置RectTransform Height 10
修改Source Image 为 built-in InputFieldBackground
修改 Image Color 为红色
不要修改Background的中心点和锚点
复制一份Background
修改复制出来的Background名称为Foreground
将Foreground设置为Background的Child
将Player prefab拖到场景中
将Healthbar Canvas拖到Player中作为Child
整个Player结构如下:
选中Foreground
设置Foreground Image为绿色
将Foreground 中心点和锚点修改为Middle Left(用于血条从左到右填充)
选中Healthbar Canvas
点击RectTransform设置按钮(小齿轮)中的Reset
设置RectTransform Scale (0.01, 0.01, 0.01)
设置RectTransform Position (0.0, 1.5, 0.0)
选中Player,点击apply,保存Player Prefab
保存场景
修改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); } }
保存脚本
回到Unity
保持Player选中
将Foreground拖到Healthbar输入框中
apply Player prefab
删除场景中的Player
保存场景
最后,修改Healthbar永远朝向主摄像机
- 给Player prefab中的Healthbar Canvas添加新脚本“Billboard”
Billboard脚本如下:
using UnityEngine; using System.Collections; public class Billboard : MonoBehaviour { void Update () { transform.LookAt(Camera.main.transform); } }
编译新Mac版本,测试
你会发现血条只在本地变化了,没有同步到所有玩家。
相关文章推荐
- Kinect结合Unity3D引擎开发体感游戏(一)
- Unity3D中脚本的执行顺序和编译顺序
- Unity3D动态对象优化代码分享
- Unity3D获取当前键盘按键及Unity3D鼠标、键盘的基本操作
- Unity3d获取系统时间
- unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk)
- Unity3D游戏引擎实现在Android中打开WebView的实例
- unity3d调用手机或电脑摄像头
- Unity3d发布IOS9应用时出现中文乱码的解决方法
- 分享一个开源的网络游戏服务器架构—HouHai
- Unity3D插件详细评测及教学下载
- Unity3D上路_01-2D太空射击游戏
- Unity3D上路_02-第一视角射击游戏
- Unity3D上路_03-塔防游戏
- Unity3D上路_04-基础资源介绍
- Unity3D上路_05-网络相关