使用Multiplayer Networking做一个简单的多人游戏例子-3/3(Unity3D开发之二十七)
使用Multiplayer Networking做一个简单的多人游戏例子-1/3
使用Multiplayer Networking做一个简单的多人游戏例子-2/3
使用Multiplayer Networking做一个简单的多人游戏例子-3/3
上一篇中血条还没有同步到所有客户端,下面添加血条同步。主要用到[SyncVar]同步变量。
13. 网络同步血条
- 打开Health脚本
- 添加命名空间UnityEngine.Networking
using UnityEngine.Networking;
- 添加继承关系为NetworkBehaviour
public class Health : NetworkBehaviour
- 为currentHealth添加[SyncVar]
[SyncVar]
public int currentHealth = maxHealth;
- 在TakeDamage函数中增加仅在Server端执行
if (!isServer)
{
return;
}
最终Health脚本如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
{
return;
}
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}
}
此时运行测试,你会发现只有客户端的血条会变化,所以我们需要修改血条变化方法
- 打开Health脚本
- 将血条修改的代码移到新函数OnChangeHealth中
void OnChangeHealth (int currentHealth)
{
healthBar.sizeDelta = new Vector2(health, currentHealth.sizeDelta.y);
}
- 修改currentHealth的SyncVar属性
[SyncVar(hook = "OnChangeHealth")]
最终Health代码:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
}
void OnChangeHealth (int health)
{
healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
}
}
14. 死亡和再出生
这里会用到[ClientRpc],让函数在服务端调用,执行却在客户端
- 打开Health脚本
- 添加出生函数Respawn
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
// move back to zero location
transform.position = Vector3.zero;
}
}
- 修改TakeDamage函数中,currentHealth = maxHealth;
- 在服务端执行RpcRespawn();
最终Health代码如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = maxHealth;
// called on the Server, but invoked on the Clients
RpcRespawn();
}
}
void OnChangeHealth (int currentHealth )
{
healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
// move back to zero location
transform.position = Vector3.zero;
}
}
}
- 保存脚本
- Build新版本,测试
15. 增加敌人
增加敌人发射器用于创建系统玩家
- 创建一个empty GameObject
- 修改名称为“Enemy Spawner”
- 保持Enemy Spawner选中
- 添加组件Network > NetworkIdentity
- 勾选NetworkIdentity中the Server Only选中,仅在服务端中执行
- 给Enemy Spawner添加新脚本“EnemySpawner”
EnemySpawner内容如下:
using UnityEngine;
using UnityEngine.Networking;
public class EnemySpawner : NetworkBehaviour {
public GameObject enemyPrefab;
public int numberOfEnemies;
public override void OnStartServer()
{
for (int i=0; i < numberOfEnemies; i++)
{
var spawnPosition = new Vector3(
Random.Range(-8.0f, 8.0f),
0.0f,
Random.Range(-8.0f, 8.0f));
var spawnRotation = Quaternion.Euler(
0.0f,
Random.Range(0,180),
0.0f);
var enemy = (GameObject)Instantiate(enemyPrefab, spawnPosition, spawnRotation);
NetworkServer.Spawn(enemy);
}
}
}
- 保存脚本
- 回到Unity
下面开始利用Player Prefab创建Enemy
- 将Player prefab拖到场景中
- 修改Player名称为“Enemy”
- 将Enemy拖到Project面板中创建一个新的Enemy prefab预制体
- 选中Enemy
- 删除Enemy中的Gun,点击继续
- 选中Enemy
- 删除Bullet Spawn
- 移除PlayerController组件
- 修改Enemy材质为Black Material
- 修改Enemy Visor的材质为Default-Material
- Apply Enemy Prefab
- 删除场景中的Enemy Prefab
- 保存场景
将 Enemy prefab 注册到NetworkManager中
- 选中NetworkManager
- 展开Spawn Info foldout
- Registered Spawnable Prefabs点击+号
- 将Enemy prefab添加到Registered Spawnable Prefabs list
- 选中场景中的Enemy Spawner
- 将Enemy prefab拖到Enemy prefab输入框中
- 设置Number Of Enemies为4
- 保存工程
build新版本,测试
16. 销毁死亡Enemy
- 打开Health脚本
- 添加destroyOnDeath变量
- TakeDamage中判断销毁或者respawning
代码如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
public bool destroyOnDeath;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
if (destroyOnDeath)
{
Destroy(gameObject);
}
else
{
currentHealth = maxHealth;
// called on the Server, will be invoked on the Clients
RpcRespawn();
}
}
}
void OnChangeHealth (int currentHealth)
{
healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{ if (isLocalPlayer)
{
// Set the player’s position to origin
transform.position = Vector3.zero;
}
}
}
- 保存脚本,回到Unity
- 选中Enemy prefab
- 将Health中Destroy On Death 属性勾选
增加出身点位置
由于Player每次出生位置一样,我们用NetworkStartPosition来增加一个出身点
- 创建一个empty GameObject
- 修改名称为“Spawn Position 1”
- 选中Spawn Position 1
- 增加组件Network > NetworkStartPosition
- 设置Transform Position (3, 0, 0)
- 复制一份Spawn Position 1 GameObject
- 将复制这份修改名称为“Spawn Position 2”
- 选中Spawn Position 2
- 设置Transform Position (-3, 0, 0)
- 选中Network Manager
- 展开Spawn Info foldout
- 修改Player Spawn Method 为 Round Robin
设置出生点位置
- 打开Health脚本
- 增加NetworkStartPosition变量
private NetworkStartPosition[] spawnPoints;
- 增加Start方法
void Start ()
{
if (isLocalPlayer)
{
spawnPoints = FindObjectsOfType<NetworkStartPosition>();
}
}
- 修改RpcRespawn中出生点坐标
最终Health代码如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
public bool destroyOnDeath;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
private NetworkStartPosition[] spawnPoints;
void Start ()
{
if (isLocalPlayer)
{
spawnPoints = FindObjectsOfType<NetworkStartPosition>();
}
}
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
if (destroyOnDeath)
{
Destroy(gameObject);
}
else
{
currentHealth = maxHealth;
// called on the Server, invoked on the Clients
RpcRespawn();
}
}
}
void OnChangeHealth (int currentHealth )
{
healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
// Set the spawn point to origin as a default value
Vector3 spawnPoint = Vector3.zero;
// If there is a spawn point array and the array is not empty, pick one at random
if (spawnPoints != null && spawnPoints.Length > 0)
{
spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
}
// Set the player’s position to the chosen spawn point
transform.position = spawnPoint;
}
}
}
Download sample code on github
OK,以上就是全部内容。关于详细的使用请看 Networking Overview
使用Multiplayer Networking做一个简单的多人游戏例子-3/3(Unity3D开发之二十七)的更多相关文章
- 使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 ...
- 使用Multiplayer Networking做一个简单的多人游戏例子-1/3(Unity3D开发之二十五)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51006463 ...
- 使用Multiplayer Networking做一个简单的多人游戏例子-1/2
原文地址: http://blog.csdn.net/cocos2der/article/details/51006463 本文主要讲述了如何使用Multiplayer Networking开发多人游 ...
- 使用Multiplayer Networking做一个简单的多人游戏例子-1/2(换一种方法)
SynMove.cs using UnityEngine; using System.Collections; using UnityEngine.Networking; public class S ...
- 【Bugly干货分享】一起用 HTML5 Canvas 做一个简单又骚气的粒子引擎
Bugly 技术干货系列内容主要涉及移动开发方向,是由Bugly邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言 好吧,说是“粒子引擎”还是大言不 ...
- 使用React并做一个简单的to-do-list
1. 前言 说到React,我从一年之前就开始试着了解并且看了相关的入门教程,而且还买过一本<React:引领未来的用户界面开发框架 >拜读.React的轻量组件化的思想及其virtual ...
- 【 D3.js 入门系列 --- 3 】 做一个简单的图表!
前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为 ...
- 一起用HTML5 canvas做一个简单又骚气的粒子引擎
前言 好吧,说是"粒子引擎"还是大言不惭而标题党了,离真正的粒子引擎还有点远.废话少说,先看demo 本文将教会你做一个简单的canvas粒子制造器(下称引擎). 世界观 这个简单 ...
- Jmeter初步使用二--使用jmeter做一个简单的性能测试
经过上一次的初步使用,我们懂得了Jmeter的安装与初步使用的方法.现在,我们使用Jmeter做一个简单的性能测试.该次测试,提交的参数不做参数化处理,Jmeter各元件使用将在介绍在下一博文开始介绍 ...
随机推荐
- Android开发学习之路--逆向分析反编译
一般情况下我们想要了解别人的app怎么实现这个动画,这个效果的时候,总是会想到反编译一下,看下布局,看下代码实现.对,这对于有经验的玩家确实手到擒来了,但是初学者,根本就不知道怎么反编译,怎么看代 ...
- Android Studio 中设置代码块自动补齐
AS中很多提示键,并不如Eclipse中做的好,需要我们自己去自定义.这里以switch...case为例,讲解一下如何设置代码自动补全. 1.进入settings --> Editor -- ...
- Git 处理tag和branch的命令
最近想给GitHub 上的项目设置tag,可是使用GitHub Desktop,找了一圈都没找到快速设置Tag 的地方,最后只能通过终端命令来添加了. 想要查看Git 的命令,可以使用 git --h ...
- Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44171115 大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中 ...
- 高通开发笔记---yukon worknote
点击打开链接 daily buildhttp://android-ci-platform.cnbj.sonyericsson.net/job/daily_build_jb-mr2-yukon/DL-C ...
- 【美工设计 - Adobe Illustrator】基本设置 (图像显示 | 图像缩放 | 置入导出 | 标尺 | 网格 | 参考线 | 画板)
作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50232767 一. 基础操作 1. 设置图像显示效果 (1) ...
- Android实现横屏以及全屏的小技巧
分享两个安卓的实用小技巧,那就是横屏和全屏的实现. 首先是横屏的实现 首先是在清单文件中实现 <activity android:name=".MainActivity" a ...
- android开发之broadcast学习笔记
android中的广播用的太多了,今天稍微总结一下. 按注册方式分为两种: 1.静态注册广播: 静态注册广播就是在androidManifest.xml文件中注册广播,假设我们要实现这样一个效果,在一 ...
- 【翻译】Ext JS 6.2 早期访问版本发布
原文:Announcing Ext JS 6.2 Early Access 非常开心,Sencha Ext JS 6.2早期访问版本今天发布了.早期访问版本的主要目的是为了让大家进行测试并评估Ext ...
- UNIX/LINUX程序设计教程(1)-- 获取系统信息
1.主机标识 每一台机器都有一个主机名,主机名由系统管理员指定,在网络中主机名可能是一个网络域名. 函数 gethostname() 和 sethostname() 可以用来获取和设置主机 ...